blob: 0da3dfa3150a2e5a29f74b8d3b4d7deb076113d6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2/* ips.c -- driver for the Adaptec / IBM ServeRAID controller */
3/* */
4/* Written By: Keith Mitchell, IBM Corporation */
5/* Jack Hammer, Adaptec, Inc. */
6/* David Jeffery, Adaptec, Inc. */
7/* */
8/* Copyright (C) 2000 IBM Corporation */
9/* Copyright (C) 2002,2003 Adaptec, Inc. */
10/* */
11/* This program is free software; you can redistribute it and/or modify */
12/* it under the terms of the GNU General Public License as published by */
13/* the Free Software Foundation; either version 2 of the License, or */
14/* (at your option) any later version. */
15/* */
16/* This program is distributed in the hope that it will be useful, */
17/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19/* GNU General Public License for more details. */
20/* */
21/* NO WARRANTY */
22/* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR */
23/* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT */
24/* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, */
25/* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is */
26/* solely responsible for determining the appropriateness of using and */
27/* distributing the Program and assumes all risks associated with its */
28/* exercise of rights under this Agreement, including but not limited to */
29/* the risks and costs of program errors, damage to or loss of data, */
30/* programs or equipment, and unavailability or interruption of operations. */
31/* */
32/* DISCLAIMER OF LIABILITY */
33/* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY */
34/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
35/* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND */
36/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR */
37/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE */
38/* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED */
39/* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES */
40/* */
41/* You should have received a copy of the GNU General Public License */
42/* along with this program; if not, write to the Free Software */
43/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
44/* */
45/* Bugs/Comments/Suggestions about this driver should be mailed to: */
46/* ipslinux@adaptec.com */
47/* */
48/* For system support issues, contact your local IBM Customer support. */
49/* Directions to find IBM Customer Support for each country can be found at: */
50/* http://www.ibm.com/planetwide/ */
51/* */
52/*****************************************************************************/
53
54/*****************************************************************************/
55/* Change Log */
56/* */
57/* 0.99.02 - Breakup commands that are bigger than 8 * the stripe size */
58/* 0.99.03 - Make interrupt routine handle all completed request on the */
59/* adapter not just the first one */
60/* - Make sure passthru commands get woken up if we run out of */
61/* SCBs */
62/* - Send all of the commands on the queue at once rather than */
63/* one at a time since the card will support it. */
64/* 0.99.04 - Fix race condition in the passthru mechanism -- this required */
65/* the interface to the utilities to change */
66/* - Fix error recovery code */
67/* 0.99.05 - Fix an oops when we get certain passthru commands */
68/* 1.00.00 - Initial Public Release */
69/* Functionally equivalent to 0.99.05 */
70/* 3.60.00 - Bump max commands to 128 for use with firmware 3.60 */
71/* - Change version to 3.60 to coincide with release numbering. */
72/* 3.60.01 - Remove bogus error check in passthru routine */
73/* 3.60.02 - Make DCDB direction based on lookup table */
74/* - Only allow one DCDB command to a SCSI ID at a time */
75/* 4.00.00 - Add support for ServeRAID 4 */
76/* 4.00.01 - Add support for First Failure Data Capture */
77/* 4.00.02 - Fix problem with PT DCDB with no buffer */
78/* 4.00.03 - Add alternative passthru interface */
79/* - Add ability to flash BIOS */
80/* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */
81/* 4.00.05 - Remove wish_block from init routine */
82/* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */
83/* 2.3.18 and later */
84/* - Sync with other changes from the 2.3 kernels */
85/* 4.00.06 - Fix timeout with initial FFDC command */
86/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@infradead.org> */
87/* 4.10.00 - Add support for ServeRAID 4M/4L */
88/* 4.10.13 - Fix for dynamic unload and proc file system */
89/* 4.20.03 - Rename version to coincide with new release schedules */
90/* Performance fixes */
91/* Fix truncation of /proc files with cat */
92/* Merge in changes through kernel 2.4.0test1ac21 */
93/* 4.20.13 - Fix some failure cases / reset code */
94/* - Hook into the reboot_notifier to flush the controller cache */
95/* 4.50.01 - Fix problem when there is a hole in logical drive numbering */
96/* 4.70.09 - Use a Common ( Large Buffer ) for Flashing from the JCRM CD */
97/* - Add IPSSEND Flash Support */
98/* - Set Sense Data for Unknown SCSI Command */
99/* - Use Slot Number from NVRAM Page 5 */
100/* - Restore caller's DCDB Structure */
101/* 4.70.12 - Corrective actions for bad controller ( during initialization )*/
102/* 4.70.13 - Don't Send CDB's if we already know the device is not present */
103/* - Don't release HA Lock in ips_next() until SC taken off queue */
104/* - Unregister SCSI device in ips_release() */
105/* 4.70.15 - Fix Breakup for very large ( non-SG ) requests in ips_done() */
106/* 4.71.00 - Change all memory allocations to not use GFP_DMA flag */
107/* Code Clean-Up for 2.4.x kernel */
108/* 4.72.00 - Allow for a Scatter-Gather Element to exceed MAX_XFER Size */
109/* 4.72.01 - I/O Mapped Memory release ( so "insmod ips" does not Fail ) */
110/* - Don't Issue Internal FFDC Command if there are Active Commands */
111/* - Close Window for getting too many IOCTL's active */
112/* 4.80.00 - Make ia64 Safe */
113/* 4.80.04 - Eliminate calls to strtok() if 2.4.x or greater */
114/* - Adjustments to Device Queue Depth */
115/* 4.80.14 - Take all semaphores off stack */
116/* - Clean Up New_IOCTL path */
117/* 4.80.20 - Set max_sectors in Scsi_Host structure ( if >= 2.4.7 kernel ) */
118/* - 5 second delay needed after resetting an i960 adapter */
119/* 4.80.26 - Clean up potential code problems ( Arjan's recommendations ) */
120/* 4.90.01 - Version Matching for FirmWare, BIOS, and Driver */
121/* 4.90.05 - Use New PCI Architecture to facilitate Hot Plug Development */
122/* 4.90.08 - Increase Delays in Flashing ( Trombone Only - 4H ) */
123/* 4.90.08 - Data Corruption if First Scatter Gather Element is > 64K */
124/* 4.90.11 - Don't actually RESET unless it's physically required */
125/* - Remove unused compile options */
126/* 5.00.01 - Sarasota ( 5i ) adapters must always be scanned first */
127/* - Get rid on IOCTL_NEW_COMMAND code */
128/* - Add Extended DCDB Commands for Tape Support in 5I */
129/* 5.10.12 - use pci_dma interfaces, update for 2.5 kernel changes */
130/* 5.10.15 - remove unused code (sem, macros, etc.) */
131/* 5.30.00 - use __devexit_p() */
132/* 6.00.00 - Add 6x Adapters and Battery Flash */
133/* 6.10.00 - Remove 1G Addressing Limitations */
134/* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */
135/* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */
Jack Hammerc1a15462005-07-26 10:20:33 -0400136/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */
138/* - Fix sort order of 7k */
139/* - Remove 3 unused "inline" functions */
Jack Hammerc1a15462005-07-26 10:20:33 -0400140/* 7.12.xx - Use STATIC functions whereever possible */
141/* - Clean up deprecated MODULE_PARM calls */
Jack Hammera60768e2005-11-03 09:46:00 -0500142/* 7.12.05 - Remove Version Matching per IBM request */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143/*****************************************************************************/
144
145/*
146 * Conditional Compilation directives for this driver:
147 *
148 * IPS_DEBUG - Turn on debugging info
149 *
150 * Parameters:
151 *
152 * debug:<number> - Set debug level to <number>
153 * NOTE: only works when IPS_DEBUG compile directive is used.
154 * 1 - Normal debug messages
155 * 2 - Verbose debug messages
156 * 11 - Method trace (non interrupt)
157 * 12 - Method trace (includes interrupt)
158 *
159 * noi2o - Don't use I2O Queues (ServeRAID 4 only)
160 * nommap - Don't use memory mapped I/O
161 * ioctlsize - Initial size of the IOCTL buffer
162 */
163
164#include <asm/io.h>
165#include <asm/byteorder.h>
166#include <asm/page.h>
167#include <linux/stddef.h>
168#include <linux/version.h>
169#include <linux/string.h>
170#include <linux/errno.h>
171#include <linux/kernel.h>
172#include <linux/ioport.h>
173#include <linux/slab.h>
174#include <linux/delay.h>
175#include <linux/pci.h>
176#include <linux/proc_fs.h>
177#include <linux/reboot.h>
178#include <linux/interrupt.h>
179
180#include <linux/blkdev.h>
181#include <linux/types.h>
Matthias Gehre910638a2006-03-28 01:56:48 -0800182#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
184#include <scsi/sg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185#include "scsi.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186#include <scsi/scsi_host.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
188#include "ips.h"
189
190#include <linux/module.h>
191
192#include <linux/stat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194#include <linux/spinlock.h>
195#include <linux/init.h>
196
197#include <linux/smp.h>
198
199#ifdef MODULE
200static char *ips = NULL;
201module_param(ips, charp, 0);
202#endif
203
204/*
205 * DRIVER_VER
206 */
Bernhard Walle8c8fdc52007-09-22 21:55:19 +0200207#define IPS_VERSION_HIGH IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING
208#define IPS_VERSION_LOW "." IPS_VER_BUILD_STRING " "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
211#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
212#endif
213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214#define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
be7db052005-04-17 15:26:13 -0500215 DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 PCI_DMA_BIDIRECTIONAL : \
be7db052005-04-17 15:26:13 -0500217 scb->scsi_cmd->sc_data_direction)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219#ifdef IPS_DEBUG
220#define METHOD_TRACE(s, i) if (ips_debug >= (i+10)) printk(KERN_NOTICE s "\n");
221#define DEBUG(i, s) if (ips_debug >= i) printk(KERN_NOTICE s "\n");
222#define DEBUG_VAR(i, s, v...) if (ips_debug >= i) printk(KERN_NOTICE s "\n", v);
223#else
224#define METHOD_TRACE(s, i)
225#define DEBUG(i, s)
226#define DEBUG_VAR(i, s, v...)
227#endif
228
229/*
230 * Function prototypes
231 */
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100232static int ips_detect(struct scsi_host_template *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233static int ips_release(struct Scsi_Host *);
Henne1516b552006-10-02 14:56:23 +0200234static int ips_eh_abort(struct scsi_cmnd *);
235static int ips_eh_reset(struct scsi_cmnd *);
236static int ips_queue(struct scsi_cmnd *, void (*)(struct scsi_cmnd *));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237static const char *ips_info(struct Scsi_Host *);
David Howells7d12e782006-10-05 14:55:46 +0100238static irqreturn_t do_ipsintr(int, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239static int ips_hainit(ips_ha_t *);
240static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
241static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
242static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
243static int ips_online(ips_ha_t *, ips_scb_t *);
244static int ips_inquiry(ips_ha_t *, ips_scb_t *);
245static int ips_rdcap(ips_ha_t *, ips_scb_t *);
246static int ips_msense(ips_ha_t *, ips_scb_t *);
247static int ips_reqsen(ips_ha_t *, ips_scb_t *);
248static int ips_deallocatescbs(ips_ha_t *, int);
249static int ips_allocatescbs(ips_ha_t *);
250static int ips_reset_copperhead(ips_ha_t *);
251static int ips_reset_copperhead_memio(ips_ha_t *);
252static int ips_reset_morpheus(ips_ha_t *);
253static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);
254static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);
255static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);
256static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);
257static int ips_isintr_copperhead(ips_ha_t *);
258static int ips_isintr_copperhead_memio(ips_ha_t *);
259static int ips_isintr_morpheus(ips_ha_t *);
260static int ips_wait(ips_ha_t *, int, int);
261static int ips_write_driver_status(ips_ha_t *, int);
262static int ips_read_adapter_status(ips_ha_t *, int);
263static int ips_read_subsystem_parameters(ips_ha_t *, int);
264static int ips_read_config(ips_ha_t *, int);
265static int ips_clear_adapter(ips_ha_t *, int);
266static int ips_readwrite_page5(ips_ha_t *, int, int);
267static int ips_init_copperhead(ips_ha_t *);
268static int ips_init_copperhead_memio(ips_ha_t *);
269static int ips_init_morpheus(ips_ha_t *);
270static int ips_isinit_copperhead(ips_ha_t *);
271static int ips_isinit_copperhead_memio(ips_ha_t *);
272static int ips_isinit_morpheus(ips_ha_t *);
273static int ips_erase_bios(ips_ha_t *);
274static int ips_program_bios(ips_ha_t *, char *, uint32_t, uint32_t);
275static int ips_verify_bios(ips_ha_t *, char *, uint32_t, uint32_t);
276static int ips_erase_bios_memio(ips_ha_t *);
277static int ips_program_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
278static int ips_verify_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
279static int ips_flash_copperhead(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
280static int ips_flash_bios(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
281static int ips_flash_firmware(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
282static void ips_free_flash_copperhead(ips_ha_t * ha);
283static void ips_get_bios_version(ips_ha_t *, int);
284static void ips_identify_controller(ips_ha_t *);
285static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);
286static void ips_enable_int_copperhead(ips_ha_t *);
287static void ips_enable_int_copperhead_memio(ips_ha_t *);
288static void ips_enable_int_morpheus(ips_ha_t *);
289static int ips_intr_copperhead(ips_ha_t *);
290static int ips_intr_morpheus(ips_ha_t *);
291static void ips_next(ips_ha_t *, int);
292static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
293static void ipsintr_done(ips_ha_t *, struct ips_scb *);
294static void ips_done(ips_ha_t *, ips_scb_t *);
295static void ips_free(ips_ha_t *);
296static void ips_init_scb(ips_ha_t *, ips_scb_t *);
297static void ips_freescb(ips_ha_t *, ips_scb_t *);
298static void ips_setup_funclist(ips_ha_t *);
299static void ips_statinit(ips_ha_t *);
300static void ips_statinit_memio(ips_ha_t *);
301static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
302static void ips_ffdc_reset(ips_ha_t *, int);
303static void ips_ffdc_time(ips_ha_t *);
304static uint32_t ips_statupd_copperhead(ips_ha_t *);
305static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
306static uint32_t ips_statupd_morpheus(ips_ha_t *);
307static ips_scb_t *ips_getscb(ips_ha_t *);
308static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
Henne1516b552006-10-02 14:56:23 +0200309static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310static void ips_putq_copp_tail(ips_copp_queue_t *,
311 ips_copp_wait_item_t *);
312static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
313static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
Henne1516b552006-10-02 14:56:23 +0200314static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
315static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *,
316 struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
318 ips_copp_wait_item_t *);
319static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
320
Henne1516b552006-10-02 14:56:23 +0200321static int ips_is_passthru(struct scsi_cmnd *);
322static int ips_make_passthru(ips_ha_t *, struct scsi_cmnd *, ips_scb_t *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
324static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
Henne1516b552006-10-02 14:56:23 +0200325static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 unsigned int count);
Henne1516b552006-10-02 14:56:23 +0200327static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data,
328 unsigned int count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
331static int ips_host_info(ips_ha_t *, char *, off_t, int);
332static void copy_mem_info(IPS_INFOSTR *, char *, int);
333static int copy_info(IPS_INFOSTR *, char *, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334static int ips_abort_init(ips_ha_t * ha, int index);
335static int ips_init_phase2(int index);
336
337static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
338static int ips_register_scsi(int index);
339
Jack Hammeree807c22005-08-29 10:44:34 -0400340static int ips_poll_for_flush_complete(ips_ha_t * ha);
341static void ips_flush_and_reset(ips_ha_t *ha);
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343/*
344 * global variables
345 */
346static const char ips_name[] = "ips";
347static struct Scsi_Host *ips_sh[IPS_MAX_ADAPTERS]; /* Array of host controller structures */
348static ips_ha_t *ips_ha[IPS_MAX_ADAPTERS]; /* Array of HA structures */
349static unsigned int ips_next_controller;
350static unsigned int ips_num_controllers;
351static unsigned int ips_released_controllers;
352static int ips_hotplug;
353static int ips_cmd_timeout = 60;
354static int ips_reset_timeout = 60 * 5;
355static int ips_force_memio = 1; /* Always use Memory Mapped I/O */
356static int ips_force_i2o = 1; /* Always use I2O command delivery */
357static int ips_ioctlsize = IPS_IOCTL_SIZE; /* Size of the ioctl buffer */
358static int ips_cd_boot; /* Booting from Manager CD */
359static char *ips_FlashData = NULL; /* CD Boot - Flash Data Buffer */
360static dma_addr_t ips_flashbusaddr;
361static long ips_FlashDataInUse; /* CD Boot - Flash Data In Use Flag */
362static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Lite Adapter */
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100363static struct scsi_host_template ips_driver_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 .detect = ips_detect,
365 .release = ips_release,
366 .info = ips_info,
367 .queuecommand = ips_queue,
368 .eh_abort_handler = ips_eh_abort,
369 .eh_host_reset_handler = ips_eh_reset,
370 .proc_name = "ips",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 .proc_info = ips_proc_info,
372 .slave_configure = ips_slave_configure,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 .bios_param = ips_biosparam,
374 .this_id = -1,
375 .sg_tablesize = IPS_MAX_SG,
376 .cmd_per_lun = 3,
377 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378};
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381/* This table describes all ServeRAID Adapters */
382static struct pci_device_id ips_pci_table[] = {
383 { 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
384 { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
385 { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
386 { 0, }
387};
388
389MODULE_DEVICE_TABLE( pci, ips_pci_table );
390
391static char ips_hot_plug_name[] = "ips";
Jeff Garzik2f277d62007-12-13 16:14:08 -0800392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
394static void __devexit ips_remove_device(struct pci_dev *pci_dev);
Jeff Garzik2f277d62007-12-13 16:14:08 -0800395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396static struct pci_driver ips_pci_driver = {
397 .name = ips_hot_plug_name,
398 .id_table = ips_pci_table,
399 .probe = ips_insert_device,
400 .remove = __devexit_p(ips_remove_device),
401};
Jeff Garzik2f277d62007-12-13 16:14:08 -0800402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404/*
405 * Necessary forward function protoypes
406 */
407static int ips_halt(struct notifier_block *nb, ulong event, void *buf);
408
409#define MAX_ADAPTER_NAME 15
410
411static char ips_adapter_name[][30] = {
412 "ServeRAID",
413 "ServeRAID II",
414 "ServeRAID on motherboard",
415 "ServeRAID on motherboard",
416 "ServeRAID 3H",
417 "ServeRAID 3L",
418 "ServeRAID 4H",
419 "ServeRAID 4M",
420 "ServeRAID 4L",
421 "ServeRAID 4Mx",
422 "ServeRAID 4Lx",
423 "ServeRAID 5i",
424 "ServeRAID 5i",
425 "ServeRAID 6M",
426 "ServeRAID 6i",
427 "ServeRAID 7t",
428 "ServeRAID 7k",
429 "ServeRAID 7M"
430};
431
432static struct notifier_block ips_notifier = {
433 ips_halt, NULL, 0
434};
435
436/*
437 * Direction table
438 */
439static char ips_command_direction[] = {
440 IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
441 IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK,
442 IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
443 IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
444 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT,
445 IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
446 IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN,
447 IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
448 IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK,
449 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
450 IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE,
451 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
452 IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT,
453 IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE,
454 IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK,
455 IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
456 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
457 IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
458 IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
459 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
460 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
461 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
462 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
463 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
464 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
465 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
466 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
467 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
468 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
469 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
470 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
471 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
472 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
473 IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE,
474 IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT,
475 IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE,
476 IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN,
477 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
478 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
479 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
480 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
481 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
482 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
483 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
484 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
485 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
486 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT,
487 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
488 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
489 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
490 IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
491};
492
493
494/****************************************************************************/
495/* */
496/* Routine Name: ips_setup */
497/* */
498/* Routine Description: */
499/* */
500/* setup parameters to the driver */
501/* */
502/****************************************************************************/
503static int
504ips_setup(char *ips_str)
505{
506
507 int i;
508 char *key;
509 char *value;
510 IPS_OPTION options[] = {
511 {"noi2o", &ips_force_i2o, 0},
512 {"nommap", &ips_force_memio, 0},
513 {"ioctlsize", &ips_ioctlsize, IPS_IOCTL_SIZE},
514 {"cdboot", &ips_cd_boot, 0},
515 {"maxcmds", &MaxLiteCmds, 32},
516 };
517
518 /* Don't use strtok() anymore ( if 2.4 Kernel or beyond ) */
519 /* Search for value */
520 while ((key = strsep(&ips_str, ",."))) {
521 if (!*key)
522 continue;
523 value = strchr(key, ':');
524 if (value)
525 *value++ = '\0';
526 /*
527 * We now have key/value pairs.
528 * Update the variables
529 */
Tobias Klauser6391a112006-06-08 22:23:48 -0700530 for (i = 0; i < ARRAY_SIZE(options); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (strnicmp
532 (key, options[i].option_name,
533 strlen(options[i].option_name)) == 0) {
534 if (value)
535 *options[i].option_flag =
536 simple_strtoul(value, NULL, 0);
537 else
538 *options[i].option_flag =
539 options[i].option_value;
540 break;
541 }
542 }
543 }
544
545 return (1);
546}
547
548__setup("ips=", ips_setup);
549
550/****************************************************************************/
551/* */
552/* Routine Name: ips_detect */
553/* */
554/* Routine Description: */
555/* */
556/* Detect and initialize the driver */
557/* */
558/* NOTE: this routine is called under the io_request_lock spinlock */
559/* */
560/****************************************************************************/
561static int
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100562ips_detect(struct scsi_host_template * SHT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563{
564 int i;
565
566 METHOD_TRACE("ips_detect", 1);
567
568#ifdef MODULE
569 if (ips)
570 ips_setup(ips);
571#endif
572
573 for (i = 0; i < ips_num_controllers; i++) {
574 if (ips_register_scsi(i))
575 ips_free(ips_ha[i]);
576 ips_released_controllers++;
577 }
578 ips_hotplug = 1;
579 return (ips_num_controllers);
580}
581
582/****************************************************************************/
583/* configure the function pointers to use the functions that will work */
584/* with the found version of the adapter */
585/****************************************************************************/
586static void
587ips_setup_funclist(ips_ha_t * ha)
588{
589
Jeff Garzik2f277d62007-12-13 16:14:08 -0800590 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 * Setup Functions
592 */
593 if (IPS_IS_MORPHEUS(ha) || IPS_IS_MARCO(ha)) {
594 /* morpheus / marco / sebring */
595 ha->func.isintr = ips_isintr_morpheus;
596 ha->func.isinit = ips_isinit_morpheus;
597 ha->func.issue = ips_issue_i2o_memio;
598 ha->func.init = ips_init_morpheus;
599 ha->func.statupd = ips_statupd_morpheus;
600 ha->func.reset = ips_reset_morpheus;
601 ha->func.intr = ips_intr_morpheus;
602 ha->func.enableint = ips_enable_int_morpheus;
603 } else if (IPS_USE_MEMIO(ha)) {
604 /* copperhead w/MEMIO */
605 ha->func.isintr = ips_isintr_copperhead_memio;
606 ha->func.isinit = ips_isinit_copperhead_memio;
607 ha->func.init = ips_init_copperhead_memio;
608 ha->func.statupd = ips_statupd_copperhead_memio;
609 ha->func.statinit = ips_statinit_memio;
610 ha->func.reset = ips_reset_copperhead_memio;
611 ha->func.intr = ips_intr_copperhead;
612 ha->func.erasebios = ips_erase_bios_memio;
613 ha->func.programbios = ips_program_bios_memio;
614 ha->func.verifybios = ips_verify_bios_memio;
615 ha->func.enableint = ips_enable_int_copperhead_memio;
616 if (IPS_USE_I2O_DELIVER(ha))
617 ha->func.issue = ips_issue_i2o_memio;
618 else
619 ha->func.issue = ips_issue_copperhead_memio;
620 } else {
621 /* copperhead */
622 ha->func.isintr = ips_isintr_copperhead;
623 ha->func.isinit = ips_isinit_copperhead;
624 ha->func.init = ips_init_copperhead;
625 ha->func.statupd = ips_statupd_copperhead;
626 ha->func.statinit = ips_statinit;
627 ha->func.reset = ips_reset_copperhead;
628 ha->func.intr = ips_intr_copperhead;
629 ha->func.erasebios = ips_erase_bios;
630 ha->func.programbios = ips_program_bios;
631 ha->func.verifybios = ips_verify_bios;
632 ha->func.enableint = ips_enable_int_copperhead;
633
634 if (IPS_USE_I2O_DELIVER(ha))
635 ha->func.issue = ips_issue_i2o;
636 else
637 ha->func.issue = ips_issue_copperhead;
638 }
639}
640
641/****************************************************************************/
642/* */
643/* Routine Name: ips_release */
644/* */
645/* Routine Description: */
646/* */
647/* Remove a driver */
648/* */
649/****************************************************************************/
650static int
651ips_release(struct Scsi_Host *sh)
652{
653 ips_scb_t *scb;
654 ips_ha_t *ha;
655 int i;
656
657 METHOD_TRACE("ips_release", 1);
658
Matthew Wilcoxa50ee7a2007-08-15 12:57:00 -0600659 scsi_remove_host(sh);
660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ;
662
663 if (i == IPS_MAX_ADAPTERS) {
664 printk(KERN_WARNING
665 "(%s) release, invalid Scsi_Host pointer.\n", ips_name);
666 BUG();
667 return (FALSE);
668 }
669
670 ha = IPS_HA(sh);
671
672 if (!ha)
673 return (FALSE);
674
675 /* flush the cache on the controller */
676 scb = &ha->scbs[ha->max_cmds - 1];
677
678 ips_init_scb(ha, scb);
679
680 scb->timeout = ips_cmd_timeout;
681 scb->cdb[0] = IPS_CMD_FLUSH;
682
683 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
684 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
685 scb->cmd.flush_cache.state = IPS_NORM_STATE;
686 scb->cmd.flush_cache.reserved = 0;
687 scb->cmd.flush_cache.reserved2 = 0;
688 scb->cmd.flush_cache.reserved3 = 0;
689 scb->cmd.flush_cache.reserved4 = 0;
690
691 IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n");
692
693 /* send command */
694 if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE)
695 IPS_PRINTK(KERN_WARNING, ha->pcidev, "Incomplete Flush.\n");
696
697 IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Complete.\n");
698
699 ips_sh[i] = NULL;
700 ips_ha[i] = NULL;
701
702 /* free extra memory */
703 ips_free(ha);
704
705 /* Free I/O Region */
706 if (ha->io_addr)
707 release_region(ha->io_addr, ha->io_len);
708
709 /* free IRQ */
Jeff Garzik8a694cc2007-12-13 16:14:07 -0800710 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 scsi_host_put(sh);
713
714 ips_released_controllers++;
715
716 return (FALSE);
717}
718
719/****************************************************************************/
720/* */
721/* Routine Name: ips_halt */
722/* */
723/* Routine Description: */
724/* */
725/* Perform cleanup when the system reboots */
726/* */
727/****************************************************************************/
728static int
729ips_halt(struct notifier_block *nb, ulong event, void *buf)
730{
731 ips_scb_t *scb;
732 ips_ha_t *ha;
733 int i;
734
735 if ((event != SYS_RESTART) && (event != SYS_HALT) &&
736 (event != SYS_POWER_OFF))
737 return (NOTIFY_DONE);
738
739 for (i = 0; i < ips_next_controller; i++) {
740 ha = (ips_ha_t *) ips_ha[i];
741
742 if (!ha)
743 continue;
744
745 if (!ha->active)
746 continue;
747
748 /* flush the cache on the controller */
749 scb = &ha->scbs[ha->max_cmds - 1];
750
751 ips_init_scb(ha, scb);
752
753 scb->timeout = ips_cmd_timeout;
754 scb->cdb[0] = IPS_CMD_FLUSH;
755
756 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
757 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
758 scb->cmd.flush_cache.state = IPS_NORM_STATE;
759 scb->cmd.flush_cache.reserved = 0;
760 scb->cmd.flush_cache.reserved2 = 0;
761 scb->cmd.flush_cache.reserved3 = 0;
762 scb->cmd.flush_cache.reserved4 = 0;
763
764 IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n");
765
766 /* send command */
767 if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) ==
768 IPS_FAILURE)
769 IPS_PRINTK(KERN_WARNING, ha->pcidev,
770 "Incomplete Flush.\n");
771 else
772 IPS_PRINTK(KERN_WARNING, ha->pcidev,
773 "Flushing Complete.\n");
774 }
775
776 return (NOTIFY_OK);
777}
778
779/****************************************************************************/
780/* */
781/* Routine Name: ips_eh_abort */
782/* */
783/* Routine Description: */
784/* */
785/* Abort a command (using the new error code stuff) */
786/* Note: this routine is called under the io_request_lock */
787/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +0200788int ips_eh_abort(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789{
790 ips_ha_t *ha;
791 ips_copp_wait_item_t *item;
792 int ret;
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400793 struct Scsi_Host *host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 METHOD_TRACE("ips_eh_abort", 1);
796
797 if (!SC)
798 return (FAILED);
799
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400800 host = SC->device->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 ha = (ips_ha_t *) SC->device->host->hostdata;
802
803 if (!ha)
804 return (FAILED);
805
806 if (!ha->active)
807 return (FAILED);
808
Adrian Bunkc6a6c812007-05-23 14:41:46 -0700809 spin_lock(host->host_lock);
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 /* See if the command is on the copp queue */
812 item = ha->copp_waitlist.head;
813 while ((item) && (item->scsi_cmd != SC))
814 item = item->next;
815
816 if (item) {
817 /* Found it */
818 ips_removeq_copp(&ha->copp_waitlist, item);
819 ret = (SUCCESS);
820
821 /* See if the command is on the wait queue */
822 } else if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
823 /* command not sent yet */
824 ret = (SUCCESS);
825 } else {
826 /* command must have already been sent */
827 ret = (FAILED);
828 }
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400829
Adrian Bunkc6a6c812007-05-23 14:41:46 -0700830 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 return ret;
832}
833
834/****************************************************************************/
835/* */
836/* Routine Name: ips_eh_reset */
837/* */
838/* Routine Description: */
839/* */
840/* Reset the controller (with new eh error code) */
841/* */
842/* NOTE: this routine is called under the io_request_lock spinlock */
843/* */
844/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +0200845static int __ips_eh_reset(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846{
847 int ret;
848 int i;
849 ips_ha_t *ha;
850 ips_scb_t *scb;
851 ips_copp_wait_item_t *item;
852
853 METHOD_TRACE("ips_eh_reset", 1);
854
855#ifdef NO_IPS_RESET
856 return (FAILED);
857#else
858
859 if (!SC) {
860 DEBUG(1, "Reset called with NULL scsi command");
861
862 return (FAILED);
863 }
864
865 ha = (ips_ha_t *) SC->device->host->hostdata;
866
867 if (!ha) {
868 DEBUG(1, "Reset called with NULL ha struct");
869
870 return (FAILED);
871 }
872
873 if (!ha->active)
874 return (FAILED);
875
876 /* See if the command is on the copp queue */
877 item = ha->copp_waitlist.head;
878 while ((item) && (item->scsi_cmd != SC))
879 item = item->next;
880
881 if (item) {
882 /* Found it */
883 ips_removeq_copp(&ha->copp_waitlist, item);
884 return (SUCCESS);
885 }
886
887 /* See if the command is on the wait queue */
888 if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
889 /* command not sent yet */
890 return (SUCCESS);
891 }
892
893 /* An explanation for the casual observer: */
894 /* Part of the function of a RAID controller is automatic error */
895 /* detection and recovery. As such, the only problem that physically */
896 /* resetting an adapter will ever fix is when, for some reason, */
897 /* the driver is not successfully communicating with the adapter. */
898 /* Therefore, we will attempt to flush this adapter. If that succeeds, */
899 /* then there's no real purpose in a physical reset. This will complete */
900 /* much faster and avoids any problems that might be caused by a */
901 /* physical reset ( such as having to fail all the outstanding I/O's ). */
902
903 if (ha->ioctl_reset == 0) { /* IF Not an IOCTL Requested Reset */
904 scb = &ha->scbs[ha->max_cmds - 1];
905
906 ips_init_scb(ha, scb);
907
908 scb->timeout = ips_cmd_timeout;
909 scb->cdb[0] = IPS_CMD_FLUSH;
910
911 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
912 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
913 scb->cmd.flush_cache.state = IPS_NORM_STATE;
914 scb->cmd.flush_cache.reserved = 0;
915 scb->cmd.flush_cache.reserved2 = 0;
916 scb->cmd.flush_cache.reserved3 = 0;
917 scb->cmd.flush_cache.reserved4 = 0;
918
919 /* Attempt the flush command */
920 ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL);
921 if (ret == IPS_SUCCESS) {
922 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
923 "Reset Request - Flushed Cache\n");
924 return (SUCCESS);
925 }
926 }
927
928 /* Either we can't communicate with the adapter or it's an IOCTL request */
929 /* from a utility. A physical reset is needed at this point. */
930
931 ha->ioctl_reset = 0; /* Reset the IOCTL Requested Reset Flag */
932
933 /*
934 * command must have already been sent
935 * reset the controller
936 */
937 IPS_PRINTK(KERN_NOTICE, ha->pcidev, "Resetting controller.\n");
938 ret = (*ha->func.reset) (ha);
939
940 if (!ret) {
Henne1516b552006-10-02 14:56:23 +0200941 struct scsi_cmnd *scsi_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
943 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
944 "Controller reset failed - controller now offline.\n");
945
946 /* Now fail all of the active commands */
947 DEBUG_VAR(1, "(%s%d) Failing active commands",
948 ips_name, ha->host_num);
949
950 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
951 scb->scsi_cmd->result = DID_ERROR << 16;
952 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
953 ips_freescb(ha, scb);
954 }
955
956 /* Now fail all of the pending commands */
957 DEBUG_VAR(1, "(%s%d) Failing pending commands",
958 ips_name, ha->host_num);
959
960 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
961 scsi_cmd->result = DID_ERROR;
962 scsi_cmd->scsi_done(scsi_cmd);
963 }
964
965 ha->active = FALSE;
966 return (FAILED);
967 }
968
969 if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
Henne1516b552006-10-02 14:56:23 +0200970 struct scsi_cmnd *scsi_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
973 "Controller reset failed - controller now offline.\n");
974
975 /* Now fail all of the active commands */
976 DEBUG_VAR(1, "(%s%d) Failing active commands",
977 ips_name, ha->host_num);
978
979 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
980 scb->scsi_cmd->result = DID_ERROR << 16;
981 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
982 ips_freescb(ha, scb);
983 }
984
985 /* Now fail all of the pending commands */
986 DEBUG_VAR(1, "(%s%d) Failing pending commands",
987 ips_name, ha->host_num);
988
989 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
990 scsi_cmd->result = DID_ERROR << 16;
991 scsi_cmd->scsi_done(scsi_cmd);
992 }
993
994 ha->active = FALSE;
995 return (FAILED);
996 }
997
998 /* FFDC */
999 if (le32_to_cpu(ha->subsys->param[3]) & 0x300000) {
1000 struct timeval tv;
1001
1002 do_gettimeofday(&tv);
1003 ha->last_ffdc = tv.tv_sec;
1004 ha->reset_count++;
1005 ips_ffdc_reset(ha, IPS_INTR_IORL);
1006 }
1007
1008 /* Now fail all of the active commands */
1009 DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num);
1010
1011 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
1012 scb->scsi_cmd->result =
1013 (DID_RESET << 16) | (SUGGEST_RETRY << 24);
1014 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1015 ips_freescb(ha, scb);
1016 }
1017
1018 /* Reset DCDB active command bits */
1019 for (i = 1; i < ha->nbus; i++)
1020 ha->dcdb_active[i - 1] = 0;
1021
1022 /* Reset the number of active IOCTLs */
1023 ha->num_ioctl = 0;
1024
1025 ips_next(ha, IPS_INTR_IORL);
1026
1027 return (SUCCESS);
1028#endif /* NO_IPS_RESET */
1029
1030}
1031
Henne1516b552006-10-02 14:56:23 +02001032static int ips_eh_reset(struct scsi_cmnd *SC)
Jeff Garzik df0ae242005-05-28 07:57:14 -04001033{
1034 int rc;
1035
1036 spin_lock_irq(SC->device->host->host_lock);
1037 rc = __ips_eh_reset(SC);
1038 spin_unlock_irq(SC->device->host->host_lock);
1039
1040 return rc;
1041}
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043/****************************************************************************/
1044/* */
1045/* Routine Name: ips_queue */
1046/* */
1047/* Routine Description: */
1048/* */
1049/* Send a command to the controller */
1050/* */
1051/* NOTE: */
1052/* Linux obtains io_request_lock before calling this function */
1053/* */
1054/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02001055static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056{
1057 ips_ha_t *ha;
1058 ips_passthru_t *pt;
1059
1060 METHOD_TRACE("ips_queue", 1);
1061
1062 ha = (ips_ha_t *) SC->device->host->hostdata;
1063
1064 if (!ha)
1065 return (1);
1066
1067 if (!ha->active)
1068 return (DID_ERROR);
1069
1070 if (ips_is_passthru(SC)) {
1071 if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
1072 SC->result = DID_BUS_BUSY << 16;
1073 done(SC);
1074
1075 return (0);
1076 }
1077 } else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
1078 SC->result = DID_BUS_BUSY << 16;
1079 done(SC);
1080
1081 return (0);
1082 }
1083
1084 SC->scsi_done = done;
1085
1086 DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)",
1087 ips_name,
1088 ha->host_num,
1089 SC->cmnd[0],
1090 SC->device->channel, SC->device->id, SC->device->lun);
1091
1092 /* Check for command to initiator IDs */
Jeff Garzik422c0d62005-10-24 18:05:09 -04001093 if ((scmd_channel(SC) > 0)
1094 && (scmd_id(SC) == ha->ha_id[scmd_channel(SC)])) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 SC->result = DID_NO_CONNECT << 16;
1096 done(SC);
1097
1098 return (0);
1099 }
1100
1101 if (ips_is_passthru(SC)) {
1102
1103 ips_copp_wait_item_t *scratch;
1104
1105 /* A Reset IOCTL is only sent by the boot CD in extreme cases. */
1106 /* There can never be any system activity ( network or disk ), but check */
1107 /* anyway just as a good practice. */
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001108 pt = (ips_passthru_t *) scsi_sglist(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
1110 (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
1111 if (ha->scb_activelist.count != 0) {
1112 SC->result = DID_BUS_BUSY << 16;
1113 done(SC);
1114 return (0);
1115 }
1116 ha->ioctl_reset = 1; /* This reset request is from an IOCTL */
Mike Christieba3af0a2006-02-22 02:11:59 -06001117 __ips_eh_reset(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 SC->result = DID_OK << 16;
1119 SC->scsi_done(SC);
1120 return (0);
1121 }
1122
1123 /* allocate space for the scribble */
1124 scratch = kmalloc(sizeof (ips_copp_wait_item_t), GFP_ATOMIC);
1125
1126 if (!scratch) {
1127 SC->result = DID_ERROR << 16;
1128 done(SC);
1129
1130 return (0);
1131 }
1132
1133 scratch->scsi_cmd = SC;
1134 scratch->next = NULL;
1135
1136 ips_putq_copp_tail(&ha->copp_waitlist, scratch);
1137 } else {
1138 ips_putq_wait_tail(&ha->scb_waitlist, SC);
1139 }
1140
1141 ips_next(ha, IPS_INTR_IORL);
1142
1143 return (0);
1144}
1145
1146/****************************************************************************/
1147/* */
1148/* Routine Name: ips_biosparam */
1149/* */
1150/* Routine Description: */
1151/* */
1152/* Set bios geometry for the controller */
1153/* */
1154/****************************************************************************/
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001155static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1156 sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157{
1158 ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 int heads;
1160 int sectors;
1161 int cylinders;
1162
1163 METHOD_TRACE("ips_biosparam", 1);
1164
1165 if (!ha)
1166 /* ?!?! host adater info invalid */
1167 return (0);
1168
1169 if (!ha->active)
1170 return (0);
1171
1172 if (!ips_read_adapter_status(ha, IPS_INTR_ON))
1173 /* ?!?! Enquiry command failed */
1174 return (0);
1175
1176 if ((capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) {
1177 heads = IPS_NORM_HEADS;
1178 sectors = IPS_NORM_SECTORS;
1179 } else {
1180 heads = IPS_COMP_HEADS;
1181 sectors = IPS_COMP_SECTORS;
1182 }
1183
1184 cylinders = (unsigned long) capacity / (heads * sectors);
1185
1186 DEBUG_VAR(2, "Geometry: heads: %d, sectors: %d, cylinders: %d",
1187 heads, sectors, cylinders);
1188
1189 geom[0] = heads;
1190 geom[1] = sectors;
1191 geom[2] = cylinders;
1192
1193 return (0);
1194}
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196/****************************************************************************/
1197/* */
1198/* Routine Name: ips_slave_configure */
1199/* */
1200/* Routine Description: */
1201/* */
1202/* Set queue depths on devices once scan is complete */
1203/* */
1204/****************************************************************************/
1205static int
Christoph Hellwigf64a1812005-10-31 18:32:08 +01001206ips_slave_configure(struct scsi_device * SDptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207{
1208 ips_ha_t *ha;
1209 int min;
1210
1211 ha = IPS_HA(SDptr->host);
1212 if (SDptr->tagged_supported && SDptr->type == TYPE_DISK) {
1213 min = ha->max_cmds / 2;
1214 if (ha->enq->ucLogDriveCount <= 2)
1215 min = ha->max_cmds - 1;
1216 scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
1217 }
Jack Hammer560c26c2006-01-13 10:06:50 -05001218
1219 SDptr->skip_ms_page_8 = 1;
1220 SDptr->skip_ms_page_3f = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 return 0;
1222}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224/****************************************************************************/
1225/* */
1226/* Routine Name: do_ipsintr */
1227/* */
1228/* Routine Description: */
1229/* */
1230/* Wrapper for the interrupt handler */
1231/* */
1232/****************************************************************************/
1233static irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +01001234do_ipsintr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
1236 ips_ha_t *ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 struct Scsi_Host *host;
1238 int irqstatus;
1239
1240 METHOD_TRACE("do_ipsintr", 2);
1241
1242 ha = (ips_ha_t *) dev_id;
1243 if (!ha)
1244 return IRQ_NONE;
1245 host = ips_sh[ha->host_num];
1246 /* interrupt during initialization */
1247 if (!host) {
1248 (*ha->func.intr) (ha);
1249 return IRQ_HANDLED;
1250 }
1251
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001252 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 if (!ha->active) {
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001255 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return IRQ_HANDLED;
1257 }
1258
1259 irqstatus = (*ha->func.intr) (ha);
1260
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001261 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 /* start the next command */
1264 ips_next(ha, IPS_INTR_ON);
1265 return IRQ_RETVAL(irqstatus);
1266}
1267
1268/****************************************************************************/
1269/* */
1270/* Routine Name: ips_intr_copperhead */
1271/* */
1272/* Routine Description: */
1273/* */
1274/* Polling interrupt handler */
1275/* */
1276/* ASSUMES interrupts are disabled */
1277/* */
1278/****************************************************************************/
1279int
1280ips_intr_copperhead(ips_ha_t * ha)
1281{
1282 ips_stat_t *sp;
1283 ips_scb_t *scb;
1284 IPS_STATUS cstatus;
1285 int intrstatus;
1286
1287 METHOD_TRACE("ips_intr", 2);
1288
1289 if (!ha)
1290 return 0;
1291
1292 if (!ha->active)
1293 return 0;
1294
1295 intrstatus = (*ha->func.isintr) (ha);
1296
1297 if (!intrstatus) {
1298 /*
1299 * Unexpected/Shared interrupt
1300 */
1301
1302 return 0;
1303 }
1304
1305 while (TRUE) {
1306 sp = &ha->sp;
1307
1308 intrstatus = (*ha->func.isintr) (ha);
1309
1310 if (!intrstatus)
1311 break;
1312 else
1313 cstatus.value = (*ha->func.statupd) (ha);
1314
1315 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1316 /* Spurious Interupt ? */
1317 continue;
1318 }
1319
1320 ips_chkstatus(ha, &cstatus);
1321 scb = (ips_scb_t *) sp->scb_addr;
1322
1323 /*
1324 * use the callback function to finish things up
1325 * NOTE: interrupts are OFF for this
1326 */
1327 (*scb->callback) (ha, scb);
1328 } /* end while */
1329 return 1;
1330}
1331
1332/****************************************************************************/
1333/* */
1334/* Routine Name: ips_intr_morpheus */
1335/* */
1336/* Routine Description: */
1337/* */
1338/* Polling interrupt handler */
1339/* */
1340/* ASSUMES interrupts are disabled */
1341/* */
1342/****************************************************************************/
1343int
1344ips_intr_morpheus(ips_ha_t * ha)
1345{
1346 ips_stat_t *sp;
1347 ips_scb_t *scb;
1348 IPS_STATUS cstatus;
1349 int intrstatus;
1350
1351 METHOD_TRACE("ips_intr_morpheus", 2);
1352
1353 if (!ha)
1354 return 0;
1355
1356 if (!ha->active)
1357 return 0;
1358
1359 intrstatus = (*ha->func.isintr) (ha);
1360
1361 if (!intrstatus) {
1362 /*
1363 * Unexpected/Shared interrupt
1364 */
1365
1366 return 0;
1367 }
1368
1369 while (TRUE) {
1370 sp = &ha->sp;
1371
1372 intrstatus = (*ha->func.isintr) (ha);
1373
1374 if (!intrstatus)
1375 break;
1376 else
1377 cstatus.value = (*ha->func.statupd) (ha);
1378
1379 if (cstatus.value == 0xffffffff)
1380 /* No more to process */
1381 break;
1382
1383 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1384 IPS_PRINTK(KERN_WARNING, ha->pcidev,
1385 "Spurious interrupt; no ccb.\n");
1386
1387 continue;
1388 }
1389
1390 ips_chkstatus(ha, &cstatus);
1391 scb = (ips_scb_t *) sp->scb_addr;
1392
1393 /*
1394 * use the callback function to finish things up
1395 * NOTE: interrupts are OFF for this
1396 */
1397 (*scb->callback) (ha, scb);
1398 } /* end while */
1399 return 1;
1400}
1401
1402/****************************************************************************/
1403/* */
1404/* Routine Name: ips_info */
1405/* */
1406/* Routine Description: */
1407/* */
1408/* Return info about the driver */
1409/* */
1410/****************************************************************************/
1411static const char *
1412ips_info(struct Scsi_Host *SH)
1413{
1414 static char buffer[256];
1415 char *bp;
1416 ips_ha_t *ha;
1417
1418 METHOD_TRACE("ips_info", 1);
1419
1420 ha = IPS_HA(SH);
1421
1422 if (!ha)
1423 return (NULL);
1424
1425 bp = &buffer[0];
1426 memset(bp, 0, sizeof (buffer));
1427
1428 sprintf(bp, "%s%s%s Build %d", "IBM PCI ServeRAID ",
1429 IPS_VERSION_HIGH, IPS_VERSION_LOW, IPS_BUILD_IDENT);
1430
1431 if (ha->ad_type > 0 && ha->ad_type <= MAX_ADAPTER_NAME) {
1432 strcat(bp, " <");
1433 strcat(bp, ips_adapter_name[ha->ad_type - 1]);
1434 strcat(bp, ">");
1435 }
1436
1437 return (bp);
1438}
1439
1440/****************************************************************************/
1441/* */
1442/* Routine Name: ips_proc_info */
1443/* */
1444/* Routine Description: */
1445/* */
1446/* The passthru interface for the driver */
1447/* */
1448/****************************************************************************/
1449static int
1450ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1451 int length, int func)
1452{
1453 int i;
1454 int ret;
1455 ips_ha_t *ha = NULL;
1456
1457 METHOD_TRACE("ips_proc_info", 1);
1458
1459 /* Find our host structure */
1460 for (i = 0; i < ips_next_controller; i++) {
1461 if (ips_sh[i]) {
1462 if (ips_sh[i] == host) {
1463 ha = (ips_ha_t *) ips_sh[i]->hostdata;
1464 break;
1465 }
1466 }
1467 }
1468
1469 if (!ha)
1470 return (-EINVAL);
1471
1472 if (func) {
1473 /* write */
1474 return (0);
1475 } else {
1476 /* read */
1477 if (start)
1478 *start = buffer;
1479
1480 ret = ips_host_info(ha, buffer, offset, length);
1481
1482 return (ret);
1483 }
1484}
1485
1486/*--------------------------------------------------------------------------*/
1487/* Helper Functions */
1488/*--------------------------------------------------------------------------*/
1489
1490/****************************************************************************/
1491/* */
1492/* Routine Name: ips_is_passthru */
1493/* */
1494/* Routine Description: */
1495/* */
1496/* Determine if the specified SCSI command is really a passthru command */
1497/* */
1498/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02001499static int ips_is_passthru(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500{
Jack Hammera3632fa2005-10-25 14:13:03 -04001501 unsigned long flags;
1502
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 METHOD_TRACE("ips_is_passthru", 1);
1504
1505 if (!SC)
1506 return (0);
1507
1508 if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
1509 (SC->device->channel == 0) &&
1510 (SC->device->id == IPS_ADAPTER_ID) &&
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001511 (SC->device->lun == 0) && scsi_sglist(SC)) {
1512 struct scatterlist *sg = scsi_sglist(SC);
1513 char *buffer;
Jack Hammera3632fa2005-10-25 14:13:03 -04001514
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001515 /* kmap_atomic() ensures addressability of the user buffer.*/
1516 /* local_irq_save() protects the KM_IRQ0 address slot. */
1517 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02001518 buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001519 if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
1520 buffer[2] == 'P' && buffer[3] == 'P') {
1521 kunmap_atomic(buffer - sg->offset, KM_IRQ0);
1522 local_irq_restore(flags);
1523 return 1;
1524 }
1525 kunmap_atomic(buffer - sg->offset, KM_IRQ0);
1526 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 }
1528 return 0;
1529}
1530
1531/****************************************************************************/
1532/* */
1533/* Routine Name: ips_alloc_passthru_buffer */
1534/* */
1535/* Routine Description: */
1536/* allocate a buffer large enough for the ioctl data if the ioctl buffer */
1537/* is too small or doesn't exist */
1538/****************************************************************************/
1539static int
1540ips_alloc_passthru_buffer(ips_ha_t * ha, int length)
1541{
1542 void *bigger_buf;
1543 dma_addr_t dma_busaddr;
1544
1545 if (ha->ioctl_data && length <= ha->ioctl_len)
1546 return 0;
1547 /* there is no buffer or it's not big enough, allocate a new one */
1548 bigger_buf = pci_alloc_consistent(ha->pcidev, length, &dma_busaddr);
1549 if (bigger_buf) {
1550 /* free the old memory */
1551 pci_free_consistent(ha->pcidev, ha->ioctl_len, ha->ioctl_data,
1552 ha->ioctl_busaddr);
1553 /* use the new memory */
1554 ha->ioctl_data = (char *) bigger_buf;
1555 ha->ioctl_len = length;
1556 ha->ioctl_busaddr = dma_busaddr;
1557 } else {
1558 return -1;
1559 }
1560 return 0;
1561}
1562
1563/****************************************************************************/
1564/* */
1565/* Routine Name: ips_make_passthru */
1566/* */
1567/* Routine Description: */
1568/* */
1569/* Make a passthru command out of the info in the Scsi block */
1570/* */
1571/****************************************************************************/
1572static int
Henne1516b552006-10-02 14:56:23 +02001573ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
1575 ips_passthru_t *pt;
1576 int length = 0;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001577 int i, ret;
1578 struct scatterlist *sg = scsi_sglist(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
1580 METHOD_TRACE("ips_make_passthru", 1);
1581
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001582 scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
1583 length += sg[i].length;
1584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 if (length < sizeof (ips_passthru_t)) {
1586 /* wrong size */
1587 DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
1588 ips_name, ha->host_num);
1589 return (IPS_FAILURE);
1590 }
1591 if (ips_alloc_passthru_buffer(ha, length)) {
1592 /* allocation failure! If ha->ioctl_data exists, use it to return
1593 some error codes. Return a failed command to the scsi layer. */
1594 if (ha->ioctl_data) {
1595 pt = (ips_passthru_t *) ha->ioctl_data;
1596 ips_scmd_buf_read(SC, pt, sizeof (ips_passthru_t));
1597 pt->BasicStatus = 0x0B;
1598 pt->ExtendedStatus = 0x00;
1599 ips_scmd_buf_write(SC, pt, sizeof (ips_passthru_t));
1600 }
1601 return IPS_FAILURE;
1602 }
1603 ha->ioctl_datasize = length;
1604
1605 ips_scmd_buf_read(SC, ha->ioctl_data, ha->ioctl_datasize);
1606 pt = (ips_passthru_t *) ha->ioctl_data;
1607
1608 /*
1609 * Some notes about the passthru interface used
1610 *
1611 * IF the scsi op_code == 0x0d then we assume
1612 * that the data came along with/goes with the
1613 * packet we received from the sg driver. In this
1614 * case the CmdBSize field of the pt structure is
1615 * used for the size of the buffer.
1616 */
1617
1618 switch (pt->CoppCmd) {
1619 case IPS_NUMCTRLS:
1620 memcpy(ha->ioctl_data + sizeof (ips_passthru_t),
1621 &ips_num_controllers, sizeof (int));
1622 ips_scmd_buf_write(SC, ha->ioctl_data,
1623 sizeof (ips_passthru_t) + sizeof (int));
1624 SC->result = DID_OK << 16;
1625
1626 return (IPS_SUCCESS_IMM);
1627
1628 case IPS_COPPUSRCMD:
1629 case IPS_COPPIOCCMD:
1630 if (SC->cmnd[0] == IPS_IOCTL_COMMAND) {
1631 if (length < (sizeof (ips_passthru_t) + pt->CmdBSize)) {
1632 /* wrong size */
1633 DEBUG_VAR(1,
1634 "(%s%d) Passthru structure wrong size",
1635 ips_name, ha->host_num);
1636
1637 return (IPS_FAILURE);
1638 }
1639
Jeff Garzik8a694cc2007-12-13 16:14:07 -08001640 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 pt->CoppCP.cmd.flashfw.op_code ==
1642 IPS_CMD_RW_BIOSFW) {
1643 ret = ips_flash_copperhead(ha, pt, scb);
1644 ips_scmd_buf_write(SC, ha->ioctl_data,
1645 sizeof (ips_passthru_t));
1646 return ret;
1647 }
1648 if (ips_usrcmd(ha, pt, scb))
1649 return (IPS_SUCCESS);
1650 else
1651 return (IPS_FAILURE);
1652 }
1653
1654 break;
1655
1656 } /* end switch */
1657
1658 return (IPS_FAILURE);
1659}
1660
1661/****************************************************************************/
1662/* Routine Name: ips_flash_copperhead */
1663/* Routine Description: */
1664/* Flash the BIOS/FW on a Copperhead style controller */
1665/****************************************************************************/
1666static int
1667ips_flash_copperhead(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1668{
1669 int datasize;
1670
1671 /* Trombone is the only copperhead that can do packet flash, but only
1672 * for firmware. No one said it had to make sence. */
1673 if (IPS_IS_TROMBONE(ha) && pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE) {
1674 if (ips_usrcmd(ha, pt, scb))
1675 return IPS_SUCCESS;
1676 else
1677 return IPS_FAILURE;
1678 }
1679 pt->BasicStatus = 0x0B;
1680 pt->ExtendedStatus = 0;
1681 scb->scsi_cmd->result = DID_OK << 16;
1682 /* IF it's OK to Use the "CD BOOT" Flash Buffer, then you can */
1683 /* avoid allocating a huge buffer per adapter ( which can fail ). */
1684 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1685 pt->CoppCP.cmd.flashfw.direction == IPS_ERASE_BIOS) {
1686 pt->BasicStatus = 0;
1687 return ips_flash_bios(ha, pt, scb);
1688 } else if (pt->CoppCP.cmd.flashfw.packet_num == 0) {
1689 if (ips_FlashData && !test_and_set_bit(0, &ips_FlashDataInUse)){
1690 ha->flash_data = ips_FlashData;
1691 ha->flash_busaddr = ips_flashbusaddr;
1692 ha->flash_len = PAGE_SIZE << 7;
1693 ha->flash_datasize = 0;
1694 } else if (!ha->flash_data) {
1695 datasize = pt->CoppCP.cmd.flashfw.total_packets *
1696 pt->CoppCP.cmd.flashfw.count;
1697 ha->flash_data = pci_alloc_consistent(ha->pcidev,
1698 datasize,
1699 &ha->flash_busaddr);
1700 if (!ha->flash_data){
1701 printk(KERN_WARNING "Unable to allocate a flash buffer\n");
1702 return IPS_FAILURE;
1703 }
1704 ha->flash_datasize = 0;
1705 ha->flash_len = datasize;
1706 } else
1707 return IPS_FAILURE;
1708 } else {
1709 if (pt->CoppCP.cmd.flashfw.count + ha->flash_datasize >
1710 ha->flash_len) {
1711 ips_free_flash_copperhead(ha);
1712 IPS_PRINTK(KERN_WARNING, ha->pcidev,
1713 "failed size sanity check\n");
1714 return IPS_FAILURE;
1715 }
1716 }
1717 if (!ha->flash_data)
1718 return IPS_FAILURE;
1719 pt->BasicStatus = 0;
1720 memcpy(&ha->flash_data[ha->flash_datasize], pt + 1,
1721 pt->CoppCP.cmd.flashfw.count);
1722 ha->flash_datasize += pt->CoppCP.cmd.flashfw.count;
1723 if (pt->CoppCP.cmd.flashfw.packet_num ==
1724 pt->CoppCP.cmd.flashfw.total_packets - 1) {
1725 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE)
1726 return ips_flash_bios(ha, pt, scb);
1727 else if (pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE)
1728 return ips_flash_firmware(ha, pt, scb);
1729 }
1730 return IPS_SUCCESS_IMM;
1731}
1732
1733/****************************************************************************/
1734/* Routine Name: ips_flash_bios */
1735/* Routine Description: */
1736/* flashes the bios of a copperhead adapter */
1737/****************************************************************************/
1738static int
1739ips_flash_bios(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1740{
1741
1742 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1743 pt->CoppCP.cmd.flashfw.direction == IPS_WRITE_BIOS) {
1744 if ((!ha->func.programbios) || (!ha->func.erasebios) ||
1745 (!ha->func.verifybios))
1746 goto error;
1747 if ((*ha->func.erasebios) (ha)) {
1748 DEBUG_VAR(1,
1749 "(%s%d) flash bios failed - unable to erase flash",
1750 ips_name, ha->host_num);
1751 goto error;
1752 } else
1753 if ((*ha->func.programbios) (ha,
1754 ha->flash_data +
1755 IPS_BIOS_HEADER,
1756 ha->flash_datasize -
1757 IPS_BIOS_HEADER, 0)) {
1758 DEBUG_VAR(1,
1759 "(%s%d) flash bios failed - unable to flash",
1760 ips_name, ha->host_num);
1761 goto error;
1762 } else
1763 if ((*ha->func.verifybios) (ha,
1764 ha->flash_data +
1765 IPS_BIOS_HEADER,
1766 ha->flash_datasize -
1767 IPS_BIOS_HEADER, 0)) {
1768 DEBUG_VAR(1,
1769 "(%s%d) flash bios failed - unable to verify flash",
1770 ips_name, ha->host_num);
1771 goto error;
1772 }
1773 ips_free_flash_copperhead(ha);
1774 return IPS_SUCCESS_IMM;
1775 } else if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1776 pt->CoppCP.cmd.flashfw.direction == IPS_ERASE_BIOS) {
1777 if (!ha->func.erasebios)
1778 goto error;
1779 if ((*ha->func.erasebios) (ha)) {
1780 DEBUG_VAR(1,
1781 "(%s%d) flash bios failed - unable to erase flash",
1782 ips_name, ha->host_num);
1783 goto error;
1784 }
1785 return IPS_SUCCESS_IMM;
1786 }
1787 error:
1788 pt->BasicStatus = 0x0B;
1789 pt->ExtendedStatus = 0x00;
1790 ips_free_flash_copperhead(ha);
1791 return IPS_FAILURE;
1792}
1793
1794/****************************************************************************/
1795/* */
1796/* Routine Name: ips_fill_scb_sg_single */
1797/* */
1798/* Routine Description: */
1799/* Fill in a single scb sg_list element from an address */
1800/* return a -1 if a breakup occurred */
1801/****************************************************************************/
1802static int
1803ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
1804 ips_scb_t * scb, int indx, unsigned int e_len)
1805{
1806
1807 int ret_val = 0;
1808
1809 if ((scb->data_len + e_len) > ha->max_xfer) {
1810 e_len = ha->max_xfer - scb->data_len;
1811 scb->breakup = indx;
1812 ++scb->sg_break;
1813 ret_val = -1;
1814 } else {
1815 scb->breakup = 0;
1816 scb->sg_break = 0;
1817 }
1818 if (IPS_USE_ENH_SGLIST(ha)) {
1819 scb->sg_list.enh_list[indx].address_lo =
1820 cpu_to_le32(pci_dma_lo32(busaddr));
1821 scb->sg_list.enh_list[indx].address_hi =
1822 cpu_to_le32(pci_dma_hi32(busaddr));
1823 scb->sg_list.enh_list[indx].length = cpu_to_le32(e_len);
1824 } else {
1825 scb->sg_list.std_list[indx].address =
1826 cpu_to_le32(pci_dma_lo32(busaddr));
1827 scb->sg_list.std_list[indx].length = cpu_to_le32(e_len);
1828 }
1829
1830 ++scb->sg_len;
1831 scb->data_len += e_len;
1832 return ret_val;
1833}
1834
1835/****************************************************************************/
1836/* Routine Name: ips_flash_firmware */
1837/* Routine Description: */
1838/* flashes the firmware of a copperhead adapter */
1839/****************************************************************************/
1840static int
1841ips_flash_firmware(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1842{
1843 IPS_SG_LIST sg_list;
1844 uint32_t cmd_busaddr;
1845
1846 if (pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE &&
1847 pt->CoppCP.cmd.flashfw.direction == IPS_WRITE_FW) {
1848 memset(&pt->CoppCP.cmd, 0, sizeof (IPS_HOST_COMMAND));
1849 pt->CoppCP.cmd.flashfw.op_code = IPS_CMD_DOWNLOAD;
1850 pt->CoppCP.cmd.flashfw.count = cpu_to_le32(ha->flash_datasize);
1851 } else {
1852 pt->BasicStatus = 0x0B;
1853 pt->ExtendedStatus = 0x00;
1854 ips_free_flash_copperhead(ha);
1855 return IPS_FAILURE;
1856 }
1857 /* Save the S/G list pointer so it doesn't get clobbered */
1858 sg_list.list = scb->sg_list.list;
1859 cmd_busaddr = scb->scb_busaddr;
1860 /* copy in the CP */
1861 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof (IPS_IOCTL_CMD));
1862 /* FIX stuff that might be wrong */
1863 scb->sg_list.list = sg_list.list;
1864 scb->scb_busaddr = cmd_busaddr;
1865 scb->bus = scb->scsi_cmd->device->channel;
1866 scb->target_id = scb->scsi_cmd->device->id;
1867 scb->lun = scb->scsi_cmd->device->lun;
1868 scb->sg_len = 0;
1869 scb->data_len = 0;
1870 scb->flags = 0;
1871 scb->op_code = 0;
1872 scb->callback = ipsintr_done;
1873 scb->timeout = ips_cmd_timeout;
1874
1875 scb->data_len = ha->flash_datasize;
1876 scb->data_busaddr =
1877 pci_map_single(ha->pcidev, ha->flash_data, scb->data_len,
1878 IPS_DMA_DIR(scb));
1879 scb->flags |= IPS_SCB_MAP_SINGLE;
1880 scb->cmd.flashfw.command_id = IPS_COMMAND_ID(ha, scb);
1881 scb->cmd.flashfw.buffer_addr = cpu_to_le32(scb->data_busaddr);
1882 if (pt->TimeOut)
1883 scb->timeout = pt->TimeOut;
1884 scb->scsi_cmd->result = DID_OK << 16;
1885 return IPS_SUCCESS;
1886}
1887
1888/****************************************************************************/
1889/* Routine Name: ips_free_flash_copperhead */
1890/* Routine Description: */
1891/* release the memory resources used to hold the flash image */
1892/****************************************************************************/
1893static void
1894ips_free_flash_copperhead(ips_ha_t * ha)
1895{
1896 if (ha->flash_data == ips_FlashData)
1897 test_and_clear_bit(0, &ips_FlashDataInUse);
1898 else if (ha->flash_data)
1899 pci_free_consistent(ha->pcidev, ha->flash_len, ha->flash_data,
1900 ha->flash_busaddr);
1901 ha->flash_data = NULL;
1902}
1903
1904/****************************************************************************/
1905/* */
1906/* Routine Name: ips_usrcmd */
1907/* */
1908/* Routine Description: */
1909/* */
1910/* Process a user command and make it ready to send */
1911/* */
1912/****************************************************************************/
1913static int
1914ips_usrcmd(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1915{
1916 IPS_SG_LIST sg_list;
1917 uint32_t cmd_busaddr;
1918
1919 METHOD_TRACE("ips_usrcmd", 1);
1920
1921 if ((!scb) || (!pt) || (!ha))
1922 return (0);
1923
1924 /* Save the S/G list pointer so it doesn't get clobbered */
1925 sg_list.list = scb->sg_list.list;
1926 cmd_busaddr = scb->scb_busaddr;
1927 /* copy in the CP */
1928 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof (IPS_IOCTL_CMD));
1929 memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof (IPS_DCDB_TABLE));
1930
1931 /* FIX stuff that might be wrong */
1932 scb->sg_list.list = sg_list.list;
1933 scb->scb_busaddr = cmd_busaddr;
1934 scb->bus = scb->scsi_cmd->device->channel;
1935 scb->target_id = scb->scsi_cmd->device->id;
1936 scb->lun = scb->scsi_cmd->device->lun;
1937 scb->sg_len = 0;
1938 scb->data_len = 0;
1939 scb->flags = 0;
1940 scb->op_code = 0;
1941 scb->callback = ipsintr_done;
1942 scb->timeout = ips_cmd_timeout;
1943 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
1944
1945 /* we don't support DCDB/READ/WRITE Scatter Gather */
1946 if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
1947 (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
1948 (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
1949 return (0);
1950
1951 if (pt->CmdBSize) {
1952 scb->data_len = pt->CmdBSize;
1953 scb->data_busaddr = ha->ioctl_busaddr + sizeof (ips_passthru_t);
1954 } else {
1955 scb->data_busaddr = 0L;
1956 }
1957
1958 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
1959 scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr +
1960 (unsigned long) &scb->
1961 dcdb -
1962 (unsigned long) scb);
1963
1964 if (pt->CmdBSize) {
1965 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
1966 scb->dcdb.buffer_pointer =
1967 cpu_to_le32(scb->data_busaddr);
1968 else
1969 scb->cmd.basic_io.sg_addr =
1970 cpu_to_le32(scb->data_busaddr);
1971 }
1972
1973 /* set timeouts */
1974 if (pt->TimeOut) {
1975 scb->timeout = pt->TimeOut;
1976
1977 if (pt->TimeOut <= 10)
1978 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
1979 else if (pt->TimeOut <= 60)
1980 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
1981 else
1982 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
1983 }
1984
1985 /* assume success */
1986 scb->scsi_cmd->result = DID_OK << 16;
1987
1988 /* success */
1989 return (1);
1990}
1991
1992/****************************************************************************/
1993/* */
1994/* Routine Name: ips_cleanup_passthru */
1995/* */
1996/* Routine Description: */
1997/* */
1998/* Cleanup after a passthru command */
1999/* */
2000/****************************************************************************/
2001static void
2002ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
2003{
2004 ips_passthru_t *pt;
2005
2006 METHOD_TRACE("ips_cleanup_passthru", 1);
2007
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002008 if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
2010 ips_name, ha->host_num);
2011
2012 return;
2013 }
2014 pt = (ips_passthru_t *) ha->ioctl_data;
2015
2016 /* Copy data back to the user */
2017 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) /* Copy DCDB Back to Caller's Area */
2018 memcpy(&pt->CoppCP.dcdb, &scb->dcdb, sizeof (IPS_DCDB_TABLE));
2019
2020 pt->BasicStatus = scb->basic_status;
2021 pt->ExtendedStatus = scb->extended_status;
2022 pt->AdapterType = ha->ad_type;
2023
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002024 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 (scb->cmd.flashfw.op_code == IPS_CMD_DOWNLOAD ||
2026 scb->cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW))
2027 ips_free_flash_copperhead(ha);
2028
2029 ips_scmd_buf_write(scb->scsi_cmd, ha->ioctl_data, ha->ioctl_datasize);
2030}
2031
2032/****************************************************************************/
2033/* */
2034/* Routine Name: ips_host_info */
2035/* */
2036/* Routine Description: */
2037/* */
2038/* The passthru interface for the driver */
2039/* */
2040/****************************************************************************/
2041static int
2042ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
2043{
2044 IPS_INFOSTR info;
2045
2046 METHOD_TRACE("ips_host_info", 1);
2047
2048 info.buffer = ptr;
2049 info.length = len;
2050 info.offset = offset;
2051 info.pos = 0;
2052 info.localpos = 0;
2053
2054 copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
2055
2056 if ((le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) &&
2057 (le16_to_cpu(ha->nvram->adapter_type) != 0))
2058 copy_info(&info, "\tController Type : %s\n",
2059 ips_adapter_name[ha->ad_type - 1]);
2060 else
2061 copy_info(&info,
2062 "\tController Type : Unknown\n");
2063
2064 if (ha->io_addr)
2065 copy_info(&info,
2066 "\tIO region : 0x%lx (%d bytes)\n",
2067 ha->io_addr, ha->io_len);
2068
2069 if (ha->mem_addr) {
2070 copy_info(&info,
2071 "\tMemory region : 0x%lx (%d bytes)\n",
2072 ha->mem_addr, ha->mem_len);
2073 copy_info(&info,
2074 "\tShared memory address : 0x%lx\n",
2075 ha->mem_ptr);
2076 }
2077
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002078 copy_info(&info, "\tIRQ number : %d\n", ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
2080 /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
2081 /* That keeps everything happy for "text" operations on the proc file. */
2082
2083 if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08002084 if (ha->nvram->bios_low[3] == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 copy_info(&info,
2086 "\tBIOS Version : %c%c%c%c%c%c%c\n",
2087 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
2088 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
2089 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
2090 ha->nvram->bios_low[2]);
2091
2092 } else {
2093 copy_info(&info,
2094 "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
2095 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
2096 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
2097 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
2098 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
2099 }
2100
2101 }
2102
2103 if (ha->enq->CodeBlkVersion[7] == 0) {
2104 copy_info(&info,
2105 "\tFirmware Version : %c%c%c%c%c%c%c\n",
2106 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
2107 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
2108 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
2109 ha->enq->CodeBlkVersion[6]);
2110 } else {
2111 copy_info(&info,
2112 "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
2113 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
2114 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
2115 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
2116 ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
2117 }
2118
2119 if (ha->enq->BootBlkVersion[7] == 0) {
2120 copy_info(&info,
2121 "\tBoot Block Version : %c%c%c%c%c%c%c\n",
2122 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
2123 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
2124 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
2125 ha->enq->BootBlkVersion[6]);
2126 } else {
2127 copy_info(&info,
2128 "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
2129 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
2130 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
2131 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
2132 ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
2133 }
2134
2135 copy_info(&info, "\tDriver Version : %s%s\n",
2136 IPS_VERSION_HIGH, IPS_VERSION_LOW);
2137
2138 copy_info(&info, "\tDriver Build : %d\n",
2139 IPS_BUILD_IDENT);
2140
2141 copy_info(&info, "\tMax Physical Devices : %d\n",
2142 ha->enq->ucMaxPhysicalDevices);
2143 copy_info(&info, "\tMax Active Commands : %d\n",
2144 ha->max_cmds);
2145 copy_info(&info, "\tCurrent Queued Commands : %d\n",
2146 ha->scb_waitlist.count);
2147 copy_info(&info, "\tCurrent Active Commands : %d\n",
2148 ha->scb_activelist.count - ha->num_ioctl);
2149 copy_info(&info, "\tCurrent Queued PT Commands : %d\n",
2150 ha->copp_waitlist.count);
2151 copy_info(&info, "\tCurrent Active PT Commands : %d\n",
2152 ha->num_ioctl);
2153
2154 copy_info(&info, "\n");
2155
2156 return (info.localpos);
2157}
2158
2159/****************************************************************************/
2160/* */
2161/* Routine Name: copy_mem_info */
2162/* */
2163/* Routine Description: */
2164/* */
2165/* Copy data into an IPS_INFOSTR structure */
2166/* */
2167/****************************************************************************/
2168static void
2169copy_mem_info(IPS_INFOSTR * info, char *data, int len)
2170{
2171 METHOD_TRACE("copy_mem_info", 1);
2172
2173 if (info->pos + len < info->offset) {
2174 info->pos += len;
2175 return;
2176 }
2177
2178 if (info->pos < info->offset) {
2179 data += (info->offset - info->pos);
2180 len -= (info->offset - info->pos);
2181 info->pos += (info->offset - info->pos);
2182 }
2183
2184 if (info->localpos + len > info->length)
2185 len = info->length - info->localpos;
2186
2187 if (len > 0) {
2188 memcpy(info->buffer + info->localpos, data, len);
2189 info->pos += len;
2190 info->localpos += len;
2191 }
2192}
2193
2194/****************************************************************************/
2195/* */
2196/* Routine Name: copy_info */
2197/* */
2198/* Routine Description: */
2199/* */
2200/* printf style wrapper for an info structure */
2201/* */
2202/****************************************************************************/
2203static int
2204copy_info(IPS_INFOSTR * info, char *fmt, ...)
2205{
2206 va_list args;
2207 char buf[128];
2208 int len;
2209
2210 METHOD_TRACE("copy_info", 1);
2211
2212 va_start(args, fmt);
2213 len = vsprintf(buf, fmt, args);
2214 va_end(args);
2215
2216 copy_mem_info(info, buf, len);
2217
2218 return (len);
2219}
2220
2221/****************************************************************************/
2222/* */
2223/* Routine Name: ips_identify_controller */
2224/* */
2225/* Routine Description: */
2226/* */
2227/* Identify this controller */
2228/* */
2229/****************************************************************************/
2230static void
2231ips_identify_controller(ips_ha_t * ha)
2232{
2233 METHOD_TRACE("ips_identify_controller", 1);
2234
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002235 switch (ha->pcidev->device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 case IPS_DEVICEID_COPPERHEAD:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002237 if (ha->pcidev->revision <= IPS_REVID_SERVERAID) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 ha->ad_type = IPS_ADTYPE_SERVERAID;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002239 } else if (ha->pcidev->revision == IPS_REVID_SERVERAID2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 ha->ad_type = IPS_ADTYPE_SERVERAID2;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002241 } else if (ha->pcidev->revision == IPS_REVID_NAVAJO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 ha->ad_type = IPS_ADTYPE_NAVAJO;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002243 } else if ((ha->pcidev->revision == IPS_REVID_SERVERAID2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 && (ha->slot_num == 0)) {
2245 ha->ad_type = IPS_ADTYPE_KIOWA;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002246 } else if ((ha->pcidev->revision >= IPS_REVID_CLARINETP1) &&
2247 (ha->pcidev->revision <= IPS_REVID_CLARINETP3)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 if (ha->enq->ucMaxPhysicalDevices == 15)
2249 ha->ad_type = IPS_ADTYPE_SERVERAID3L;
2250 else
2251 ha->ad_type = IPS_ADTYPE_SERVERAID3;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002252 } else if ((ha->pcidev->revision >= IPS_REVID_TROMBONE32) &&
2253 (ha->pcidev->revision <= IPS_REVID_TROMBONE64)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 ha->ad_type = IPS_ADTYPE_SERVERAID4H;
2255 }
2256 break;
2257
2258 case IPS_DEVICEID_MORPHEUS:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002259 switch (ha->pcidev->subsystem_device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 case IPS_SUBDEVICEID_4L:
2261 ha->ad_type = IPS_ADTYPE_SERVERAID4L;
2262 break;
2263
2264 case IPS_SUBDEVICEID_4M:
2265 ha->ad_type = IPS_ADTYPE_SERVERAID4M;
2266 break;
2267
2268 case IPS_SUBDEVICEID_4MX:
2269 ha->ad_type = IPS_ADTYPE_SERVERAID4MX;
2270 break;
2271
2272 case IPS_SUBDEVICEID_4LX:
2273 ha->ad_type = IPS_ADTYPE_SERVERAID4LX;
2274 break;
2275
2276 case IPS_SUBDEVICEID_5I2:
2277 ha->ad_type = IPS_ADTYPE_SERVERAID5I2;
2278 break;
2279
2280 case IPS_SUBDEVICEID_5I1:
2281 ha->ad_type = IPS_ADTYPE_SERVERAID5I1;
2282 break;
2283 }
2284
2285 break;
2286
2287 case IPS_DEVICEID_MARCO:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002288 switch (ha->pcidev->subsystem_device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 case IPS_SUBDEVICEID_6M:
2290 ha->ad_type = IPS_ADTYPE_SERVERAID6M;
2291 break;
2292 case IPS_SUBDEVICEID_6I:
2293 ha->ad_type = IPS_ADTYPE_SERVERAID6I;
2294 break;
2295 case IPS_SUBDEVICEID_7k:
2296 ha->ad_type = IPS_ADTYPE_SERVERAID7k;
2297 break;
2298 case IPS_SUBDEVICEID_7M:
2299 ha->ad_type = IPS_ADTYPE_SERVERAID7M;
2300 break;
2301 }
2302 break;
2303 }
2304}
2305
2306/****************************************************************************/
2307/* */
2308/* Routine Name: ips_get_bios_version */
2309/* */
2310/* Routine Description: */
2311/* */
2312/* Get the BIOS revision number */
2313/* */
2314/****************************************************************************/
2315static void
2316ips_get_bios_version(ips_ha_t * ha, int intr)
2317{
2318 ips_scb_t *scb;
2319 int ret;
2320 uint8_t major;
2321 uint8_t minor;
2322 uint8_t subminor;
2323 uint8_t *buffer;
2324 char hexDigits[] =
2325 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
2326 'D', 'E', 'F' };
2327
2328 METHOD_TRACE("ips_get_bios_version", 1);
2329
2330 major = 0;
2331 minor = 0;
2332
2333 strncpy(ha->bios_version, " ?", 8);
2334
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002335 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 if (IPS_USE_MEMIO(ha)) {
2337 /* Memory Mapped I/O */
2338
2339 /* test 1st byte */
2340 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002341 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 udelay(25); /* 25 us */
2343
2344 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
2345 return;
2346
2347 writel(1, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002348 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 udelay(25); /* 25 us */
2350
2351 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
2352 return;
2353
2354 /* Get Major version */
2355 writel(0x1FF, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002356 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 udelay(25); /* 25 us */
2358
2359 major = readb(ha->mem_ptr + IPS_REG_FLDP);
2360
2361 /* Get Minor version */
2362 writel(0x1FE, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002363 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 udelay(25); /* 25 us */
2365 minor = readb(ha->mem_ptr + IPS_REG_FLDP);
2366
2367 /* Get SubMinor version */
2368 writel(0x1FD, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002369 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 udelay(25); /* 25 us */
2371 subminor = readb(ha->mem_ptr + IPS_REG_FLDP);
2372
2373 } else {
2374 /* Programmed I/O */
2375
2376 /* test 1st byte */
2377 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002378 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 udelay(25); /* 25 us */
2380
2381 if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
2382 return;
2383
2384 outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002385 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 udelay(25); /* 25 us */
2387
2388 if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
2389 return;
2390
2391 /* Get Major version */
2392 outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002393 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 udelay(25); /* 25 us */
2395
2396 major = inb(ha->io_addr + IPS_REG_FLDP);
2397
2398 /* Get Minor version */
2399 outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002400 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 udelay(25); /* 25 us */
2402
2403 minor = inb(ha->io_addr + IPS_REG_FLDP);
2404
2405 /* Get SubMinor version */
2406 outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002407 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 udelay(25); /* 25 us */
2409
2410 subminor = inb(ha->io_addr + IPS_REG_FLDP);
2411
2412 }
2413 } else {
2414 /* Morpheus Family - Send Command to the card */
2415
2416 buffer = ha->ioctl_data;
2417
2418 memset(buffer, 0, 0x1000);
2419
2420 scb = &ha->scbs[ha->max_cmds - 1];
2421
2422 ips_init_scb(ha, scb);
2423
2424 scb->timeout = ips_cmd_timeout;
2425 scb->cdb[0] = IPS_CMD_RW_BIOSFW;
2426
2427 scb->cmd.flashfw.op_code = IPS_CMD_RW_BIOSFW;
2428 scb->cmd.flashfw.command_id = IPS_COMMAND_ID(ha, scb);
2429 scb->cmd.flashfw.type = 1;
2430 scb->cmd.flashfw.direction = 0;
2431 scb->cmd.flashfw.count = cpu_to_le32(0x800);
2432 scb->cmd.flashfw.total_packets = 1;
2433 scb->cmd.flashfw.packet_num = 0;
2434 scb->data_len = 0x1000;
2435 scb->cmd.flashfw.buffer_addr = ha->ioctl_busaddr;
2436
2437 /* issue the command */
2438 if (((ret =
2439 ips_send_wait(ha, scb, ips_cmd_timeout,
2440 intr)) == IPS_FAILURE)
2441 || (ret == IPS_SUCCESS_IMM)
2442 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
2443 /* Error occurred */
2444
2445 return;
2446 }
2447
2448 if ((buffer[0xC0] == 0x55) && (buffer[0xC1] == 0xAA)) {
2449 major = buffer[0x1ff + 0xC0]; /* Offset 0x1ff after the header (0xc0) */
2450 minor = buffer[0x1fe + 0xC0]; /* Offset 0x1fe after the header (0xc0) */
2451 subminor = buffer[0x1fd + 0xC0]; /* Offset 0x1fd after the header (0xc0) */
2452 } else {
2453 return;
2454 }
2455 }
2456
2457 ha->bios_version[0] = hexDigits[(major & 0xF0) >> 4];
2458 ha->bios_version[1] = '.';
2459 ha->bios_version[2] = hexDigits[major & 0x0F];
2460 ha->bios_version[3] = hexDigits[subminor];
2461 ha->bios_version[4] = '.';
2462 ha->bios_version[5] = hexDigits[(minor & 0xF0) >> 4];
2463 ha->bios_version[6] = hexDigits[minor & 0x0F];
2464 ha->bios_version[7] = 0;
2465}
2466
2467/****************************************************************************/
2468/* */
2469/* Routine Name: ips_hainit */
2470/* */
2471/* Routine Description: */
2472/* */
2473/* Initialize the controller */
2474/* */
2475/* NOTE: Assumes to be called from with a lock */
2476/* */
2477/****************************************************************************/
2478static int
2479ips_hainit(ips_ha_t * ha)
2480{
2481 int i;
2482 struct timeval tv;
2483
2484 METHOD_TRACE("ips_hainit", 1);
2485
2486 if (!ha)
2487 return (0);
2488
2489 if (ha->func.statinit)
2490 (*ha->func.statinit) (ha);
2491
2492 if (ha->func.enableint)
2493 (*ha->func.enableint) (ha);
2494
2495 /* Send FFDC */
2496 ha->reset_count = 1;
2497 do_gettimeofday(&tv);
2498 ha->last_ffdc = tv.tv_sec;
2499 ips_ffdc_reset(ha, IPS_INTR_IORL);
2500
2501 if (!ips_read_config(ha, IPS_INTR_IORL)) {
2502 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2503 "unable to read config from controller.\n");
2504
2505 return (0);
2506 }
2507 /* end if */
2508 if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) {
2509 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2510 "unable to read controller status.\n");
2511
2512 return (0);
2513 }
2514
2515 /* Identify this controller */
2516 ips_identify_controller(ha);
2517
2518 if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
2519 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2520 "unable to read subsystem parameters.\n");
2521
2522 return (0);
2523 }
2524
2525 /* write nvram user page 5 */
2526 if (!ips_write_driver_status(ha, IPS_INTR_IORL)) {
2527 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2528 "unable to write driver info to controller.\n");
2529
2530 return (0);
2531 }
2532
2533 /* If there are Logical Drives and a Reset Occurred, then an EraseStripeLock is Needed */
2534 if ((ha->conf->ucLogDriveCount > 0) && (ha->requires_esl == 1))
2535 ips_clear_adapter(ha, IPS_INTR_IORL);
2536
2537 /* set limits on SID, LUN, BUS */
2538 ha->ntargets = IPS_MAX_TARGETS + 1;
2539 ha->nlun = 1;
2540 ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS) + 1;
2541
2542 switch (ha->conf->logical_drive[0].ucStripeSize) {
2543 case 4:
2544 ha->max_xfer = 0x10000;
2545 break;
2546
2547 case 5:
2548 ha->max_xfer = 0x20000;
2549 break;
2550
2551 case 6:
2552 ha->max_xfer = 0x40000;
2553 break;
2554
2555 case 7:
2556 default:
2557 ha->max_xfer = 0x80000;
2558 break;
2559 }
2560
2561 /* setup max concurrent commands */
2562 if (le32_to_cpu(ha->subsys->param[4]) & 0x1) {
2563 /* Use the new method */
2564 ha->max_cmds = ha->enq->ucConcurrentCmdCount;
2565 } else {
2566 /* use the old method */
2567 switch (ha->conf->logical_drive[0].ucStripeSize) {
2568 case 4:
2569 ha->max_cmds = 32;
2570 break;
2571
2572 case 5:
2573 ha->max_cmds = 16;
2574 break;
2575
2576 case 6:
2577 ha->max_cmds = 8;
2578 break;
2579
2580 case 7:
2581 default:
2582 ha->max_cmds = 4;
2583 break;
2584 }
2585 }
2586
2587 /* Limit the Active Commands on a Lite Adapter */
2588 if ((ha->ad_type == IPS_ADTYPE_SERVERAID3L) ||
2589 (ha->ad_type == IPS_ADTYPE_SERVERAID4L) ||
2590 (ha->ad_type == IPS_ADTYPE_SERVERAID4LX)) {
2591 if ((ha->max_cmds > MaxLiteCmds) && (MaxLiteCmds))
2592 ha->max_cmds = MaxLiteCmds;
2593 }
2594
2595 /* set controller IDs */
2596 ha->ha_id[0] = IPS_ADAPTER_ID;
2597 for (i = 1; i < ha->nbus; i++) {
2598 ha->ha_id[i] = ha->conf->init_id[i - 1] & 0x1f;
2599 ha->dcdb_active[i - 1] = 0;
2600 }
2601
2602 return (1);
2603}
2604
2605/****************************************************************************/
2606/* */
2607/* Routine Name: ips_next */
2608/* */
2609/* Routine Description: */
2610/* */
2611/* Take the next command off the queue and send it to the controller */
2612/* */
2613/****************************************************************************/
2614static void
2615ips_next(ips_ha_t * ha, int intr)
2616{
2617 ips_scb_t *scb;
Henne1516b552006-10-02 14:56:23 +02002618 struct scsi_cmnd *SC;
2619 struct scsi_cmnd *p;
2620 struct scsi_cmnd *q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 ips_copp_wait_item_t *item;
2622 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 struct Scsi_Host *host;
2624 METHOD_TRACE("ips_next", 1);
2625
2626 if (!ha)
2627 return;
2628 host = ips_sh[ha->host_num];
2629 /*
2630 * Block access to the queue function so
2631 * this command won't time out
2632 */
2633 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002634 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 if ((ha->subsys->param[3] & 0x300000)
2637 && (ha->scb_activelist.count == 0)) {
2638 struct timeval tv;
2639
2640 do_gettimeofday(&tv);
2641
2642 if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
2643 ha->last_ffdc = tv.tv_sec;
2644 ips_ffdc_time(ha);
2645 }
2646 }
2647
2648 /*
2649 * Send passthru commands
2650 * These have priority over normal I/O
2651 * but shouldn't affect performance too much
2652 * since we limit the number that can be active
2653 * on the card at any one time
2654 */
2655 while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
2656 (ha->copp_waitlist.head) && (scb = ips_getscb(ha))) {
2657
2658 item = ips_removeq_copp_head(&ha->copp_waitlist);
2659 ha->num_ioctl++;
2660 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002661 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 scb->scsi_cmd = item->scsi_cmd;
2663 kfree(item);
2664
2665 ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
2666
2667 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002668 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 switch (ret) {
2670 case IPS_FAILURE:
2671 if (scb->scsi_cmd) {
2672 scb->scsi_cmd->result = DID_ERROR << 16;
2673 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2674 }
2675
2676 ips_freescb(ha, scb);
2677 break;
2678 case IPS_SUCCESS_IMM:
2679 if (scb->scsi_cmd) {
2680 scb->scsi_cmd->result = DID_OK << 16;
2681 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2682 }
2683
2684 ips_freescb(ha, scb);
2685 break;
2686 default:
2687 break;
2688 } /* end case */
2689
2690 if (ret != IPS_SUCCESS) {
2691 ha->num_ioctl--;
2692 continue;
2693 }
2694
2695 ret = ips_send_cmd(ha, scb);
2696
2697 if (ret == IPS_SUCCESS)
2698 ips_putq_scb_head(&ha->scb_activelist, scb);
2699 else
2700 ha->num_ioctl--;
2701
2702 switch (ret) {
2703 case IPS_FAILURE:
2704 if (scb->scsi_cmd) {
2705 scb->scsi_cmd->result = DID_ERROR << 16;
2706 }
2707
2708 ips_freescb(ha, scb);
2709 break;
2710 case IPS_SUCCESS_IMM:
2711 ips_freescb(ha, scb);
2712 break;
2713 default:
2714 break;
2715 } /* end case */
2716
2717 }
2718
2719 /*
2720 * Send "Normal" I/O commands
2721 */
2722
2723 p = ha->scb_waitlist.head;
2724 while ((p) && (scb = ips_getscb(ha))) {
Jeff Garzik422c0d62005-10-24 18:05:09 -04002725 if ((scmd_channel(p) > 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 && (ha->
Jeff Garzik422c0d62005-10-24 18:05:09 -04002727 dcdb_active[scmd_channel(p) -
2728 1] & (1 << scmd_id(p)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 ips_freescb(ha, scb);
Henne1516b552006-10-02 14:56:23 +02002730 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 continue;
2732 }
2733
2734 q = p;
2735 SC = ips_removeq_wait(&ha->scb_waitlist, q);
2736
2737 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002738 spin_unlock(host->host_lock); /* Unlock HA after command is taken off queue */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 SC->result = DID_OK;
2741 SC->host_scribble = NULL;
2742
2743 memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer));
2744
2745 scb->target_id = SC->device->id;
2746 scb->lun = SC->device->lun;
2747 scb->bus = SC->device->channel;
2748 scb->scsi_cmd = SC;
2749 scb->breakup = 0;
2750 scb->data_len = 0;
2751 scb->callback = ipsintr_done;
2752 scb->timeout = ips_cmd_timeout;
2753 memset(&scb->cmd, 0, 16);
2754
2755 /* copy in the CDB */
2756 memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
2757
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002758 scb->sg_count = scsi_dma_map(SC);
2759 BUG_ON(scb->sg_count < 0);
2760 if (scb->sg_count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 struct scatterlist *sg;
2762 int i;
2763
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 scb->flags |= IPS_SCB_MAP_SG;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002765
2766 scsi_for_each_sg(SC, sg, scb->sg_count, i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 if (ips_fill_scb_sg_single
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002768 (ha, sg_dma_address(sg), scb, i,
2769 sg_dma_len(sg)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 break;
2771 }
2772 scb->dcdb.transfer_length = scb->data_len;
2773 } else {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002774 scb->data_busaddr = 0L;
2775 scb->sg_len = 0;
2776 scb->data_len = 0;
2777 scb->dcdb.transfer_length = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 }
2779
2780 scb->dcdb.cmd_attribute =
2781 ips_command_direction[scb->scsi_cmd->cmnd[0]];
2782
Jeff Garzik2f277d62007-12-13 16:14:08 -08002783 /* Allow a WRITE BUFFER Command to Have no Data */
2784 /* This is Used by Tape Flash Utilites */
2785 if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) &&
2786 (scb->data_len == 0))
2787 scb->dcdb.cmd_attribute = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788
2789 if (!(scb->dcdb.cmd_attribute & 0x3))
2790 scb->dcdb.transfer_length = 0;
2791
2792 if (scb->data_len >= IPS_MAX_XFER) {
2793 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
2794 scb->dcdb.transfer_length = 0;
2795 }
2796 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002797 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 ret = ips_send_cmd(ha, scb);
2800
2801 switch (ret) {
2802 case IPS_SUCCESS:
2803 ips_putq_scb_head(&ha->scb_activelist, scb);
2804 break;
2805 case IPS_FAILURE:
2806 if (scb->scsi_cmd) {
2807 scb->scsi_cmd->result = DID_ERROR << 16;
2808 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2809 }
2810
2811 if (scb->bus)
2812 ha->dcdb_active[scb->bus - 1] &=
2813 ~(1 << scb->target_id);
2814
2815 ips_freescb(ha, scb);
2816 break;
2817 case IPS_SUCCESS_IMM:
2818 if (scb->scsi_cmd)
2819 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2820
2821 if (scb->bus)
2822 ha->dcdb_active[scb->bus - 1] &=
2823 ~(1 << scb->target_id);
2824
2825 ips_freescb(ha, scb);
2826 break;
2827 default:
2828 break;
2829 } /* end case */
2830
Henne1516b552006-10-02 14:56:23 +02002831 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
2833 } /* end while */
2834
2835 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002836 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837}
2838
2839/****************************************************************************/
2840/* */
2841/* Routine Name: ips_putq_scb_head */
2842/* */
2843/* Routine Description: */
2844/* */
2845/* Add an item to the head of the queue */
2846/* */
2847/* ASSUMED to be called from within the HA lock */
2848/* */
2849/****************************************************************************/
2850static void
2851ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
2852{
2853 METHOD_TRACE("ips_putq_scb_head", 1);
2854
2855 if (!item)
2856 return;
2857
2858 item->q_next = queue->head;
2859 queue->head = item;
2860
2861 if (!queue->tail)
2862 queue->tail = item;
2863
2864 queue->count++;
2865}
2866
2867/****************************************************************************/
2868/* */
2869/* Routine Name: ips_removeq_scb_head */
2870/* */
2871/* Routine Description: */
2872/* */
2873/* Remove the head of the queue */
2874/* */
2875/* ASSUMED to be called from within the HA lock */
2876/* */
2877/****************************************************************************/
2878static ips_scb_t *
2879ips_removeq_scb_head(ips_scb_queue_t * queue)
2880{
2881 ips_scb_t *item;
2882
2883 METHOD_TRACE("ips_removeq_scb_head", 1);
2884
2885 item = queue->head;
2886
2887 if (!item) {
2888 return (NULL);
2889 }
2890
2891 queue->head = item->q_next;
2892 item->q_next = NULL;
2893
2894 if (queue->tail == item)
2895 queue->tail = NULL;
2896
2897 queue->count--;
2898
2899 return (item);
2900}
2901
2902/****************************************************************************/
2903/* */
2904/* Routine Name: ips_removeq_scb */
2905/* */
2906/* Routine Description: */
2907/* */
2908/* Remove an item from a queue */
2909/* */
2910/* ASSUMED to be called from within the HA lock */
2911/* */
2912/****************************************************************************/
2913static ips_scb_t *
2914ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
2915{
2916 ips_scb_t *p;
2917
2918 METHOD_TRACE("ips_removeq_scb", 1);
2919
2920 if (!item)
2921 return (NULL);
2922
2923 if (item == queue->head) {
2924 return (ips_removeq_scb_head(queue));
2925 }
2926
2927 p = queue->head;
2928
2929 while ((p) && (item != p->q_next))
2930 p = p->q_next;
2931
2932 if (p) {
2933 /* found a match */
2934 p->q_next = item->q_next;
2935
2936 if (!item->q_next)
2937 queue->tail = p;
2938
2939 item->q_next = NULL;
2940 queue->count--;
2941
2942 return (item);
2943 }
2944
2945 return (NULL);
2946}
2947
2948/****************************************************************************/
2949/* */
2950/* Routine Name: ips_putq_wait_tail */
2951/* */
2952/* Routine Description: */
2953/* */
2954/* Add an item to the tail of the queue */
2955/* */
2956/* ASSUMED to be called from within the HA lock */
2957/* */
2958/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02002959static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960{
2961 METHOD_TRACE("ips_putq_wait_tail", 1);
2962
2963 if (!item)
2964 return;
2965
2966 item->host_scribble = NULL;
2967
2968 if (queue->tail)
2969 queue->tail->host_scribble = (char *) item;
2970
2971 queue->tail = item;
2972
2973 if (!queue->head)
2974 queue->head = item;
2975
2976 queue->count++;
2977}
2978
2979/****************************************************************************/
2980/* */
2981/* Routine Name: ips_removeq_wait_head */
2982/* */
2983/* Routine Description: */
2984/* */
2985/* Remove the head of the queue */
2986/* */
2987/* ASSUMED to be called from within the HA lock */
2988/* */
2989/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02002990static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991{
Henne1516b552006-10-02 14:56:23 +02002992 struct scsi_cmnd *item;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
2994 METHOD_TRACE("ips_removeq_wait_head", 1);
2995
2996 item = queue->head;
2997
2998 if (!item) {
2999 return (NULL);
3000 }
3001
Henne1516b552006-10-02 14:56:23 +02003002 queue->head = (struct scsi_cmnd *) item->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 item->host_scribble = NULL;
3004
3005 if (queue->tail == item)
3006 queue->tail = NULL;
3007
3008 queue->count--;
3009
3010 return (item);
3011}
3012
3013/****************************************************************************/
3014/* */
3015/* Routine Name: ips_removeq_wait */
3016/* */
3017/* Routine Description: */
3018/* */
3019/* Remove an item from a queue */
3020/* */
3021/* ASSUMED to be called from within the HA lock */
3022/* */
3023/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02003024static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
3025 struct scsi_cmnd *item)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026{
Henne1516b552006-10-02 14:56:23 +02003027 struct scsi_cmnd *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
3029 METHOD_TRACE("ips_removeq_wait", 1);
3030
3031 if (!item)
3032 return (NULL);
3033
3034 if (item == queue->head) {
3035 return (ips_removeq_wait_head(queue));
3036 }
3037
3038 p = queue->head;
3039
Henne1516b552006-10-02 14:56:23 +02003040 while ((p) && (item != (struct scsi_cmnd *) p->host_scribble))
3041 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042
3043 if (p) {
3044 /* found a match */
3045 p->host_scribble = item->host_scribble;
3046
3047 if (!item->host_scribble)
3048 queue->tail = p;
3049
3050 item->host_scribble = NULL;
3051 queue->count--;
3052
3053 return (item);
3054 }
3055
3056 return (NULL);
3057}
3058
3059/****************************************************************************/
3060/* */
3061/* Routine Name: ips_putq_copp_tail */
3062/* */
3063/* Routine Description: */
3064/* */
3065/* Add an item to the tail of the queue */
3066/* */
3067/* ASSUMED to be called from within the HA lock */
3068/* */
3069/****************************************************************************/
3070static void
3071ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
3072{
3073 METHOD_TRACE("ips_putq_copp_tail", 1);
3074
3075 if (!item)
3076 return;
3077
3078 item->next = NULL;
3079
3080 if (queue->tail)
3081 queue->tail->next = item;
3082
3083 queue->tail = item;
3084
3085 if (!queue->head)
3086 queue->head = item;
3087
3088 queue->count++;
3089}
3090
3091/****************************************************************************/
3092/* */
3093/* Routine Name: ips_removeq_copp_head */
3094/* */
3095/* Routine Description: */
3096/* */
3097/* Remove the head of the queue */
3098/* */
3099/* ASSUMED to be called from within the HA lock */
3100/* */
3101/****************************************************************************/
3102static ips_copp_wait_item_t *
3103ips_removeq_copp_head(ips_copp_queue_t * queue)
3104{
3105 ips_copp_wait_item_t *item;
3106
3107 METHOD_TRACE("ips_removeq_copp_head", 1);
3108
3109 item = queue->head;
3110
3111 if (!item) {
3112 return (NULL);
3113 }
3114
3115 queue->head = item->next;
3116 item->next = NULL;
3117
3118 if (queue->tail == item)
3119 queue->tail = NULL;
3120
3121 queue->count--;
3122
3123 return (item);
3124}
3125
3126/****************************************************************************/
3127/* */
3128/* Routine Name: ips_removeq_copp */
3129/* */
3130/* Routine Description: */
3131/* */
3132/* Remove an item from a queue */
3133/* */
3134/* ASSUMED to be called from within the HA lock */
3135/* */
3136/****************************************************************************/
3137static ips_copp_wait_item_t *
3138ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
3139{
3140 ips_copp_wait_item_t *p;
3141
3142 METHOD_TRACE("ips_removeq_copp", 1);
3143
3144 if (!item)
3145 return (NULL);
3146
3147 if (item == queue->head) {
3148 return (ips_removeq_copp_head(queue));
3149 }
3150
3151 p = queue->head;
3152
3153 while ((p) && (item != p->next))
3154 p = p->next;
3155
3156 if (p) {
3157 /* found a match */
3158 p->next = item->next;
3159
3160 if (!item->next)
3161 queue->tail = p;
3162
3163 item->next = NULL;
3164 queue->count--;
3165
3166 return (item);
3167 }
3168
3169 return (NULL);
3170}
3171
3172/****************************************************************************/
3173/* */
3174/* Routine Name: ipsintr_blocking */
3175/* */
3176/* Routine Description: */
3177/* */
3178/* Finalize an interrupt for internal commands */
3179/* */
3180/****************************************************************************/
3181static void
3182ipsintr_blocking(ips_ha_t * ha, ips_scb_t * scb)
3183{
3184 METHOD_TRACE("ipsintr_blocking", 2);
3185
3186 ips_freescb(ha, scb);
3187 if ((ha->waitflag == TRUE) && (ha->cmd_in_progress == scb->cdb[0])) {
3188 ha->waitflag = FALSE;
3189
3190 return;
3191 }
3192}
3193
3194/****************************************************************************/
3195/* */
3196/* Routine Name: ipsintr_done */
3197/* */
3198/* Routine Description: */
3199/* */
3200/* Finalize an interrupt for non-internal commands */
3201/* */
3202/****************************************************************************/
3203static void
3204ipsintr_done(ips_ha_t * ha, ips_scb_t * scb)
3205{
3206 METHOD_TRACE("ipsintr_done", 2);
3207
3208 if (!scb) {
3209 IPS_PRINTK(KERN_WARNING, ha->pcidev,
3210 "Spurious interrupt; scb NULL.\n");
3211
3212 return;
3213 }
3214
3215 if (scb->scsi_cmd == NULL) {
3216 /* unexpected interrupt */
3217 IPS_PRINTK(KERN_WARNING, ha->pcidev,
3218 "Spurious interrupt; scsi_cmd not set.\n");
3219
3220 return;
3221 }
3222
3223 ips_done(ha, scb);
3224}
3225
3226/****************************************************************************/
3227/* */
3228/* Routine Name: ips_done */
3229/* */
3230/* Routine Description: */
3231/* */
3232/* Do housekeeping on completed commands */
3233/* ASSUMED to be called form within the request lock */
3234/****************************************************************************/
3235static void
3236ips_done(ips_ha_t * ha, ips_scb_t * scb)
3237{
3238 int ret;
3239
3240 METHOD_TRACE("ips_done", 1);
3241
3242 if (!scb)
3243 return;
3244
3245 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
3246 ips_cleanup_passthru(ha, scb);
3247 ha->num_ioctl--;
3248 } else {
3249 /*
3250 * Check to see if this command had too much
3251 * data and had to be broke up. If so, queue
3252 * the rest of the data and continue.
3253 */
3254 if ((scb->breakup) || (scb->sg_break)) {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003255 struct scatterlist *sg;
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003256 int i, sg_dma_index, ips_sg_index = 0;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003257
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 /* we had a data breakup */
3259 scb->data_len = 0;
3260
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003261 sg = scsi_sglist(scb->scsi_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003263 /* Spin forward to last dma chunk */
3264 sg_dma_index = scb->breakup;
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003265 for (i = 0; i < scb->breakup; i++)
3266 sg = sg_next(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003268 /* Take care of possible partial on last chunk */
3269 ips_fill_scb_sg_single(ha,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003270 sg_dma_address(sg),
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003271 scb, ips_sg_index++,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003272 sg_dma_len(sg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003274 for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003275 sg_dma_index++, sg = sg_next(sg)) {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003276 if (ips_fill_scb_sg_single
3277 (ha,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003278 sg_dma_address(sg),
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003279 scb, ips_sg_index++,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003280 sg_dma_len(sg)) < 0)
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003281 break;
3282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
3284 scb->dcdb.transfer_length = scb->data_len;
3285 scb->dcdb.cmd_attribute |=
3286 ips_command_direction[scb->scsi_cmd->cmnd[0]];
3287
3288 if (!(scb->dcdb.cmd_attribute & 0x3))
3289 scb->dcdb.transfer_length = 0;
3290
3291 if (scb->data_len >= IPS_MAX_XFER) {
3292 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
3293 scb->dcdb.transfer_length = 0;
3294 }
3295
3296 ret = ips_send_cmd(ha, scb);
3297
3298 switch (ret) {
3299 case IPS_FAILURE:
3300 if (scb->scsi_cmd) {
3301 scb->scsi_cmd->result = DID_ERROR << 16;
3302 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3303 }
3304
3305 ips_freescb(ha, scb);
3306 break;
3307 case IPS_SUCCESS_IMM:
3308 if (scb->scsi_cmd) {
3309 scb->scsi_cmd->result = DID_ERROR << 16;
3310 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3311 }
3312
3313 ips_freescb(ha, scb);
3314 break;
3315 default:
3316 break;
3317 } /* end case */
3318
3319 return;
3320 }
3321 } /* end if passthru */
3322
3323 if (scb->bus) {
3324 ha->dcdb_active[scb->bus - 1] &= ~(1 << scb->target_id);
3325 }
3326
3327 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3328
3329 ips_freescb(ha, scb);
3330}
3331
3332/****************************************************************************/
3333/* */
3334/* Routine Name: ips_map_status */
3335/* */
3336/* Routine Description: */
3337/* */
3338/* Map Controller Error codes to Linux Error Codes */
3339/* */
3340/****************************************************************************/
3341static int
3342ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
3343{
3344 int errcode;
3345 int device_error;
3346 uint32_t transfer_len;
3347 IPS_DCDB_TABLE_TAPE *tapeDCDB;
Jack Hammera5b3c862006-01-31 13:17:55 -05003348 IPS_SCSI_INQ_DATA inquiryData;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349
3350 METHOD_TRACE("ips_map_status", 1);
3351
3352 if (scb->bus) {
3353 DEBUG_VAR(2,
3354 "(%s%d) Physical device error (%d %d %d): %x %x, Sense Key: %x, ASC: %x, ASCQ: %x",
3355 ips_name, ha->host_num,
3356 scb->scsi_cmd->device->channel,
3357 scb->scsi_cmd->device->id, scb->scsi_cmd->device->lun,
3358 scb->basic_status, scb->extended_status,
3359 scb->extended_status ==
3360 IPS_ERR_CKCOND ? scb->dcdb.sense_info[2] & 0xf : 0,
3361 scb->extended_status ==
3362 IPS_ERR_CKCOND ? scb->dcdb.sense_info[12] : 0,
3363 scb->extended_status ==
3364 IPS_ERR_CKCOND ? scb->dcdb.sense_info[13] : 0);
3365 }
3366
3367 /* default driver error */
3368 errcode = DID_ERROR;
3369 device_error = 0;
3370
3371 switch (scb->basic_status & IPS_GSC_STATUS_MASK) {
3372 case IPS_CMD_TIMEOUT:
3373 errcode = DID_TIME_OUT;
3374 break;
3375
3376 case IPS_INVAL_OPCO:
3377 case IPS_INVAL_CMD_BLK:
3378 case IPS_INVAL_PARM_BLK:
3379 case IPS_LD_ERROR:
3380 case IPS_CMD_CMPLT_WERROR:
3381 break;
3382
3383 case IPS_PHYS_DRV_ERROR:
3384 switch (scb->extended_status) {
3385 case IPS_ERR_SEL_TO:
3386 if (scb->bus)
3387 errcode = DID_NO_CONNECT;
3388
3389 break;
3390
3391 case IPS_ERR_OU_RUN:
3392 if ((scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB) ||
3393 (scb->cmd.dcdb.op_code ==
3394 IPS_CMD_EXTENDED_DCDB_SG)) {
3395 tapeDCDB = (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
3396 transfer_len = tapeDCDB->transfer_length;
3397 } else {
3398 transfer_len =
3399 (uint32_t) scb->dcdb.transfer_length;
3400 }
3401
3402 if ((scb->bus) && (transfer_len < scb->data_len)) {
3403 /* Underrun - set default to no error */
3404 errcode = DID_OK;
3405
3406 /* Restrict access to physical DASD */
Jack Hammera5b3c862006-01-31 13:17:55 -05003407 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08003408 ips_scmd_buf_read(scb->scsi_cmd,
Jack Hammera5b3c862006-01-31 13:17:55 -05003409 &inquiryData, sizeof (inquiryData));
3410 if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
3411 errcode = DID_TIME_OUT;
3412 break;
3413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 }
3415 } else
3416 errcode = DID_ERROR;
3417
3418 break;
3419
3420 case IPS_ERR_RECOVERY:
3421 /* don't fail recovered errors */
3422 if (scb->bus)
3423 errcode = DID_OK;
3424
3425 break;
3426
3427 case IPS_ERR_HOST_RESET:
3428 case IPS_ERR_DEV_RESET:
3429 errcode = DID_RESET;
3430 break;
3431
3432 case IPS_ERR_CKCOND:
3433 if (scb->bus) {
3434 if ((scb->cmd.dcdb.op_code ==
3435 IPS_CMD_EXTENDED_DCDB)
3436 || (scb->cmd.dcdb.op_code ==
3437 IPS_CMD_EXTENDED_DCDB_SG)) {
3438 tapeDCDB =
3439 (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
3440 memcpy(scb->scsi_cmd->sense_buffer,
3441 tapeDCDB->sense_info,
3442 sizeof (scb->scsi_cmd->
3443 sense_buffer));
3444 } else {
3445 memcpy(scb->scsi_cmd->sense_buffer,
3446 scb->dcdb.sense_info,
3447 sizeof (scb->scsi_cmd->
3448 sense_buffer));
3449 }
3450 device_error = 2; /* check condition */
3451 }
3452
3453 errcode = DID_OK;
3454
3455 break;
3456
3457 default:
3458 errcode = DID_ERROR;
3459 break;
3460
3461 } /* end switch */
3462 } /* end switch */
3463
3464 scb->scsi_cmd->result = device_error | (errcode << 16);
3465
3466 return (1);
3467}
3468
3469/****************************************************************************/
3470/* */
3471/* Routine Name: ips_send_wait */
3472/* */
3473/* Routine Description: */
3474/* */
3475/* Send a command to the controller and wait for it to return */
3476/* */
3477/* The FFDC Time Stamp use this function for the callback, but doesn't */
3478/* actually need to wait. */
3479/****************************************************************************/
3480static int
3481ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
3482{
3483 int ret;
3484
3485 METHOD_TRACE("ips_send_wait", 1);
3486
3487 if (intr != IPS_FFDC) { /* Won't be Waiting if this is a Time Stamp */
3488 ha->waitflag = TRUE;
3489 ha->cmd_in_progress = scb->cdb[0];
3490 }
3491 scb->callback = ipsintr_blocking;
3492 ret = ips_send_cmd(ha, scb);
3493
3494 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3495 return (ret);
3496
3497 if (intr != IPS_FFDC) /* Don't Wait around if this is a Time Stamp */
3498 ret = ips_wait(ha, timeout, intr);
3499
3500 return (ret);
3501}
3502
3503/****************************************************************************/
3504/* */
3505/* Routine Name: ips_scmd_buf_write */
3506/* */
3507/* Routine Description: */
Henne1516b552006-10-02 14:56:23 +02003508/* Write data to struct scsi_cmnd request_buffer at proper offsets */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509/****************************************************************************/
3510static void
Henne1516b552006-10-02 14:56:23 +02003511ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512{
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003513 int i;
3514 unsigned int min_cnt, xfer_cnt;
3515 char *cdata = (char *) data;
3516 unsigned char *buffer;
3517 unsigned long flags;
3518 struct scatterlist *sg = scsi_sglist(scmd);
Jack Hammera3632fa2005-10-25 14:13:03 -04003519
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003520 for (i = 0, xfer_cnt = 0;
3521 (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
3522 min_cnt = min(count - xfer_cnt, sg[i].length);
Jack Hammera3632fa2005-10-25 14:13:03 -04003523
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003524 /* kmap_atomic() ensures addressability of the data buffer.*/
3525 /* local_irq_save() protects the KM_IRQ0 address slot. */
3526 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02003527 buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003528 memcpy(buffer, &cdata[xfer_cnt], min_cnt);
3529 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
3530 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003532 xfer_cnt += min_cnt;
3533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534}
3535
3536/****************************************************************************/
3537/* */
3538/* Routine Name: ips_scmd_buf_read */
3539/* */
3540/* Routine Description: */
Henne1516b552006-10-02 14:56:23 +02003541/* Copy data from a struct scsi_cmnd to a new, linear buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542/****************************************************************************/
3543static void
Henne1516b552006-10-02 14:56:23 +02003544ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545{
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003546 int i;
3547 unsigned int min_cnt, xfer_cnt;
3548 char *cdata = (char *) data;
3549 unsigned char *buffer;
3550 unsigned long flags;
3551 struct scatterlist *sg = scsi_sglist(scmd);
Jack Hammera3632fa2005-10-25 14:13:03 -04003552
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003553 for (i = 0, xfer_cnt = 0;
3554 (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
3555 min_cnt = min(count - xfer_cnt, sg[i].length);
Jack Hammera3632fa2005-10-25 14:13:03 -04003556
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003557 /* kmap_atomic() ensures addressability of the data buffer.*/
3558 /* local_irq_save() protects the KM_IRQ0 address slot. */
3559 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02003560 buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003561 memcpy(&cdata[xfer_cnt], buffer, min_cnt);
3562 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
3563 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003565 xfer_cnt += min_cnt;
3566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567}
3568
3569/****************************************************************************/
3570/* */
3571/* Routine Name: ips_send_cmd */
3572/* */
3573/* Routine Description: */
3574/* */
3575/* Map SCSI commands to ServeRAID commands for logical drives */
3576/* */
3577/****************************************************************************/
3578static int
3579ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
3580{
3581 int ret;
3582 char *sp;
3583 int device_error;
3584 IPS_DCDB_TABLE_TAPE *tapeDCDB;
3585 int TimeOut;
3586
3587 METHOD_TRACE("ips_send_cmd", 1);
3588
3589 ret = IPS_SUCCESS;
3590
3591 if (!scb->scsi_cmd) {
3592 /* internal command */
3593
3594 if (scb->bus > 0) {
3595 /* Controller commands can't be issued */
3596 /* to real devices -- fail them */
3597 if ((ha->waitflag == TRUE) &&
3598 (ha->cmd_in_progress == scb->cdb[0])) {
3599 ha->waitflag = FALSE;
3600 }
3601
3602 return (1);
3603 }
3604 } else if ((scb->bus == 0) && (!ips_is_passthru(scb->scsi_cmd))) {
3605 /* command to logical bus -- interpret */
3606 ret = IPS_SUCCESS_IMM;
3607
3608 switch (scb->scsi_cmd->cmnd[0]) {
3609 case ALLOW_MEDIUM_REMOVAL:
3610 case REZERO_UNIT:
3611 case ERASE:
3612 case WRITE_FILEMARKS:
3613 case SPACE:
3614 scb->scsi_cmd->result = DID_ERROR << 16;
3615 break;
3616
3617 case START_STOP:
3618 scb->scsi_cmd->result = DID_OK << 16;
3619
3620 case TEST_UNIT_READY:
3621 case INQUIRY:
3622 if (scb->target_id == IPS_ADAPTER_ID) {
3623 /*
3624 * Either we have a TUR
3625 * or we have a SCSI inquiry
3626 */
3627 if (scb->scsi_cmd->cmnd[0] == TEST_UNIT_READY)
3628 scb->scsi_cmd->result = DID_OK << 16;
3629
3630 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
3631 IPS_SCSI_INQ_DATA inquiry;
3632
3633 memset(&inquiry, 0,
3634 sizeof (IPS_SCSI_INQ_DATA));
3635
3636 inquiry.DeviceType =
3637 IPS_SCSI_INQ_TYPE_PROCESSOR;
3638 inquiry.DeviceTypeQualifier =
3639 IPS_SCSI_INQ_LU_CONNECTED;
3640 inquiry.Version = IPS_SCSI_INQ_REV2;
3641 inquiry.ResponseDataFormat =
3642 IPS_SCSI_INQ_RD_REV2;
3643 inquiry.AdditionalLength = 31;
3644 inquiry.Flags[0] =
3645 IPS_SCSI_INQ_Address16;
3646 inquiry.Flags[1] =
3647 IPS_SCSI_INQ_WBus16 |
3648 IPS_SCSI_INQ_Sync;
3649 strncpy(inquiry.VendorId, "IBM ",
3650 8);
3651 strncpy(inquiry.ProductId,
3652 "SERVERAID ", 16);
3653 strncpy(inquiry.ProductRevisionLevel,
3654 "1.00", 4);
3655
3656 ips_scmd_buf_write(scb->scsi_cmd,
3657 &inquiry,
3658 sizeof (inquiry));
3659
3660 scb->scsi_cmd->result = DID_OK << 16;
3661 }
3662 } else {
3663 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
3664 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
3665 scb->cmd.logical_info.reserved = 0;
3666 scb->cmd.logical_info.reserved2 = 0;
3667 scb->data_len = sizeof (IPS_LD_INFO);
3668 scb->data_busaddr = ha->logical_drive_info_dma_addr;
3669 scb->flags = 0;
3670 scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
3671 ret = IPS_SUCCESS;
3672 }
3673
3674 break;
3675
3676 case REQUEST_SENSE:
3677 ips_reqsen(ha, scb);
3678 scb->scsi_cmd->result = DID_OK << 16;
3679 break;
3680
3681 case READ_6:
3682 case WRITE_6:
3683 if (!scb->sg_len) {
3684 scb->cmd.basic_io.op_code =
3685 (scb->scsi_cmd->cmnd[0] ==
3686 READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE;
3687 scb->cmd.basic_io.enhanced_sg = 0;
3688 scb->cmd.basic_io.sg_addr =
3689 cpu_to_le32(scb->data_busaddr);
3690 } else {
3691 scb->cmd.basic_io.op_code =
3692 (scb->scsi_cmd->cmnd[0] ==
3693 READ_6) ? IPS_CMD_READ_SG :
3694 IPS_CMD_WRITE_SG;
3695 scb->cmd.basic_io.enhanced_sg =
3696 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3697 scb->cmd.basic_io.sg_addr =
3698 cpu_to_le32(scb->sg_busaddr);
3699 }
3700
3701 scb->cmd.basic_io.segment_4G = 0;
3702 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3703 scb->cmd.basic_io.log_drv = scb->target_id;
3704 scb->cmd.basic_io.sg_count = scb->sg_len;
3705
3706 if (scb->cmd.basic_io.lba)
3707 scb->cmd.basic_io.lba =
3708 cpu_to_le32(le32_to_cpu
3709 (scb->cmd.basic_io.lba) +
3710 le16_to_cpu(scb->cmd.basic_io.
3711 sector_count));
3712 else
3713 scb->cmd.basic_io.lba =
3714 (((scb->scsi_cmd->
3715 cmnd[1] & 0x1f) << 16) | (scb->scsi_cmd->
3716 cmnd[2] << 8) |
3717 (scb->scsi_cmd->cmnd[3]));
3718
3719 scb->cmd.basic_io.sector_count =
3720 cpu_to_le16(scb->data_len / IPS_BLKSIZE);
3721
3722 if (le16_to_cpu(scb->cmd.basic_io.sector_count) == 0)
3723 scb->cmd.basic_io.sector_count =
3724 cpu_to_le16(256);
3725
3726 ret = IPS_SUCCESS;
3727 break;
3728
3729 case READ_10:
3730 case WRITE_10:
3731 if (!scb->sg_len) {
3732 scb->cmd.basic_io.op_code =
3733 (scb->scsi_cmd->cmnd[0] ==
3734 READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE;
3735 scb->cmd.basic_io.enhanced_sg = 0;
3736 scb->cmd.basic_io.sg_addr =
3737 cpu_to_le32(scb->data_busaddr);
3738 } else {
3739 scb->cmd.basic_io.op_code =
3740 (scb->scsi_cmd->cmnd[0] ==
3741 READ_10) ? IPS_CMD_READ_SG :
3742 IPS_CMD_WRITE_SG;
3743 scb->cmd.basic_io.enhanced_sg =
3744 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3745 scb->cmd.basic_io.sg_addr =
3746 cpu_to_le32(scb->sg_busaddr);
3747 }
3748
3749 scb->cmd.basic_io.segment_4G = 0;
3750 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3751 scb->cmd.basic_io.log_drv = scb->target_id;
3752 scb->cmd.basic_io.sg_count = scb->sg_len;
3753
3754 if (scb->cmd.basic_io.lba)
3755 scb->cmd.basic_io.lba =
3756 cpu_to_le32(le32_to_cpu
3757 (scb->cmd.basic_io.lba) +
3758 le16_to_cpu(scb->cmd.basic_io.
3759 sector_count));
3760 else
3761 scb->cmd.basic_io.lba =
3762 ((scb->scsi_cmd->cmnd[2] << 24) | (scb->
3763 scsi_cmd->
3764 cmnd[3]
3765 << 16) |
3766 (scb->scsi_cmd->cmnd[4] << 8) | scb->
3767 scsi_cmd->cmnd[5]);
3768
3769 scb->cmd.basic_io.sector_count =
3770 cpu_to_le16(scb->data_len / IPS_BLKSIZE);
3771
3772 if (cpu_to_le16(scb->cmd.basic_io.sector_count) == 0) {
3773 /*
3774 * This is a null condition
3775 * we don't have to do anything
3776 * so just return
3777 */
3778 scb->scsi_cmd->result = DID_OK << 16;
3779 } else
3780 ret = IPS_SUCCESS;
3781
3782 break;
3783
3784 case RESERVE:
3785 case RELEASE:
3786 scb->scsi_cmd->result = DID_OK << 16;
3787 break;
3788
3789 case MODE_SENSE:
3790 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
3791 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3792 scb->cmd.basic_io.segment_4G = 0;
3793 scb->cmd.basic_io.enhanced_sg = 0;
3794 scb->data_len = sizeof (*ha->enq);
3795 scb->cmd.basic_io.sg_addr = ha->enq_busaddr;
3796 ret = IPS_SUCCESS;
3797 break;
3798
3799 case READ_CAPACITY:
3800 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
3801 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
3802 scb->cmd.logical_info.reserved = 0;
3803 scb->cmd.logical_info.reserved2 = 0;
3804 scb->cmd.logical_info.reserved3 = 0;
3805 scb->data_len = sizeof (IPS_LD_INFO);
3806 scb->data_busaddr = ha->logical_drive_info_dma_addr;
3807 scb->flags = 0;
3808 scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
3809 ret = IPS_SUCCESS;
3810 break;
3811
3812 case SEND_DIAGNOSTIC:
3813 case REASSIGN_BLOCKS:
3814 case FORMAT_UNIT:
3815 case SEEK_10:
3816 case VERIFY:
3817 case READ_DEFECT_DATA:
3818 case READ_BUFFER:
3819 case WRITE_BUFFER:
3820 scb->scsi_cmd->result = DID_OK << 16;
3821 break;
3822
3823 default:
3824 /* Set the Return Info to appear like the Command was */
3825 /* attempted, a Check Condition occurred, and Sense */
3826 /* Data indicating an Invalid CDB OpCode is returned. */
3827 sp = (char *) scb->scsi_cmd->sense_buffer;
3828 memset(sp, 0, sizeof (scb->scsi_cmd->sense_buffer));
3829
3830 sp[0] = 0x70; /* Error Code */
3831 sp[2] = ILLEGAL_REQUEST; /* Sense Key 5 Illegal Req. */
3832 sp[7] = 0x0A; /* Additional Sense Length */
3833 sp[12] = 0x20; /* ASC = Invalid OpCode */
3834 sp[13] = 0x00; /* ASCQ */
3835
3836 device_error = 2; /* Indicate Check Condition */
3837 scb->scsi_cmd->result = device_error | (DID_OK << 16);
3838 break;
3839 } /* end switch */
3840 }
3841 /* end if */
3842 if (ret == IPS_SUCCESS_IMM)
3843 return (ret);
3844
3845 /* setup DCDB */
3846 if (scb->bus > 0) {
3847
3848 /* If we already know the Device is Not there, no need to attempt a Command */
3849 /* This also protects an NT FailOver Controller from getting CDB's sent to it */
3850 if (ha->conf->dev[scb->bus - 1][scb->target_id].ucState == 0) {
3851 scb->scsi_cmd->result = DID_NO_CONNECT << 16;
3852 return (IPS_SUCCESS_IMM);
3853 }
3854
3855 ha->dcdb_active[scb->bus - 1] |= (1 << scb->target_id);
3856 scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
3857 scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr +
3858 (unsigned long) &scb->
3859 dcdb -
3860 (unsigned long) scb);
3861 scb->cmd.dcdb.reserved = 0;
3862 scb->cmd.dcdb.reserved2 = 0;
3863 scb->cmd.dcdb.reserved3 = 0;
3864 scb->cmd.dcdb.segment_4G = 0;
3865 scb->cmd.dcdb.enhanced_sg = 0;
3866
3867 TimeOut = scb->scsi_cmd->timeout_per_command;
3868
3869 if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
3870 if (!scb->sg_len) {
3871 scb->cmd.dcdb.op_code = IPS_CMD_EXTENDED_DCDB;
3872 } else {
3873 scb->cmd.dcdb.op_code =
3874 IPS_CMD_EXTENDED_DCDB_SG;
3875 scb->cmd.dcdb.enhanced_sg =
3876 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3877 }
3878
3879 tapeDCDB = (IPS_DCDB_TABLE_TAPE *) & scb->dcdb; /* Use Same Data Area as Old DCDB Struct */
3880 tapeDCDB->device_address =
3881 ((scb->bus - 1) << 4) | scb->target_id;
3882 tapeDCDB->cmd_attribute |= IPS_DISCONNECT_ALLOWED;
3883 tapeDCDB->cmd_attribute &= ~IPS_TRANSFER64K; /* Always Turn OFF 64K Size Flag */
3884
3885 if (TimeOut) {
3886 if (TimeOut < (10 * HZ))
3887 tapeDCDB->cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
3888 else if (TimeOut < (60 * HZ))
3889 tapeDCDB->cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
3890 else if (TimeOut < (1200 * HZ))
3891 tapeDCDB->cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
3892 }
3893
3894 tapeDCDB->cdb_length = scb->scsi_cmd->cmd_len;
3895 tapeDCDB->reserved_for_LUN = 0;
3896 tapeDCDB->transfer_length = scb->data_len;
3897 if (scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB_SG)
3898 tapeDCDB->buffer_pointer =
3899 cpu_to_le32(scb->sg_busaddr);
3900 else
3901 tapeDCDB->buffer_pointer =
3902 cpu_to_le32(scb->data_busaddr);
3903 tapeDCDB->sg_count = scb->sg_len;
3904 tapeDCDB->sense_length = sizeof (tapeDCDB->sense_info);
3905 tapeDCDB->scsi_status = 0;
3906 tapeDCDB->reserved = 0;
3907 memcpy(tapeDCDB->scsi_cdb, scb->scsi_cmd->cmnd,
3908 scb->scsi_cmd->cmd_len);
3909 } else {
3910 if (!scb->sg_len) {
3911 scb->cmd.dcdb.op_code = IPS_CMD_DCDB;
3912 } else {
3913 scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG;
3914 scb->cmd.dcdb.enhanced_sg =
3915 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3916 }
3917
3918 scb->dcdb.device_address =
3919 ((scb->bus - 1) << 4) | scb->target_id;
3920 scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED;
3921
3922 if (TimeOut) {
3923 if (TimeOut < (10 * HZ))
3924 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
3925 else if (TimeOut < (60 * HZ))
3926 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
3927 else if (TimeOut < (1200 * HZ))
3928 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
3929 }
3930
3931 scb->dcdb.transfer_length = scb->data_len;
3932 if (scb->dcdb.cmd_attribute & IPS_TRANSFER64K)
3933 scb->dcdb.transfer_length = 0;
3934 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB_SG)
3935 scb->dcdb.buffer_pointer =
3936 cpu_to_le32(scb->sg_busaddr);
3937 else
3938 scb->dcdb.buffer_pointer =
3939 cpu_to_le32(scb->data_busaddr);
3940 scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
3941 scb->dcdb.sense_length = sizeof (scb->dcdb.sense_info);
3942 scb->dcdb.sg_count = scb->sg_len;
3943 scb->dcdb.reserved = 0;
3944 memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd,
3945 scb->scsi_cmd->cmd_len);
3946 scb->dcdb.scsi_status = 0;
3947 scb->dcdb.reserved2[0] = 0;
3948 scb->dcdb.reserved2[1] = 0;
3949 scb->dcdb.reserved2[2] = 0;
3950 }
3951 }
3952
3953 return ((*ha->func.issue) (ha, scb));
3954}
3955
3956/****************************************************************************/
3957/* */
3958/* Routine Name: ips_chk_status */
3959/* */
3960/* Routine Description: */
3961/* */
3962/* Check the status of commands to logical drives */
3963/* Assumed to be called with the HA lock */
3964/****************************************************************************/
3965static void
3966ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
3967{
3968 ips_scb_t *scb;
3969 ips_stat_t *sp;
3970 uint8_t basic_status;
3971 uint8_t ext_status;
3972 int errcode;
Jack Hammera5b3c862006-01-31 13:17:55 -05003973 IPS_SCSI_INQ_DATA inquiryData;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
3975 METHOD_TRACE("ips_chkstatus", 1);
3976
3977 scb = &ha->scbs[pstatus->fields.command_id];
3978 scb->basic_status = basic_status =
3979 pstatus->fields.basic_status & IPS_BASIC_STATUS_MASK;
3980 scb->extended_status = ext_status = pstatus->fields.extended_status;
3981
3982 sp = &ha->sp;
3983 sp->residue_len = 0;
3984 sp->scb_addr = (void *) scb;
3985
3986 /* Remove the item from the active queue */
3987 ips_removeq_scb(&ha->scb_activelist, scb);
3988
3989 if (!scb->scsi_cmd)
3990 /* internal commands are handled in do_ipsintr */
3991 return;
3992
3993 DEBUG_VAR(2, "(%s%d) ips_chkstatus: cmd 0x%X id %d (%d %d %d)",
3994 ips_name,
3995 ha->host_num,
3996 scb->cdb[0],
3997 scb->cmd.basic_io.command_id,
3998 scb->bus, scb->target_id, scb->lun);
3999
4000 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
4001 /* passthru - just returns the raw result */
4002 return;
4003
4004 errcode = DID_OK;
4005
4006 if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) ||
4007 ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) {
4008
4009 if (scb->bus == 0) {
4010 if ((basic_status & IPS_GSC_STATUS_MASK) ==
4011 IPS_CMD_RECOVERED_ERROR) {
4012 DEBUG_VAR(1,
4013 "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4014 ips_name, ha->host_num,
4015 scb->cmd.basic_io.op_code,
4016 basic_status, ext_status);
4017 }
4018
4019 switch (scb->scsi_cmd->cmnd[0]) {
4020 case ALLOW_MEDIUM_REMOVAL:
4021 case REZERO_UNIT:
4022 case ERASE:
4023 case WRITE_FILEMARKS:
4024 case SPACE:
4025 errcode = DID_ERROR;
4026 break;
4027
4028 case START_STOP:
4029 break;
4030
4031 case TEST_UNIT_READY:
4032 if (!ips_online(ha, scb)) {
4033 errcode = DID_TIME_OUT;
4034 }
4035 break;
4036
4037 case INQUIRY:
4038 if (ips_online(ha, scb)) {
4039 ips_inquiry(ha, scb);
4040 } else {
4041 errcode = DID_TIME_OUT;
4042 }
4043 break;
4044
4045 case REQUEST_SENSE:
4046 ips_reqsen(ha, scb);
4047 break;
4048
4049 case READ_6:
4050 case WRITE_6:
4051 case READ_10:
4052 case WRITE_10:
4053 case RESERVE:
4054 case RELEASE:
4055 break;
4056
4057 case MODE_SENSE:
4058 if (!ips_online(ha, scb)
4059 || !ips_msense(ha, scb)) {
4060 errcode = DID_ERROR;
4061 }
4062 break;
4063
4064 case READ_CAPACITY:
4065 if (ips_online(ha, scb))
4066 ips_rdcap(ha, scb);
4067 else {
4068 errcode = DID_TIME_OUT;
4069 }
4070 break;
4071
4072 case SEND_DIAGNOSTIC:
4073 case REASSIGN_BLOCKS:
4074 break;
4075
4076 case FORMAT_UNIT:
4077 errcode = DID_ERROR;
4078 break;
4079
4080 case SEEK_10:
4081 case VERIFY:
4082 case READ_DEFECT_DATA:
4083 case READ_BUFFER:
4084 case WRITE_BUFFER:
4085 break;
4086
4087 default:
4088 errcode = DID_ERROR;
4089 } /* end switch */
4090
4091 scb->scsi_cmd->result = errcode << 16;
4092 } else { /* bus == 0 */
4093 /* restrict access to physical drives */
Jeff Garzik2f277d62007-12-13 16:14:08 -08004094 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
4095 ips_scmd_buf_read(scb->scsi_cmd,
Jack Hammera5b3c862006-01-31 13:17:55 -05004096 &inquiryData, sizeof (inquiryData));
Jeff Garzik2f277d62007-12-13 16:14:08 -08004097 if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK)
Jack Hammera5b3c862006-01-31 13:17:55 -05004098 scb->scsi_cmd->result = DID_TIME_OUT << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 }
4100 } /* else */
4101 } else { /* recovered error / success */
4102 if (scb->bus == 0) {
4103 DEBUG_VAR(1,
4104 "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4105 ips_name, ha->host_num,
4106 scb->cmd.basic_io.op_code, basic_status,
4107 ext_status);
4108 }
4109
4110 ips_map_status(ha, scb, sp);
4111 } /* else */
4112}
4113
4114/****************************************************************************/
4115/* */
4116/* Routine Name: ips_online */
4117/* */
4118/* Routine Description: */
4119/* */
4120/* Determine if a logical drive is online */
4121/* */
4122/****************************************************************************/
4123static int
4124ips_online(ips_ha_t * ha, ips_scb_t * scb)
4125{
4126 METHOD_TRACE("ips_online", 1);
4127
4128 if (scb->target_id >= IPS_MAX_LD)
4129 return (0);
4130
4131 if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
4132 memset(ha->logical_drive_info, 0, sizeof (IPS_LD_INFO));
4133 return (0);
4134 }
4135
4136 if (ha->logical_drive_info->drive_info[scb->target_id].state !=
4137 IPS_LD_OFFLINE
4138 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4139 IPS_LD_FREE
4140 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4141 IPS_LD_CRS
4142 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4143 IPS_LD_SYS)
4144 return (1);
4145 else
4146 return (0);
4147}
4148
4149/****************************************************************************/
4150/* */
4151/* Routine Name: ips_inquiry */
4152/* */
4153/* Routine Description: */
4154/* */
4155/* Simulate an inquiry command to a logical drive */
4156/* */
4157/****************************************************************************/
4158static int
4159ips_inquiry(ips_ha_t * ha, ips_scb_t * scb)
4160{
4161 IPS_SCSI_INQ_DATA inquiry;
4162
4163 METHOD_TRACE("ips_inquiry", 1);
4164
4165 memset(&inquiry, 0, sizeof (IPS_SCSI_INQ_DATA));
4166
4167 inquiry.DeviceType = IPS_SCSI_INQ_TYPE_DASD;
4168 inquiry.DeviceTypeQualifier = IPS_SCSI_INQ_LU_CONNECTED;
4169 inquiry.Version = IPS_SCSI_INQ_REV2;
4170 inquiry.ResponseDataFormat = IPS_SCSI_INQ_RD_REV2;
4171 inquiry.AdditionalLength = 31;
4172 inquiry.Flags[0] = IPS_SCSI_INQ_Address16;
4173 inquiry.Flags[1] =
4174 IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync | IPS_SCSI_INQ_CmdQue;
4175 strncpy(inquiry.VendorId, "IBM ", 8);
4176 strncpy(inquiry.ProductId, "SERVERAID ", 16);
4177 strncpy(inquiry.ProductRevisionLevel, "1.00", 4);
4178
4179 ips_scmd_buf_write(scb->scsi_cmd, &inquiry, sizeof (inquiry));
4180
4181 return (1);
4182}
4183
4184/****************************************************************************/
4185/* */
4186/* Routine Name: ips_rdcap */
4187/* */
4188/* Routine Description: */
4189/* */
4190/* Simulate a read capacity command to a logical drive */
4191/* */
4192/****************************************************************************/
4193static int
4194ips_rdcap(ips_ha_t * ha, ips_scb_t * scb)
4195{
4196 IPS_SCSI_CAPACITY cap;
4197
4198 METHOD_TRACE("ips_rdcap", 1);
4199
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09004200 if (scsi_bufflen(scb->scsi_cmd) < 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 return (0);
4202
4203 cap.lba =
4204 cpu_to_be32(le32_to_cpu
4205 (ha->logical_drive_info->
4206 drive_info[scb->target_id].sector_count) - 1);
4207 cap.len = cpu_to_be32((uint32_t) IPS_BLKSIZE);
4208
4209 ips_scmd_buf_write(scb->scsi_cmd, &cap, sizeof (cap));
4210
4211 return (1);
4212}
4213
4214/****************************************************************************/
4215/* */
4216/* Routine Name: ips_msense */
4217/* */
4218/* Routine Description: */
4219/* */
4220/* Simulate a mode sense command to a logical drive */
4221/* */
4222/****************************************************************************/
4223static int
4224ips_msense(ips_ha_t * ha, ips_scb_t * scb)
4225{
4226 uint16_t heads;
4227 uint16_t sectors;
4228 uint32_t cylinders;
4229 IPS_SCSI_MODE_PAGE_DATA mdata;
4230
4231 METHOD_TRACE("ips_msense", 1);
4232
4233 if (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) > 0x400000 &&
4234 (ha->enq->ucMiscFlag & 0x8) == 0) {
4235 heads = IPS_NORM_HEADS;
4236 sectors = IPS_NORM_SECTORS;
4237 } else {
4238 heads = IPS_COMP_HEADS;
4239 sectors = IPS_COMP_SECTORS;
4240 }
4241
4242 cylinders =
4243 (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) -
4244 1) / (heads * sectors);
4245
4246 memset(&mdata, 0, sizeof (IPS_SCSI_MODE_PAGE_DATA));
4247
4248 mdata.hdr.BlockDescLength = 8;
4249
4250 switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
4251 case 0x03: /* page 3 */
4252 mdata.pdata.pg3.PageCode = 3;
4253 mdata.pdata.pg3.PageLength = sizeof (IPS_SCSI_MODE_PAGE3);
4254 mdata.hdr.DataLength =
4255 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg3.PageLength;
4256 mdata.pdata.pg3.TracksPerZone = 0;
4257 mdata.pdata.pg3.AltSectorsPerZone = 0;
4258 mdata.pdata.pg3.AltTracksPerZone = 0;
4259 mdata.pdata.pg3.AltTracksPerVolume = 0;
4260 mdata.pdata.pg3.SectorsPerTrack = cpu_to_be16(sectors);
4261 mdata.pdata.pg3.BytesPerSector = cpu_to_be16(IPS_BLKSIZE);
4262 mdata.pdata.pg3.Interleave = cpu_to_be16(1);
4263 mdata.pdata.pg3.TrackSkew = 0;
4264 mdata.pdata.pg3.CylinderSkew = 0;
4265 mdata.pdata.pg3.flags = IPS_SCSI_MP3_SoftSector;
4266 break;
4267
4268 case 0x4:
4269 mdata.pdata.pg4.PageCode = 4;
4270 mdata.pdata.pg4.PageLength = sizeof (IPS_SCSI_MODE_PAGE4);
4271 mdata.hdr.DataLength =
4272 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg4.PageLength;
4273 mdata.pdata.pg4.CylindersHigh =
4274 cpu_to_be16((cylinders >> 8) & 0xFFFF);
4275 mdata.pdata.pg4.CylindersLow = (cylinders & 0xFF);
4276 mdata.pdata.pg4.Heads = heads;
4277 mdata.pdata.pg4.WritePrecompHigh = 0;
4278 mdata.pdata.pg4.WritePrecompLow = 0;
4279 mdata.pdata.pg4.ReducedWriteCurrentHigh = 0;
4280 mdata.pdata.pg4.ReducedWriteCurrentLow = 0;
4281 mdata.pdata.pg4.StepRate = cpu_to_be16(1);
4282 mdata.pdata.pg4.LandingZoneHigh = 0;
4283 mdata.pdata.pg4.LandingZoneLow = 0;
4284 mdata.pdata.pg4.flags = 0;
4285 mdata.pdata.pg4.RotationalOffset = 0;
4286 mdata.pdata.pg4.MediumRotationRate = 0;
4287 break;
4288 case 0x8:
4289 mdata.pdata.pg8.PageCode = 8;
4290 mdata.pdata.pg8.PageLength = sizeof (IPS_SCSI_MODE_PAGE8);
4291 mdata.hdr.DataLength =
4292 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg8.PageLength;
4293 /* everything else is left set to 0 */
4294 break;
4295
4296 default:
4297 return (0);
4298 } /* end switch */
4299
4300 ips_scmd_buf_write(scb->scsi_cmd, &mdata, sizeof (mdata));
4301
4302 return (1);
4303}
4304
4305/****************************************************************************/
4306/* */
4307/* Routine Name: ips_reqsen */
4308/* */
4309/* Routine Description: */
4310/* */
4311/* Simulate a request sense command to a logical drive */
4312/* */
4313/****************************************************************************/
4314static int
4315ips_reqsen(ips_ha_t * ha, ips_scb_t * scb)
4316{
4317 IPS_SCSI_REQSEN reqsen;
4318
4319 METHOD_TRACE("ips_reqsen", 1);
4320
4321 memset(&reqsen, 0, sizeof (IPS_SCSI_REQSEN));
4322
4323 reqsen.ResponseCode =
4324 IPS_SCSI_REQSEN_VALID | IPS_SCSI_REQSEN_CURRENT_ERR;
4325 reqsen.AdditionalLength = 10;
4326 reqsen.AdditionalSenseCode = IPS_SCSI_REQSEN_NO_SENSE;
4327 reqsen.AdditionalSenseCodeQual = IPS_SCSI_REQSEN_NO_SENSE;
4328
4329 ips_scmd_buf_write(scb->scsi_cmd, &reqsen, sizeof (reqsen));
4330
4331 return (1);
4332}
4333
4334/****************************************************************************/
4335/* */
4336/* Routine Name: ips_free */
4337/* */
4338/* Routine Description: */
4339/* */
4340/* Free any allocated space for this controller */
4341/* */
4342/****************************************************************************/
4343static void
4344ips_free(ips_ha_t * ha)
4345{
4346
4347 METHOD_TRACE("ips_free", 1);
4348
4349 if (ha) {
4350 if (ha->enq) {
4351 pci_free_consistent(ha->pcidev, sizeof(IPS_ENQ),
4352 ha->enq, ha->enq_busaddr);
4353 ha->enq = NULL;
4354 }
4355
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004356 kfree(ha->conf);
4357 ha->conf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
4359 if (ha->adapt) {
4360 pci_free_consistent(ha->pcidev,
4361 sizeof (IPS_ADAPTER) +
4362 sizeof (IPS_IO_CMD), ha->adapt,
4363 ha->adapt->hw_status_start);
4364 ha->adapt = NULL;
4365 }
4366
4367 if (ha->logical_drive_info) {
4368 pci_free_consistent(ha->pcidev,
4369 sizeof (IPS_LD_INFO),
4370 ha->logical_drive_info,
4371 ha->logical_drive_info_dma_addr);
4372 ha->logical_drive_info = NULL;
4373 }
4374
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004375 kfree(ha->nvram);
4376 ha->nvram = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004378 kfree(ha->subsys);
4379 ha->subsys = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
4381 if (ha->ioctl_data) {
4382 pci_free_consistent(ha->pcidev, ha->ioctl_len,
4383 ha->ioctl_data, ha->ioctl_busaddr);
4384 ha->ioctl_data = NULL;
4385 ha->ioctl_datasize = 0;
4386 ha->ioctl_len = 0;
4387 }
4388 ips_deallocatescbs(ha, ha->max_cmds);
4389
4390 /* free memory mapped (if applicable) */
4391 if (ha->mem_ptr) {
4392 iounmap(ha->ioremap_ptr);
4393 ha->ioremap_ptr = NULL;
4394 ha->mem_ptr = NULL;
4395 }
4396
4397 if (ha->mem_addr)
4398 release_mem_region(ha->mem_addr, ha->mem_len);
4399 ha->mem_addr = 0;
4400
4401 }
4402}
4403
4404/****************************************************************************/
4405/* */
4406/* Routine Name: ips_deallocatescbs */
4407/* */
4408/* Routine Description: */
4409/* */
4410/* Free the command blocks */
4411/* */
4412/****************************************************************************/
4413static int
4414ips_deallocatescbs(ips_ha_t * ha, int cmds)
4415{
4416 if (ha->scbs) {
4417 pci_free_consistent(ha->pcidev,
4418 IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * cmds,
4419 ha->scbs->sg_list.list,
4420 ha->scbs->sg_busaddr);
4421 pci_free_consistent(ha->pcidev, sizeof (ips_scb_t) * cmds,
4422 ha->scbs, ha->scbs->scb_busaddr);
4423 ha->scbs = NULL;
4424 } /* end if */
4425 return 1;
4426}
4427
4428/****************************************************************************/
4429/* */
4430/* Routine Name: ips_allocatescbs */
4431/* */
4432/* Routine Description: */
4433/* */
4434/* Allocate the command blocks */
4435/* */
4436/****************************************************************************/
4437static int
4438ips_allocatescbs(ips_ha_t * ha)
4439{
4440 ips_scb_t *scb_p;
4441 IPS_SG_LIST ips_sg;
4442 int i;
4443 dma_addr_t command_dma, sg_dma;
4444
4445 METHOD_TRACE("ips_allocatescbs", 1);
4446
4447 /* Allocate memory for the SCBs */
4448 ha->scbs =
4449 pci_alloc_consistent(ha->pcidev, ha->max_cmds * sizeof (ips_scb_t),
4450 &command_dma);
4451 if (ha->scbs == NULL)
4452 return 0;
4453 ips_sg.list =
4454 pci_alloc_consistent(ha->pcidev,
4455 IPS_SGLIST_SIZE(ha) * IPS_MAX_SG *
4456 ha->max_cmds, &sg_dma);
4457 if (ips_sg.list == NULL) {
4458 pci_free_consistent(ha->pcidev,
4459 ha->max_cmds * sizeof (ips_scb_t), ha->scbs,
4460 command_dma);
4461 return 0;
4462 }
4463
4464 memset(ha->scbs, 0, ha->max_cmds * sizeof (ips_scb_t));
4465
4466 for (i = 0; i < ha->max_cmds; i++) {
4467 scb_p = &ha->scbs[i];
4468 scb_p->scb_busaddr = command_dma + sizeof (ips_scb_t) * i;
4469 /* set up S/G list */
4470 if (IPS_USE_ENH_SGLIST(ha)) {
4471 scb_p->sg_list.enh_list =
4472 ips_sg.enh_list + i * IPS_MAX_SG;
4473 scb_p->sg_busaddr =
4474 sg_dma + IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * i;
4475 } else {
4476 scb_p->sg_list.std_list =
4477 ips_sg.std_list + i * IPS_MAX_SG;
4478 scb_p->sg_busaddr =
4479 sg_dma + IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * i;
4480 }
4481
4482 /* add to the free list */
4483 if (i < ha->max_cmds - 1) {
4484 scb_p->q_next = ha->scb_freelist;
4485 ha->scb_freelist = scb_p;
4486 }
4487 }
4488
4489 /* success */
4490 return (1);
4491}
4492
4493/****************************************************************************/
4494/* */
4495/* Routine Name: ips_init_scb */
4496/* */
4497/* Routine Description: */
4498/* */
4499/* Initialize a CCB to default values */
4500/* */
4501/****************************************************************************/
4502static void
4503ips_init_scb(ips_ha_t * ha, ips_scb_t * scb)
4504{
4505 IPS_SG_LIST sg_list;
4506 uint32_t cmd_busaddr, sg_busaddr;
4507 METHOD_TRACE("ips_init_scb", 1);
4508
4509 if (scb == NULL)
4510 return;
4511
4512 sg_list.list = scb->sg_list.list;
4513 cmd_busaddr = scb->scb_busaddr;
4514 sg_busaddr = scb->sg_busaddr;
4515 /* zero fill */
4516 memset(scb, 0, sizeof (ips_scb_t));
4517 memset(ha->dummy, 0, sizeof (IPS_IO_CMD));
4518
4519 /* Initialize dummy command bucket */
4520 ha->dummy->op_code = 0xFF;
4521 ha->dummy->ccsar = cpu_to_le32(ha->adapt->hw_status_start
4522 + sizeof (IPS_ADAPTER));
4523 ha->dummy->command_id = IPS_MAX_CMDS;
4524
4525 /* set bus address of scb */
4526 scb->scb_busaddr = cmd_busaddr;
4527 scb->sg_busaddr = sg_busaddr;
4528 scb->sg_list.list = sg_list.list;
4529
4530 /* Neptune Fix */
4531 scb->cmd.basic_io.cccr = cpu_to_le32((uint32_t) IPS_BIT_ILE);
4532 scb->cmd.basic_io.ccsar = cpu_to_le32(ha->adapt->hw_status_start
4533 + sizeof (IPS_ADAPTER));
4534}
4535
4536/****************************************************************************/
4537/* */
4538/* Routine Name: ips_get_scb */
4539/* */
4540/* Routine Description: */
4541/* */
4542/* Initialize a CCB to default values */
4543/* */
4544/* ASSUMED to be callled from within a lock */
4545/* */
4546/****************************************************************************/
4547static ips_scb_t *
4548ips_getscb(ips_ha_t * ha)
4549{
4550 ips_scb_t *scb;
4551
4552 METHOD_TRACE("ips_getscb", 1);
4553
4554 if ((scb = ha->scb_freelist) == NULL) {
4555
4556 return (NULL);
4557 }
4558
4559 ha->scb_freelist = scb->q_next;
4560 scb->flags = 0;
4561 scb->q_next = NULL;
4562
4563 ips_init_scb(ha, scb);
4564
4565 return (scb);
4566}
4567
4568/****************************************************************************/
4569/* */
4570/* Routine Name: ips_free_scb */
4571/* */
4572/* Routine Description: */
4573/* */
4574/* Return an unused CCB back to the free list */
4575/* */
4576/* ASSUMED to be called from within a lock */
4577/* */
4578/****************************************************************************/
4579static void
4580ips_freescb(ips_ha_t * ha, ips_scb_t * scb)
4581{
4582
4583 METHOD_TRACE("ips_freescb", 1);
4584 if (scb->flags & IPS_SCB_MAP_SG)
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09004585 scsi_dma_unmap(scb->scsi_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586 else if (scb->flags & IPS_SCB_MAP_SINGLE)
4587 pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
4588 IPS_DMA_DIR(scb));
4589
4590 /* check to make sure this is not our "special" scb */
4591 if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
4592 scb->q_next = ha->scb_freelist;
4593 ha->scb_freelist = scb;
4594 }
4595}
4596
4597/****************************************************************************/
4598/* */
4599/* Routine Name: ips_isinit_copperhead */
4600/* */
4601/* Routine Description: */
4602/* */
4603/* Is controller initialized ? */
4604/* */
4605/****************************************************************************/
4606static int
4607ips_isinit_copperhead(ips_ha_t * ha)
4608{
4609 uint8_t scpr;
4610 uint8_t isr;
4611
4612 METHOD_TRACE("ips_isinit_copperhead", 1);
4613
4614 isr = inb(ha->io_addr + IPS_REG_HISR);
4615 scpr = inb(ha->io_addr + IPS_REG_SCPR);
4616
4617 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4618 return (0);
4619 else
4620 return (1);
4621}
4622
4623/****************************************************************************/
4624/* */
4625/* Routine Name: ips_isinit_copperhead_memio */
4626/* */
4627/* Routine Description: */
4628/* */
4629/* Is controller initialized ? */
4630/* */
4631/****************************************************************************/
4632static int
4633ips_isinit_copperhead_memio(ips_ha_t * ha)
4634{
4635 uint8_t isr = 0;
4636 uint8_t scpr;
4637
4638 METHOD_TRACE("ips_is_init_copperhead_memio", 1);
4639
4640 isr = readb(ha->mem_ptr + IPS_REG_HISR);
4641 scpr = readb(ha->mem_ptr + IPS_REG_SCPR);
4642
4643 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4644 return (0);
4645 else
4646 return (1);
4647}
4648
4649/****************************************************************************/
4650/* */
4651/* Routine Name: ips_isinit_morpheus */
4652/* */
4653/* Routine Description: */
4654/* */
4655/* Is controller initialized ? */
4656/* */
4657/****************************************************************************/
4658static int
4659ips_isinit_morpheus(ips_ha_t * ha)
4660{
4661 uint32_t post;
4662 uint32_t bits;
4663
4664 METHOD_TRACE("ips_is_init_morpheus", 1);
Jeff Garzik2f277d62007-12-13 16:14:08 -08004665
4666 if (ips_isintr_morpheus(ha))
Jack Hammeree807c22005-08-29 10:44:34 -04004667 ips_flush_and_reset(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668
4669 post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
4670 bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
4671
4672 if (post == 0)
4673 return (0);
4674 else if (bits & 0x3)
4675 return (0);
4676 else
4677 return (1);
4678}
4679
4680/****************************************************************************/
4681/* */
Jack Hammeree807c22005-08-29 10:44:34 -04004682/* Routine Name: ips_flush_and_reset */
4683/* */
4684/* Routine Description: */
4685/* */
4686/* Perform cleanup ( FLUSH and RESET ) when the adapter is in an unknown */
4687/* state ( was trying to INIT and an interrupt was already pending ) ... */
4688/* */
4689/****************************************************************************/
Jeff Garzik2f277d62007-12-13 16:14:08 -08004690static void
Jack Hammeree807c22005-08-29 10:44:34 -04004691ips_flush_and_reset(ips_ha_t *ha)
4692{
4693 ips_scb_t *scb;
4694 int ret;
4695 int time;
4696 int done;
4697 dma_addr_t command_dma;
4698
4699 /* Create a usuable SCB */
4700 scb = pci_alloc_consistent(ha->pcidev, sizeof(ips_scb_t), &command_dma);
4701 if (scb) {
4702 memset(scb, 0, sizeof(ips_scb_t));
4703 ips_init_scb(ha, scb);
4704 scb->scb_busaddr = command_dma;
4705
4706 scb->timeout = ips_cmd_timeout;
4707 scb->cdb[0] = IPS_CMD_FLUSH;
4708
4709 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
4710 scb->cmd.flush_cache.command_id = IPS_MAX_CMDS; /* Use an ID that would otherwise not exist */
4711 scb->cmd.flush_cache.state = IPS_NORM_STATE;
4712 scb->cmd.flush_cache.reserved = 0;
4713 scb->cmd.flush_cache.reserved2 = 0;
4714 scb->cmd.flush_cache.reserved3 = 0;
4715 scb->cmd.flush_cache.reserved4 = 0;
4716
4717 ret = ips_send_cmd(ha, scb); /* Send the Flush Command */
4718
4719 if (ret == IPS_SUCCESS) {
4720 time = 60 * IPS_ONE_SEC; /* Max Wait time is 60 seconds */
4721 done = 0;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004722
Jack Hammeree807c22005-08-29 10:44:34 -04004723 while ((time > 0) && (!done)) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08004724 done = ips_poll_for_flush_complete(ha);
Jack Hammeree807c22005-08-29 10:44:34 -04004725 /* This may look evil, but it's only done during extremely rare start-up conditions ! */
4726 udelay(1000);
4727 time--;
4728 }
4729 }
4730 }
4731
4732 /* Now RESET and INIT the adapter */
4733 (*ha->func.reset) (ha);
4734
4735 pci_free_consistent(ha->pcidev, sizeof(ips_scb_t), scb, command_dma);
4736 return;
4737}
4738
4739/****************************************************************************/
4740/* */
4741/* Routine Name: ips_poll_for_flush_complete */
4742/* */
4743/* Routine Description: */
4744/* */
4745/* Poll for the Flush Command issued by ips_flush_and_reset() to complete */
4746/* All other responses are just taken off the queue and ignored */
4747/* */
4748/****************************************************************************/
4749static int
4750ips_poll_for_flush_complete(ips_ha_t * ha)
4751{
4752 IPS_STATUS cstatus;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004753
Jack Hammeree807c22005-08-29 10:44:34 -04004754 while (TRUE) {
4755 cstatus.value = (*ha->func.statupd) (ha);
4756
4757 if (cstatus.value == 0xffffffff) /* If No Interrupt to process */
4758 break;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004759
Jack Hammeree807c22005-08-29 10:44:34 -04004760 /* Success is when we see the Flush Command ID */
Jeff Garzik2f277d62007-12-13 16:14:08 -08004761 if (cstatus.fields.command_id == IPS_MAX_CMDS)
Jack Hammeree807c22005-08-29 10:44:34 -04004762 return 1;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004763 }
Jack Hammeree807c22005-08-29 10:44:34 -04004764
4765 return 0;
James Bottomley0ee957c2005-11-04 23:22:55 -06004766}
Jack Hammeree807c22005-08-29 10:44:34 -04004767
4768/****************************************************************************/
4769/* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770/* Routine Name: ips_enable_int_copperhead */
4771/* */
4772/* Routine Description: */
4773/* Turn on interrupts */
4774/* */
4775/****************************************************************************/
4776static void
4777ips_enable_int_copperhead(ips_ha_t * ha)
4778{
4779 METHOD_TRACE("ips_enable_int_copperhead", 1);
4780
4781 outb(ha->io_addr + IPS_REG_HISR, IPS_BIT_EI);
4782 inb(ha->io_addr + IPS_REG_HISR); /*Ensure PCI Posting Completes*/
4783}
4784
4785/****************************************************************************/
4786/* */
4787/* Routine Name: ips_enable_int_copperhead_memio */
4788/* */
4789/* Routine Description: */
4790/* Turn on interrupts */
4791/* */
4792/****************************************************************************/
4793static void
4794ips_enable_int_copperhead_memio(ips_ha_t * ha)
4795{
4796 METHOD_TRACE("ips_enable_int_copperhead_memio", 1);
4797
4798 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
4799 readb(ha->mem_ptr + IPS_REG_HISR); /*Ensure PCI Posting Completes*/
4800}
4801
4802/****************************************************************************/
4803/* */
4804/* Routine Name: ips_enable_int_morpheus */
4805/* */
4806/* Routine Description: */
4807/* Turn on interrupts */
4808/* */
4809/****************************************************************************/
4810static void
4811ips_enable_int_morpheus(ips_ha_t * ha)
4812{
4813 uint32_t Oimr;
4814
4815 METHOD_TRACE("ips_enable_int_morpheus", 1);
4816
4817 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
4818 Oimr &= ~0x08;
4819 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
4820 readl(ha->mem_ptr + IPS_REG_I960_OIMR); /*Ensure PCI Posting Completes*/
4821}
4822
4823/****************************************************************************/
4824/* */
4825/* Routine Name: ips_init_copperhead */
4826/* */
4827/* Routine Description: */
4828/* */
4829/* Initialize a copperhead controller */
4830/* */
4831/****************************************************************************/
4832static int
4833ips_init_copperhead(ips_ha_t * ha)
4834{
4835 uint8_t Isr;
4836 uint8_t Cbsp;
4837 uint8_t PostByte[IPS_MAX_POST_BYTES];
4838 uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
4839 int i, j;
4840
4841 METHOD_TRACE("ips_init_copperhead", 1);
4842
4843 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4844 for (j = 0; j < 45; j++) {
4845 Isr = inb(ha->io_addr + IPS_REG_HISR);
4846 if (Isr & IPS_BIT_GHI)
4847 break;
4848
4849 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004850 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851 }
4852
4853 if (j >= 45)
4854 /* error occurred */
4855 return (0);
4856
4857 PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4858 outb(Isr, ha->io_addr + IPS_REG_HISR);
4859 }
4860
4861 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4862 IPS_PRINTK(KERN_WARNING, ha->pcidev,
4863 "reset controller fails (post status %x %x).\n",
4864 PostByte[0], PostByte[1]);
4865
4866 return (0);
4867 }
4868
4869 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4870 for (j = 0; j < 240; j++) {
4871 Isr = inb(ha->io_addr + IPS_REG_HISR);
4872 if (Isr & IPS_BIT_GHI)
4873 break;
4874
4875 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004876 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004877 }
4878
4879 if (j >= 240)
4880 /* error occurred */
4881 return (0);
4882
4883 ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4884 outb(Isr, ha->io_addr + IPS_REG_HISR);
4885 }
4886
4887 for (i = 0; i < 240; i++) {
4888 Cbsp = inb(ha->io_addr + IPS_REG_CBSP);
4889
4890 if ((Cbsp & IPS_BIT_OP) == 0)
4891 break;
4892
4893 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004894 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895 }
4896
4897 if (i >= 240)
4898 /* reset failed */
4899 return (0);
4900
4901 /* setup CCCR */
4902 outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
4903
4904 /* Enable busmastering */
4905 outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
4906
Jeff Garzik8a694cc2007-12-13 16:14:07 -08004907 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908 /* fix for anaconda64 */
4909 outl(0, ha->io_addr + IPS_REG_NDAE);
4910
4911 /* Enable interrupts */
4912 outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR);
4913
4914 return (1);
4915}
4916
4917/****************************************************************************/
4918/* */
4919/* Routine Name: ips_init_copperhead_memio */
4920/* */
4921/* Routine Description: */
4922/* */
4923/* Initialize a copperhead controller with memory mapped I/O */
4924/* */
4925/****************************************************************************/
4926static int
4927ips_init_copperhead_memio(ips_ha_t * ha)
4928{
4929 uint8_t Isr = 0;
4930 uint8_t Cbsp;
4931 uint8_t PostByte[IPS_MAX_POST_BYTES];
4932 uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
4933 int i, j;
4934
4935 METHOD_TRACE("ips_init_copperhead_memio", 1);
4936
4937 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4938 for (j = 0; j < 45; j++) {
4939 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4940 if (Isr & IPS_BIT_GHI)
4941 break;
4942
4943 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004944 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945 }
4946
4947 if (j >= 45)
4948 /* error occurred */
4949 return (0);
4950
4951 PostByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4952 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4953 }
4954
4955 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4956 IPS_PRINTK(KERN_WARNING, ha->pcidev,
4957 "reset controller fails (post status %x %x).\n",
4958 PostByte[0], PostByte[1]);
4959
4960 return (0);
4961 }
4962
4963 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4964 for (j = 0; j < 240; j++) {
4965 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4966 if (Isr & IPS_BIT_GHI)
4967 break;
4968
4969 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004970 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 }
4972
4973 if (j >= 240)
4974 /* error occurred */
4975 return (0);
4976
4977 ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4978 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4979 }
4980
4981 for (i = 0; i < 240; i++) {
4982 Cbsp = readb(ha->mem_ptr + IPS_REG_CBSP);
4983
4984 if ((Cbsp & IPS_BIT_OP) == 0)
4985 break;
4986
4987 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004988 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 }
4990
4991 if (i >= 240)
4992 /* error occurred */
4993 return (0);
4994
4995 /* setup CCCR */
4996 writel(0x1010, ha->mem_ptr + IPS_REG_CCCR);
4997
4998 /* Enable busmastering */
4999 writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
5000
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005001 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 /* fix for anaconda64 */
5003 writel(0, ha->mem_ptr + IPS_REG_NDAE);
5004
5005 /* Enable interrupts */
5006 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
5007
5008 /* if we get here then everything went OK */
5009 return (1);
5010}
5011
5012/****************************************************************************/
5013/* */
5014/* Routine Name: ips_init_morpheus */
5015/* */
5016/* Routine Description: */
5017/* */
5018/* Initialize a morpheus controller */
5019/* */
5020/****************************************************************************/
5021static int
5022ips_init_morpheus(ips_ha_t * ha)
5023{
5024 uint32_t Post;
5025 uint32_t Config;
5026 uint32_t Isr;
5027 uint32_t Oimr;
5028 int i;
5029
5030 METHOD_TRACE("ips_init_morpheus", 1);
5031
5032 /* Wait up to 45 secs for Post */
5033 for (i = 0; i < 45; i++) {
5034 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5035
5036 if (Isr & IPS_BIT_I960_MSG0I)
5037 break;
5038
5039 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005040 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041 }
5042
5043 if (i >= 45) {
5044 /* error occurred */
5045 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5046 "timeout waiting for post.\n");
5047
5048 return (0);
5049 }
5050
5051 Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
5052
5053 if (Post == 0x4F00) { /* If Flashing the Battery PIC */
5054 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5055 "Flashing Battery PIC, Please wait ...\n");
5056
5057 /* Clear the interrupt bit */
5058 Isr = (uint32_t) IPS_BIT_I960_MSG0I;
5059 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5060
5061 for (i = 0; i < 120; i++) { /* Wait Up to 2 Min. for Completion */
5062 Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
5063 if (Post != 0x4F00)
5064 break;
5065 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005066 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067 }
5068
5069 if (i >= 120) {
5070 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5071 "timeout waiting for Battery PIC Flash\n");
5072 return (0);
5073 }
5074
5075 }
5076
5077 /* Clear the interrupt bit */
5078 Isr = (uint32_t) IPS_BIT_I960_MSG0I;
5079 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5080
5081 if (Post < (IPS_GOOD_POST_STATUS << 8)) {
5082 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5083 "reset controller fails (post status %x).\n", Post);
5084
5085 return (0);
5086 }
5087
5088 /* Wait up to 240 secs for config bytes */
5089 for (i = 0; i < 240; i++) {
5090 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5091
5092 if (Isr & IPS_BIT_I960_MSG1I)
5093 break;
5094
5095 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005096 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097 }
5098
5099 if (i >= 240) {
5100 /* error occurred */
5101 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5102 "timeout waiting for config.\n");
5103
5104 return (0);
5105 }
5106
5107 Config = readl(ha->mem_ptr + IPS_REG_I960_MSG1);
5108
5109 /* Clear interrupt bit */
5110 Isr = (uint32_t) IPS_BIT_I960_MSG1I;
5111 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5112
5113 /* Turn on the interrupts */
5114 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
5115 Oimr &= ~0x8;
5116 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
5117
5118 /* if we get here then everything went OK */
5119
5120 /* Since we did a RESET, an EraseStripeLock may be needed */
5121 if (Post == 0xEF10) {
5122 if ((Config == 0x000F) || (Config == 0x0009))
5123 ha->requires_esl = 1;
5124 }
5125
5126 return (1);
5127}
5128
5129/****************************************************************************/
5130/* */
5131/* Routine Name: ips_reset_copperhead */
5132/* */
5133/* Routine Description: */
5134/* */
5135/* Reset the controller */
5136/* */
5137/****************************************************************************/
5138static int
5139ips_reset_copperhead(ips_ha_t * ha)
5140{
5141 int reset_counter;
5142
5143 METHOD_TRACE("ips_reset_copperhead", 1);
5144
5145 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005146 ips_name, ha->host_num, ha->io_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
5148 reset_counter = 0;
5149
5150 while (reset_counter < 2) {
5151 reset_counter++;
5152
5153 outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
5154
5155 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005156 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157
5158 outb(0, ha->io_addr + IPS_REG_SCPR);
5159
5160 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005161 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162
5163 if ((*ha->func.init) (ha))
5164 break;
5165 else if (reset_counter >= 2) {
5166
5167 return (0);
5168 }
5169 }
5170
5171 return (1);
5172}
5173
5174/****************************************************************************/
5175/* */
5176/* Routine Name: ips_reset_copperhead_memio */
5177/* */
5178/* Routine Description: */
5179/* */
5180/* Reset the controller */
5181/* */
5182/****************************************************************************/
5183static int
5184ips_reset_copperhead_memio(ips_ha_t * ha)
5185{
5186 int reset_counter;
5187
5188 METHOD_TRACE("ips_reset_copperhead_memio", 1);
5189
5190 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005191 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
5193 reset_counter = 0;
5194
5195 while (reset_counter < 2) {
5196 reset_counter++;
5197
5198 writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
5199
5200 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005201 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202
5203 writeb(0, ha->mem_ptr + IPS_REG_SCPR);
5204
5205 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005206 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
5208 if ((*ha->func.init) (ha))
5209 break;
5210 else if (reset_counter >= 2) {
5211
5212 return (0);
5213 }
5214 }
5215
5216 return (1);
5217}
5218
5219/****************************************************************************/
5220/* */
5221/* Routine Name: ips_reset_morpheus */
5222/* */
5223/* Routine Description: */
5224/* */
5225/* Reset the controller */
5226/* */
5227/****************************************************************************/
5228static int
5229ips_reset_morpheus(ips_ha_t * ha)
5230{
5231 int reset_counter;
5232 uint8_t junk;
5233
5234 METHOD_TRACE("ips_reset_morpheus", 1);
5235
5236 DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005237 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
5239 reset_counter = 0;
5240
5241 while (reset_counter < 2) {
5242 reset_counter++;
5243
5244 writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
5245
5246 /* Delay for 5 Seconds */
Andrew Mortonbf471342006-11-08 19:56:24 -08005247 MDELAY(5 * IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
5249 /* Do a PCI config read to wait for adapter */
5250 pci_read_config_byte(ha->pcidev, 4, &junk);
5251
5252 if ((*ha->func.init) (ha))
5253 break;
5254 else if (reset_counter >= 2) {
5255
5256 return (0);
5257 }
5258 }
5259
5260 return (1);
5261}
5262
5263/****************************************************************************/
5264/* */
5265/* Routine Name: ips_statinit */
5266/* */
5267/* Routine Description: */
5268/* */
5269/* Initialize the status queues on the controller */
5270/* */
5271/****************************************************************************/
5272static void
5273ips_statinit(ips_ha_t * ha)
5274{
5275 uint32_t phys_status_start;
5276
5277 METHOD_TRACE("ips_statinit", 1);
5278
5279 ha->adapt->p_status_start = ha->adapt->status;
5280 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5281 ha->adapt->p_status_tail = ha->adapt->status;
5282
5283 phys_status_start = ha->adapt->hw_status_start;
5284 outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
5285 outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
5286 ha->io_addr + IPS_REG_SQER);
5287 outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
5288 ha->io_addr + IPS_REG_SQHR);
5289 outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
5290
5291 ha->adapt->hw_status_tail = phys_status_start;
5292}
5293
5294/****************************************************************************/
5295/* */
5296/* Routine Name: ips_statinit_memio */
5297/* */
5298/* Routine Description: */
5299/* */
5300/* Initialize the status queues on the controller */
5301/* */
5302/****************************************************************************/
5303static void
5304ips_statinit_memio(ips_ha_t * ha)
5305{
5306 uint32_t phys_status_start;
5307
5308 METHOD_TRACE("ips_statinit_memio", 1);
5309
5310 ha->adapt->p_status_start = ha->adapt->status;
5311 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5312 ha->adapt->p_status_tail = ha->adapt->status;
5313
5314 phys_status_start = ha->adapt->hw_status_start;
5315 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQSR);
5316 writel(phys_status_start + IPS_STATUS_Q_SIZE,
5317 ha->mem_ptr + IPS_REG_SQER);
5318 writel(phys_status_start + IPS_STATUS_SIZE, ha->mem_ptr + IPS_REG_SQHR);
5319 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQTR);
5320
5321 ha->adapt->hw_status_tail = phys_status_start;
5322}
5323
5324/****************************************************************************/
5325/* */
5326/* Routine Name: ips_statupd_copperhead */
5327/* */
5328/* Routine Description: */
5329/* */
5330/* Remove an element from the status queue */
5331/* */
5332/****************************************************************************/
5333static uint32_t
5334ips_statupd_copperhead(ips_ha_t * ha)
5335{
5336 METHOD_TRACE("ips_statupd_copperhead", 1);
5337
5338 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5339 ha->adapt->p_status_tail++;
5340 ha->adapt->hw_status_tail += sizeof (IPS_STATUS);
5341 } else {
5342 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5343 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5344 }
5345
5346 outl(cpu_to_le32(ha->adapt->hw_status_tail),
5347 ha->io_addr + IPS_REG_SQTR);
5348
5349 return (ha->adapt->p_status_tail->value);
5350}
5351
5352/****************************************************************************/
5353/* */
5354/* Routine Name: ips_statupd_copperhead_memio */
5355/* */
5356/* Routine Description: */
5357/* */
5358/* Remove an element from the status queue */
5359/* */
5360/****************************************************************************/
5361static uint32_t
5362ips_statupd_copperhead_memio(ips_ha_t * ha)
5363{
5364 METHOD_TRACE("ips_statupd_copperhead_memio", 1);
5365
5366 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5367 ha->adapt->p_status_tail++;
5368 ha->adapt->hw_status_tail += sizeof (IPS_STATUS);
5369 } else {
5370 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5371 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5372 }
5373
5374 writel(ha->adapt->hw_status_tail, ha->mem_ptr + IPS_REG_SQTR);
5375
5376 return (ha->adapt->p_status_tail->value);
5377}
5378
5379/****************************************************************************/
5380/* */
5381/* Routine Name: ips_statupd_morpheus */
5382/* */
5383/* Routine Description: */
5384/* */
5385/* Remove an element from the status queue */
5386/* */
5387/****************************************************************************/
5388static uint32_t
5389ips_statupd_morpheus(ips_ha_t * ha)
5390{
5391 uint32_t val;
5392
5393 METHOD_TRACE("ips_statupd_morpheus", 1);
5394
5395 val = readl(ha->mem_ptr + IPS_REG_I2O_OUTMSGQ);
5396
5397 return (val);
5398}
5399
5400/****************************************************************************/
5401/* */
5402/* Routine Name: ips_issue_copperhead */
5403/* */
5404/* Routine Description: */
5405/* */
5406/* Send a command down to the controller */
5407/* */
5408/****************************************************************************/
5409static int
5410ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
5411{
5412 uint32_t TimeOut;
5413 uint32_t val;
5414
5415 METHOD_TRACE("ips_issue_copperhead", 1);
5416
5417 if (scb->scsi_cmd) {
5418 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5419 ips_name,
5420 ha->host_num,
5421 scb->cdb[0],
5422 scb->cmd.basic_io.command_id,
5423 scb->bus, scb->target_id, scb->lun);
5424 } else {
5425 DEBUG_VAR(2, KERN_NOTICE "(%s%d) ips_issue: logical cmd id %d",
5426 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5427 }
5428
5429 TimeOut = 0;
5430
5431 while ((val =
5432 le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
5433 udelay(1000);
5434
5435 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5436 if (!(val & IPS_BIT_START_STOP))
5437 break;
5438
5439 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5440 "ips_issue val [0x%x].\n", val);
5441 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5442 "ips_issue semaphore chk timeout.\n");
5443
5444 return (IPS_FAILURE);
5445 } /* end if */
5446 } /* end while */
5447
5448 outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
5449 outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
5450
5451 return (IPS_SUCCESS);
5452}
5453
5454/****************************************************************************/
5455/* */
5456/* Routine Name: ips_issue_copperhead_memio */
5457/* */
5458/* Routine Description: */
5459/* */
5460/* Send a command down to the controller */
5461/* */
5462/****************************************************************************/
5463static int
5464ips_issue_copperhead_memio(ips_ha_t * ha, ips_scb_t * scb)
5465{
5466 uint32_t TimeOut;
5467 uint32_t val;
5468
5469 METHOD_TRACE("ips_issue_copperhead_memio", 1);
5470
5471 if (scb->scsi_cmd) {
5472 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5473 ips_name,
5474 ha->host_num,
5475 scb->cdb[0],
5476 scb->cmd.basic_io.command_id,
5477 scb->bus, scb->target_id, scb->lun);
5478 } else {
5479 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5480 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5481 }
5482
5483 TimeOut = 0;
5484
5485 while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
5486 udelay(1000);
5487
5488 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5489 if (!(val & IPS_BIT_START_STOP))
5490 break;
5491
5492 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5493 "ips_issue val [0x%x].\n", val);
5494 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5495 "ips_issue semaphore chk timeout.\n");
5496
5497 return (IPS_FAILURE);
5498 } /* end if */
5499 } /* end while */
5500
5501 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_CCSAR);
5502 writel(IPS_BIT_START_CMD, ha->mem_ptr + IPS_REG_CCCR);
5503
5504 return (IPS_SUCCESS);
5505}
5506
5507/****************************************************************************/
5508/* */
5509/* Routine Name: ips_issue_i2o */
5510/* */
5511/* Routine Description: */
5512/* */
5513/* Send a command down to the controller */
5514/* */
5515/****************************************************************************/
5516static int
5517ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
5518{
5519
5520 METHOD_TRACE("ips_issue_i2o", 1);
5521
5522 if (scb->scsi_cmd) {
5523 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5524 ips_name,
5525 ha->host_num,
5526 scb->cdb[0],
5527 scb->cmd.basic_io.command_id,
5528 scb->bus, scb->target_id, scb->lun);
5529 } else {
5530 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5531 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5532 }
5533
5534 outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
5535
5536 return (IPS_SUCCESS);
5537}
5538
5539/****************************************************************************/
5540/* */
5541/* Routine Name: ips_issue_i2o_memio */
5542/* */
5543/* Routine Description: */
5544/* */
5545/* Send a command down to the controller */
5546/* */
5547/****************************************************************************/
5548static int
5549ips_issue_i2o_memio(ips_ha_t * ha, ips_scb_t * scb)
5550{
5551
5552 METHOD_TRACE("ips_issue_i2o_memio", 1);
5553
5554 if (scb->scsi_cmd) {
5555 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5556 ips_name,
5557 ha->host_num,
5558 scb->cdb[0],
5559 scb->cmd.basic_io.command_id,
5560 scb->bus, scb->target_id, scb->lun);
5561 } else {
5562 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5563 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5564 }
5565
5566 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_I2O_INMSGQ);
5567
5568 return (IPS_SUCCESS);
5569}
5570
5571/****************************************************************************/
5572/* */
5573/* Routine Name: ips_isintr_copperhead */
5574/* */
5575/* Routine Description: */
5576/* */
5577/* Test to see if an interrupt is for us */
5578/* */
5579/****************************************************************************/
5580static int
5581ips_isintr_copperhead(ips_ha_t * ha)
5582{
5583 uint8_t Isr;
5584
5585 METHOD_TRACE("ips_isintr_copperhead", 2);
5586
5587 Isr = inb(ha->io_addr + IPS_REG_HISR);
5588
5589 if (Isr == 0xFF)
5590 /* ?!?! Nothing really there */
5591 return (0);
5592
5593 if (Isr & IPS_BIT_SCE)
5594 return (1);
5595 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5596 /* status queue overflow or GHI */
5597 /* just clear the interrupt */
5598 outb(Isr, ha->io_addr + IPS_REG_HISR);
5599 }
5600
5601 return (0);
5602}
5603
5604/****************************************************************************/
5605/* */
5606/* Routine Name: ips_isintr_copperhead_memio */
5607/* */
5608/* Routine Description: */
5609/* */
5610/* Test to see if an interrupt is for us */
5611/* */
5612/****************************************************************************/
5613static int
5614ips_isintr_copperhead_memio(ips_ha_t * ha)
5615{
5616 uint8_t Isr;
5617
5618 METHOD_TRACE("ips_isintr_memio", 2);
5619
5620 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
5621
5622 if (Isr == 0xFF)
5623 /* ?!?! Nothing really there */
5624 return (0);
5625
5626 if (Isr & IPS_BIT_SCE)
5627 return (1);
5628 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5629 /* status queue overflow or GHI */
5630 /* just clear the interrupt */
5631 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
5632 }
5633
5634 return (0);
5635}
5636
5637/****************************************************************************/
5638/* */
5639/* Routine Name: ips_isintr_morpheus */
5640/* */
5641/* Routine Description: */
5642/* */
5643/* Test to see if an interrupt is for us */
5644/* */
5645/****************************************************************************/
5646static int
5647ips_isintr_morpheus(ips_ha_t * ha)
5648{
5649 uint32_t Isr;
5650
5651 METHOD_TRACE("ips_isintr_morpheus", 2);
5652
5653 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5654
5655 if (Isr & IPS_BIT_I2O_OPQI)
5656 return (1);
5657 else
5658 return (0);
5659}
5660
5661/****************************************************************************/
5662/* */
5663/* Routine Name: ips_wait */
5664/* */
5665/* Routine Description: */
5666/* */
5667/* Wait for a command to complete */
5668/* */
5669/****************************************************************************/
5670static int
5671ips_wait(ips_ha_t * ha, int time, int intr)
5672{
5673 int ret;
5674 int done;
5675
5676 METHOD_TRACE("ips_wait", 1);
5677
5678 ret = IPS_FAILURE;
5679 done = FALSE;
5680
5681 time *= IPS_ONE_SEC; /* convert seconds */
5682
5683 while ((time > 0) && (!done)) {
5684 if (intr == IPS_INTR_ON) {
5685 if (ha->waitflag == FALSE) {
5686 ret = IPS_SUCCESS;
5687 done = TRUE;
5688 break;
5689 }
5690 } else if (intr == IPS_INTR_IORL) {
5691 if (ha->waitflag == FALSE) {
5692 /*
5693 * controller generated an interrupt to
5694 * acknowledge completion of the command
5695 * and ips_intr() has serviced the interrupt.
5696 */
5697 ret = IPS_SUCCESS;
5698 done = TRUE;
5699 break;
5700 }
5701
5702 /*
5703 * NOTE: we already have the io_request_lock so
5704 * even if we get an interrupt it won't get serviced
5705 * until after we finish.
5706 */
5707
5708 (*ha->func.intr) (ha);
5709 }
5710
5711 /* This looks like a very evil loop, but it only does this during start-up */
5712 udelay(1000);
5713 time--;
5714 }
5715
5716 return (ret);
5717}
5718
5719/****************************************************************************/
5720/* */
5721/* Routine Name: ips_write_driver_status */
5722/* */
5723/* Routine Description: */
5724/* */
5725/* Write OS/Driver version to Page 5 of the nvram on the controller */
5726/* */
5727/****************************************************************************/
5728static int
5729ips_write_driver_status(ips_ha_t * ha, int intr)
5730{
5731 METHOD_TRACE("ips_write_driver_status", 1);
5732
5733 if (!ips_readwrite_page5(ha, FALSE, intr)) {
5734 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5735 "unable to read NVRAM page 5.\n");
5736
5737 return (0);
5738 }
5739
5740 /* check to make sure the page has a valid */
5741 /* signature */
5742 if (le32_to_cpu(ha->nvram->signature) != IPS_NVRAM_P5_SIG) {
5743 DEBUG_VAR(1,
5744 "(%s%d) NVRAM page 5 has an invalid signature: %X.",
5745 ips_name, ha->host_num, ha->nvram->signature);
5746 ha->nvram->signature = IPS_NVRAM_P5_SIG;
5747 }
5748
5749 DEBUG_VAR(2,
5750 "(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.",
5751 ips_name, ha->host_num, le16_to_cpu(ha->nvram->adapter_type),
5752 ha->nvram->adapter_slot, ha->nvram->bios_high[0],
5753 ha->nvram->bios_high[1], ha->nvram->bios_high[2],
5754 ha->nvram->bios_high[3], ha->nvram->bios_low[0],
5755 ha->nvram->bios_low[1], ha->nvram->bios_low[2],
5756 ha->nvram->bios_low[3]);
5757
5758 ips_get_bios_version(ha, intr);
5759
5760 /* change values (as needed) */
5761 ha->nvram->operating_system = IPS_OS_LINUX;
5762 ha->nvram->adapter_type = ha->ad_type;
5763 strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
5764 strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
5765 strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
5766 strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
5767
Jack Hammera60768e2005-11-03 09:46:00 -05005768 ha->nvram->versioning = 0; /* Indicate the Driver Does Not Support Versioning */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769
5770 /* now update the page */
5771 if (!ips_readwrite_page5(ha, TRUE, intr)) {
5772 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5773 "unable to write NVRAM page 5.\n");
5774
5775 return (0);
5776 }
5777
5778 /* IF NVRAM Page 5 is OK, Use it for Slot Number Info Because Linux Doesn't Do Slots */
5779 ha->slot_num = ha->nvram->adapter_slot;
5780
5781 return (1);
5782}
5783
5784/****************************************************************************/
5785/* */
5786/* Routine Name: ips_read_adapter_status */
5787/* */
5788/* Routine Description: */
5789/* */
5790/* Do an Inquiry command to the adapter */
5791/* */
5792/****************************************************************************/
5793static int
5794ips_read_adapter_status(ips_ha_t * ha, int intr)
5795{
5796 ips_scb_t *scb;
5797 int ret;
5798
5799 METHOD_TRACE("ips_read_adapter_status", 1);
5800
5801 scb = &ha->scbs[ha->max_cmds - 1];
5802
5803 ips_init_scb(ha, scb);
5804
5805 scb->timeout = ips_cmd_timeout;
5806 scb->cdb[0] = IPS_CMD_ENQUIRY;
5807
5808 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
5809 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5810 scb->cmd.basic_io.sg_count = 0;
5811 scb->cmd.basic_io.lba = 0;
5812 scb->cmd.basic_io.sector_count = 0;
5813 scb->cmd.basic_io.log_drv = 0;
5814 scb->data_len = sizeof (*ha->enq);
5815 scb->cmd.basic_io.sg_addr = ha->enq_busaddr;
5816
5817 /* send command */
5818 if (((ret =
5819 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5820 || (ret == IPS_SUCCESS_IMM)
5821 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5822 return (0);
5823
5824 return (1);
5825}
5826
5827/****************************************************************************/
5828/* */
5829/* Routine Name: ips_read_subsystem_parameters */
5830/* */
5831/* Routine Description: */
5832/* */
5833/* Read subsystem parameters from the adapter */
5834/* */
5835/****************************************************************************/
5836static int
5837ips_read_subsystem_parameters(ips_ha_t * ha, int intr)
5838{
5839 ips_scb_t *scb;
5840 int ret;
5841
5842 METHOD_TRACE("ips_read_subsystem_parameters", 1);
5843
5844 scb = &ha->scbs[ha->max_cmds - 1];
5845
5846 ips_init_scb(ha, scb);
5847
5848 scb->timeout = ips_cmd_timeout;
5849 scb->cdb[0] = IPS_CMD_GET_SUBSYS;
5850
5851 scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS;
5852 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5853 scb->cmd.basic_io.sg_count = 0;
5854 scb->cmd.basic_io.lba = 0;
5855 scb->cmd.basic_io.sector_count = 0;
5856 scb->cmd.basic_io.log_drv = 0;
5857 scb->data_len = sizeof (*ha->subsys);
5858 scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
5859
5860 /* send command */
5861 if (((ret =
5862 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5863 || (ret == IPS_SUCCESS_IMM)
5864 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5865 return (0);
5866
5867 memcpy(ha->subsys, ha->ioctl_data, sizeof(*ha->subsys));
5868 return (1);
5869}
5870
5871/****************************************************************************/
5872/* */
5873/* Routine Name: ips_read_config */
5874/* */
5875/* Routine Description: */
5876/* */
5877/* Read the configuration on the adapter */
5878/* */
5879/****************************************************************************/
5880static int
5881ips_read_config(ips_ha_t * ha, int intr)
5882{
5883 ips_scb_t *scb;
5884 int i;
5885 int ret;
5886
5887 METHOD_TRACE("ips_read_config", 1);
5888
5889 /* set defaults for initiator IDs */
5890 for (i = 0; i < 4; i++)
5891 ha->conf->init_id[i] = 7;
5892
5893 scb = &ha->scbs[ha->max_cmds - 1];
5894
5895 ips_init_scb(ha, scb);
5896
5897 scb->timeout = ips_cmd_timeout;
5898 scb->cdb[0] = IPS_CMD_READ_CONF;
5899
5900 scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF;
5901 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5902 scb->data_len = sizeof (*ha->conf);
5903 scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
5904
5905 /* send command */
5906 if (((ret =
5907 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5908 || (ret == IPS_SUCCESS_IMM)
5909 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5910
5911 memset(ha->conf, 0, sizeof (IPS_CONF));
5912
5913 /* reset initiator IDs */
5914 for (i = 0; i < 4; i++)
5915 ha->conf->init_id[i] = 7;
5916
5917 /* Allow Completed with Errors, so JCRM can access the Adapter to fix the problems */
5918 if ((scb->basic_status & IPS_GSC_STATUS_MASK) ==
5919 IPS_CMD_CMPLT_WERROR)
5920 return (1);
5921
5922 return (0);
5923 }
Jeff Garzik2f277d62007-12-13 16:14:08 -08005924
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 memcpy(ha->conf, ha->ioctl_data, sizeof(*ha->conf));
5926 return (1);
5927}
5928
5929/****************************************************************************/
5930/* */
5931/* Routine Name: ips_readwrite_page5 */
5932/* */
5933/* Routine Description: */
5934/* */
5935/* Read nvram page 5 from the adapter */
5936/* */
5937/****************************************************************************/
5938static int
5939ips_readwrite_page5(ips_ha_t * ha, int write, int intr)
5940{
5941 ips_scb_t *scb;
5942 int ret;
5943
5944 METHOD_TRACE("ips_readwrite_page5", 1);
5945
5946 scb = &ha->scbs[ha->max_cmds - 1];
5947
5948 ips_init_scb(ha, scb);
5949
5950 scb->timeout = ips_cmd_timeout;
5951 scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE;
5952
5953 scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE;
5954 scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
5955 scb->cmd.nvram.page = 5;
5956 scb->cmd.nvram.write = write;
5957 scb->cmd.nvram.reserved = 0;
5958 scb->cmd.nvram.reserved2 = 0;
5959 scb->data_len = sizeof (*ha->nvram);
5960 scb->cmd.nvram.buffer_addr = ha->ioctl_busaddr;
5961 if (write)
5962 memcpy(ha->ioctl_data, ha->nvram, sizeof(*ha->nvram));
Jeff Garzik2f277d62007-12-13 16:14:08 -08005963
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964 /* issue the command */
5965 if (((ret =
5966 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5967 || (ret == IPS_SUCCESS_IMM)
5968 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5969
5970 memset(ha->nvram, 0, sizeof (IPS_NVRAM_P5));
5971
5972 return (0);
5973 }
5974 if (!write)
5975 memcpy(ha->nvram, ha->ioctl_data, sizeof(*ha->nvram));
5976 return (1);
5977}
5978
5979/****************************************************************************/
5980/* */
5981/* Routine Name: ips_clear_adapter */
5982/* */
5983/* Routine Description: */
5984/* */
5985/* Clear the stripe lock tables */
5986/* */
5987/****************************************************************************/
5988static int
5989ips_clear_adapter(ips_ha_t * ha, int intr)
5990{
5991 ips_scb_t *scb;
5992 int ret;
5993
5994 METHOD_TRACE("ips_clear_adapter", 1);
5995
5996 scb = &ha->scbs[ha->max_cmds - 1];
5997
5998 ips_init_scb(ha, scb);
5999
6000 scb->timeout = ips_reset_timeout;
6001 scb->cdb[0] = IPS_CMD_CONFIG_SYNC;
6002
6003 scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC;
6004 scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
6005 scb->cmd.config_sync.channel = 0;
6006 scb->cmd.config_sync.source_target = IPS_POCL;
6007 scb->cmd.config_sync.reserved = 0;
6008 scb->cmd.config_sync.reserved2 = 0;
6009 scb->cmd.config_sync.reserved3 = 0;
6010
6011 /* issue command */
6012 if (((ret =
6013 ips_send_wait(ha, scb, ips_reset_timeout, intr)) == IPS_FAILURE)
6014 || (ret == IPS_SUCCESS_IMM)
6015 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
6016 return (0);
6017
6018 /* send unlock stripe command */
6019 ips_init_scb(ha, scb);
6020
6021 scb->cdb[0] = IPS_CMD_ERROR_TABLE;
6022 scb->timeout = ips_reset_timeout;
6023
6024 scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE;
6025 scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
6026 scb->cmd.unlock_stripe.log_drv = 0;
6027 scb->cmd.unlock_stripe.control = IPS_CSL;
6028 scb->cmd.unlock_stripe.reserved = 0;
6029 scb->cmd.unlock_stripe.reserved2 = 0;
6030 scb->cmd.unlock_stripe.reserved3 = 0;
6031
6032 /* issue command */
6033 if (((ret =
6034 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
6035 || (ret == IPS_SUCCESS_IMM)
6036 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
6037 return (0);
6038
6039 return (1);
6040}
6041
6042/****************************************************************************/
6043/* */
6044/* Routine Name: ips_ffdc_reset */
6045/* */
6046/* Routine Description: */
6047/* */
6048/* FFDC: write reset info */
6049/* */
6050/****************************************************************************/
6051static void
6052ips_ffdc_reset(ips_ha_t * ha, int intr)
6053{
6054 ips_scb_t *scb;
6055
6056 METHOD_TRACE("ips_ffdc_reset", 1);
6057
6058 scb = &ha->scbs[ha->max_cmds - 1];
6059
6060 ips_init_scb(ha, scb);
6061
6062 scb->timeout = ips_cmd_timeout;
6063 scb->cdb[0] = IPS_CMD_FFDC;
6064 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6065 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6066 scb->cmd.ffdc.reset_count = ha->reset_count;
6067 scb->cmd.ffdc.reset_type = 0x80;
6068
6069 /* convert time to what the card wants */
6070 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6071
6072 /* issue command */
6073 ips_send_wait(ha, scb, ips_cmd_timeout, intr);
6074}
6075
6076/****************************************************************************/
6077/* */
6078/* Routine Name: ips_ffdc_time */
6079/* */
6080/* Routine Description: */
6081/* */
6082/* FFDC: write time info */
6083/* */
6084/****************************************************************************/
6085static void
6086ips_ffdc_time(ips_ha_t * ha)
6087{
6088 ips_scb_t *scb;
6089
6090 METHOD_TRACE("ips_ffdc_time", 1);
6091
6092 DEBUG_VAR(1, "(%s%d) Sending time update.", ips_name, ha->host_num);
6093
6094 scb = &ha->scbs[ha->max_cmds - 1];
6095
6096 ips_init_scb(ha, scb);
6097
6098 scb->timeout = ips_cmd_timeout;
6099 scb->cdb[0] = IPS_CMD_FFDC;
6100 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6101 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6102 scb->cmd.ffdc.reset_count = 0;
6103 scb->cmd.ffdc.reset_type = 0;
6104
6105 /* convert time to what the card wants */
6106 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6107
6108 /* issue command */
6109 ips_send_wait(ha, scb, ips_cmd_timeout, IPS_FFDC);
6110}
6111
6112/****************************************************************************/
6113/* */
6114/* Routine Name: ips_fix_ffdc_time */
6115/* */
6116/* Routine Description: */
6117/* Adjust time_t to what the card wants */
6118/* */
6119/****************************************************************************/
6120static void
6121ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time_t current_time)
6122{
6123 long days;
6124 long rem;
6125 int i;
6126 int year;
6127 int yleap;
6128 int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
6129 int month_lengths[12][2] = { {31, 31},
6130 {28, 29},
6131 {31, 31},
6132 {30, 30},
6133 {31, 31},
6134 {30, 30},
6135 {31, 31},
6136 {31, 31},
6137 {30, 30},
6138 {31, 31},
6139 {30, 30},
6140 {31, 31}
6141 };
6142
6143 METHOD_TRACE("ips_fix_ffdc_time", 1);
6144
6145 days = current_time / IPS_SECS_DAY;
6146 rem = current_time % IPS_SECS_DAY;
6147
6148 scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
6149 rem = rem % IPS_SECS_HOUR;
6150 scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
6151 scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
6152
6153 year = IPS_EPOCH_YEAR;
6154 while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
6155 int newy;
6156
6157 newy = year + (days / IPS_DAYS_NORMAL_YEAR);
6158 if (days < 0)
6159 --newy;
6160 days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
6161 IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
6162 IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
6163 year = newy;
6164 }
6165
6166 scb->cmd.ffdc.yearH = year / 100;
6167 scb->cmd.ffdc.yearL = year % 100;
6168
6169 for (i = 0; days >= month_lengths[i][yleap]; ++i)
6170 days -= month_lengths[i][yleap];
6171
6172 scb->cmd.ffdc.month = i + 1;
6173 scb->cmd.ffdc.day = days + 1;
6174}
6175
6176/****************************************************************************
6177 * BIOS Flash Routines *
6178 ****************************************************************************/
6179
6180/****************************************************************************/
6181/* */
6182/* Routine Name: ips_erase_bios */
6183/* */
6184/* Routine Description: */
6185/* Erase the BIOS on the adapter */
6186/* */
6187/****************************************************************************/
6188static int
6189ips_erase_bios(ips_ha_t * ha)
6190{
6191 int timeout;
6192 uint8_t status = 0;
6193
6194 METHOD_TRACE("ips_erase_bios", 1);
6195
6196 status = 0;
6197
6198 /* Clear the status register */
6199 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006200 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201 udelay(25); /* 25 us */
6202
6203 outb(0x50, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006204 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006205 udelay(25); /* 25 us */
6206
6207 /* Erase Setup */
6208 outb(0x20, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006209 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210 udelay(25); /* 25 us */
6211
6212 /* Erase Confirm */
6213 outb(0xD0, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006214 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215 udelay(25); /* 25 us */
6216
6217 /* Erase Status */
6218 outb(0x70, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006219 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220 udelay(25); /* 25 us */
6221
6222 timeout = 80000; /* 80 seconds */
6223
6224 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006225 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226 outl(0, ha->io_addr + IPS_REG_FLAP);
6227 udelay(25); /* 25 us */
6228 }
6229
6230 status = inb(ha->io_addr + IPS_REG_FLDP);
6231
6232 if (status & 0x80)
6233 break;
6234
6235 MDELAY(1);
6236 timeout--;
6237 }
6238
6239 /* check for timeout */
6240 if (timeout <= 0) {
6241 /* timeout */
6242
6243 /* try to suspend the erase */
6244 outb(0xB0, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006245 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246 udelay(25); /* 25 us */
6247
6248 /* wait for 10 seconds */
6249 timeout = 10000;
6250 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006251 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252 outl(0, ha->io_addr + IPS_REG_FLAP);
6253 udelay(25); /* 25 us */
6254 }
6255
6256 status = inb(ha->io_addr + IPS_REG_FLDP);
6257
6258 if (status & 0xC0)
6259 break;
6260
6261 MDELAY(1);
6262 timeout--;
6263 }
6264
6265 return (1);
6266 }
6267
6268 /* check for valid VPP */
6269 if (status & 0x08)
6270 /* VPP failure */
6271 return (1);
6272
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02006273 /* check for successful flash */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274 if (status & 0x30)
6275 /* sequence error */
6276 return (1);
6277
6278 /* Otherwise, we were successful */
6279 /* clear status */
6280 outb(0x50, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006281 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282 udelay(25); /* 25 us */
6283
6284 /* enable reads */
6285 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006286 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287 udelay(25); /* 25 us */
6288
6289 return (0);
6290}
6291
6292/****************************************************************************/
6293/* */
6294/* Routine Name: ips_erase_bios_memio */
6295/* */
6296/* Routine Description: */
6297/* Erase the BIOS on the adapter */
6298/* */
6299/****************************************************************************/
6300static int
6301ips_erase_bios_memio(ips_ha_t * ha)
6302{
6303 int timeout;
6304 uint8_t status;
6305
6306 METHOD_TRACE("ips_erase_bios_memio", 1);
6307
6308 status = 0;
6309
6310 /* Clear the status register */
6311 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006312 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313 udelay(25); /* 25 us */
6314
6315 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006316 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006317 udelay(25); /* 25 us */
6318
6319 /* Erase Setup */
6320 writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006321 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006322 udelay(25); /* 25 us */
6323
6324 /* Erase Confirm */
6325 writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006326 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006327 udelay(25); /* 25 us */
6328
6329 /* Erase Status */
6330 writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006331 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332 udelay(25); /* 25 us */
6333
6334 timeout = 80000; /* 80 seconds */
6335
6336 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006337 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6339 udelay(25); /* 25 us */
6340 }
6341
6342 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6343
6344 if (status & 0x80)
6345 break;
6346
6347 MDELAY(1);
6348 timeout--;
6349 }
6350
6351 /* check for timeout */
6352 if (timeout <= 0) {
6353 /* timeout */
6354
6355 /* try to suspend the erase */
6356 writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006357 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006358 udelay(25); /* 25 us */
6359
6360 /* wait for 10 seconds */
6361 timeout = 10000;
6362 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006363 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6365 udelay(25); /* 25 us */
6366 }
6367
6368 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6369
6370 if (status & 0xC0)
6371 break;
6372
6373 MDELAY(1);
6374 timeout--;
6375 }
6376
6377 return (1);
6378 }
6379
6380 /* check for valid VPP */
6381 if (status & 0x08)
6382 /* VPP failure */
6383 return (1);
6384
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02006385 /* check for successful flash */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 if (status & 0x30)
6387 /* sequence error */
6388 return (1);
6389
6390 /* Otherwise, we were successful */
6391 /* clear status */
6392 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006393 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006394 udelay(25); /* 25 us */
6395
6396 /* enable reads */
6397 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006398 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006399 udelay(25); /* 25 us */
6400
6401 return (0);
6402}
6403
6404/****************************************************************************/
6405/* */
6406/* Routine Name: ips_program_bios */
6407/* */
6408/* Routine Description: */
6409/* Program the BIOS on the adapter */
6410/* */
6411/****************************************************************************/
6412static int
6413ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6414 uint32_t offset)
6415{
6416 int i;
6417 int timeout;
6418 uint8_t status = 0;
6419
6420 METHOD_TRACE("ips_program_bios", 1);
6421
6422 status = 0;
6423
6424 for (i = 0; i < buffersize; i++) {
6425 /* write a byte */
6426 outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006427 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006428 udelay(25); /* 25 us */
6429
6430 outb(0x40, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006431 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432 udelay(25); /* 25 us */
6433
6434 outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006435 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436 udelay(25); /* 25 us */
6437
6438 /* wait up to one second */
6439 timeout = 1000;
6440 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006441 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006442 outl(0, ha->io_addr + IPS_REG_FLAP);
6443 udelay(25); /* 25 us */
6444 }
6445
6446 status = inb(ha->io_addr + IPS_REG_FLDP);
6447
6448 if (status & 0x80)
6449 break;
6450
6451 MDELAY(1);
6452 timeout--;
6453 }
6454
6455 if (timeout == 0) {
6456 /* timeout error */
6457 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006458 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006459 udelay(25); /* 25 us */
6460
6461 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006462 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463 udelay(25); /* 25 us */
6464
6465 return (1);
6466 }
6467
6468 /* check the status */
6469 if (status & 0x18) {
6470 /* programming error */
6471 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006472 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473 udelay(25); /* 25 us */
6474
6475 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006476 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477 udelay(25); /* 25 us */
6478
6479 return (1);
6480 }
6481 } /* end for */
6482
6483 /* Enable reading */
6484 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006485 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486 udelay(25); /* 25 us */
6487
6488 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006489 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006490 udelay(25); /* 25 us */
6491
6492 return (0);
6493}
6494
6495/****************************************************************************/
6496/* */
6497/* Routine Name: ips_program_bios_memio */
6498/* */
6499/* Routine Description: */
6500/* Program the BIOS on the adapter */
6501/* */
6502/****************************************************************************/
6503static int
6504ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6505 uint32_t offset)
6506{
6507 int i;
6508 int timeout;
6509 uint8_t status = 0;
6510
6511 METHOD_TRACE("ips_program_bios_memio", 1);
6512
6513 status = 0;
6514
6515 for (i = 0; i < buffersize; i++) {
6516 /* write a byte */
6517 writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006518 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006519 udelay(25); /* 25 us */
6520
6521 writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006522 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006523 udelay(25); /* 25 us */
6524
6525 writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006526 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527 udelay(25); /* 25 us */
6528
6529 /* wait up to one second */
6530 timeout = 1000;
6531 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006532 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006533 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6534 udelay(25); /* 25 us */
6535 }
6536
6537 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6538
6539 if (status & 0x80)
6540 break;
6541
6542 MDELAY(1);
6543 timeout--;
6544 }
6545
6546 if (timeout == 0) {
6547 /* timeout error */
6548 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006549 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550 udelay(25); /* 25 us */
6551
6552 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006553 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554 udelay(25); /* 25 us */
6555
6556 return (1);
6557 }
6558
6559 /* check the status */
6560 if (status & 0x18) {
6561 /* programming error */
6562 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006563 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006564 udelay(25); /* 25 us */
6565
6566 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006567 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006568 udelay(25); /* 25 us */
6569
6570 return (1);
6571 }
6572 } /* end for */
6573
6574 /* Enable reading */
6575 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006576 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577 udelay(25); /* 25 us */
6578
6579 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006580 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006581 udelay(25); /* 25 us */
6582
6583 return (0);
6584}
6585
6586/****************************************************************************/
6587/* */
6588/* Routine Name: ips_verify_bios */
6589/* */
6590/* Routine Description: */
6591/* Verify the BIOS on the adapter */
6592/* */
6593/****************************************************************************/
6594static int
6595ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6596 uint32_t offset)
6597{
6598 uint8_t checksum;
6599 int i;
6600
6601 METHOD_TRACE("ips_verify_bios", 1);
6602
6603 /* test 1st byte */
6604 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006605 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006606 udelay(25); /* 25 us */
6607
6608 if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
6609 return (1);
6610
6611 outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006612 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006613 udelay(25); /* 25 us */
6614 if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
6615 return (1);
6616
6617 checksum = 0xff;
6618 for (i = 2; i < buffersize; i++) {
6619
6620 outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006621 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006622 udelay(25); /* 25 us */
6623
6624 checksum = (uint8_t) checksum + inb(ha->io_addr + IPS_REG_FLDP);
6625 }
6626
6627 if (checksum != 0)
6628 /* failure */
6629 return (1);
6630 else
6631 /* success */
6632 return (0);
6633}
6634
6635/****************************************************************************/
6636/* */
6637/* Routine Name: ips_verify_bios_memio */
6638/* */
6639/* Routine Description: */
6640/* Verify the BIOS on the adapter */
6641/* */
6642/****************************************************************************/
6643static int
6644ips_verify_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6645 uint32_t offset)
6646{
6647 uint8_t checksum;
6648 int i;
6649
6650 METHOD_TRACE("ips_verify_bios_memio", 1);
6651
6652 /* test 1st byte */
6653 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006654 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006655 udelay(25); /* 25 us */
6656
6657 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
6658 return (1);
6659
6660 writel(1, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006661 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006662 udelay(25); /* 25 us */
6663 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
6664 return (1);
6665
6666 checksum = 0xff;
6667 for (i = 2; i < buffersize; i++) {
6668
6669 writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006670 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671 udelay(25); /* 25 us */
6672
6673 checksum =
6674 (uint8_t) checksum + readb(ha->mem_ptr + IPS_REG_FLDP);
6675 }
6676
6677 if (checksum != 0)
6678 /* failure */
6679 return (1);
6680 else
6681 /* success */
6682 return (0);
6683}
6684
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685/****************************************************************************/
6686/* */
6687/* Routine Name: ips_abort_init */
6688/* */
6689/* Routine Description: */
6690/* cleanup routine for a failed adapter initialization */
6691/****************************************************************************/
6692static int
6693ips_abort_init(ips_ha_t * ha, int index)
6694{
6695 ha->active = 0;
6696 ips_free(ha);
6697 ips_ha[index] = NULL;
6698 ips_sh[index] = NULL;
6699 return -1;
6700}
6701
6702/****************************************************************************/
6703/* */
6704/* Routine Name: ips_shift_controllers */
6705/* */
6706/* Routine Description: */
6707/* helper function for ordering adapters */
6708/****************************************************************************/
6709static void
6710ips_shift_controllers(int lowindex, int highindex)
6711{
6712 ips_ha_t *ha_sav = ips_ha[highindex];
6713 struct Scsi_Host *sh_sav = ips_sh[highindex];
6714 int i;
6715
6716 for (i = highindex; i > lowindex; i--) {
6717 ips_ha[i] = ips_ha[i - 1];
6718 ips_sh[i] = ips_sh[i - 1];
6719 ips_ha[i]->host_num = i;
6720 }
6721 ha_sav->host_num = lowindex;
6722 ips_ha[lowindex] = ha_sav;
6723 ips_sh[lowindex] = sh_sav;
6724}
6725
6726/****************************************************************************/
6727/* */
6728/* Routine Name: ips_order_controllers */
6729/* */
6730/* Routine Description: */
6731/* place controllers is the "proper" boot order */
6732/****************************************************************************/
6733static void
6734ips_order_controllers(void)
6735{
6736 int i, j, tmp, position = 0;
6737 IPS_NVRAM_P5 *nvram;
6738 if (!ips_ha[0])
6739 return;
6740 nvram = ips_ha[0]->nvram;
6741
6742 if (nvram->adapter_order[0]) {
6743 for (i = 1; i <= nvram->adapter_order[0]; i++) {
6744 for (j = position; j < ips_num_controllers; j++) {
6745 switch (ips_ha[j]->ad_type) {
6746 case IPS_ADTYPE_SERVERAID6M:
6747 case IPS_ADTYPE_SERVERAID7M:
6748 if (nvram->adapter_order[i] == 'M') {
6749 ips_shift_controllers(position,
6750 j);
6751 position++;
6752 }
6753 break;
6754 case IPS_ADTYPE_SERVERAID4L:
6755 case IPS_ADTYPE_SERVERAID4M:
6756 case IPS_ADTYPE_SERVERAID4MX:
6757 case IPS_ADTYPE_SERVERAID4LX:
6758 if (nvram->adapter_order[i] == 'N') {
6759 ips_shift_controllers(position,
6760 j);
6761 position++;
6762 }
6763 break;
6764 case IPS_ADTYPE_SERVERAID6I:
6765 case IPS_ADTYPE_SERVERAID5I2:
6766 case IPS_ADTYPE_SERVERAID5I1:
6767 case IPS_ADTYPE_SERVERAID7k:
6768 if (nvram->adapter_order[i] == 'S') {
6769 ips_shift_controllers(position,
6770 j);
6771 position++;
6772 }
6773 break;
6774 case IPS_ADTYPE_SERVERAID:
6775 case IPS_ADTYPE_SERVERAID2:
6776 case IPS_ADTYPE_NAVAJO:
6777 case IPS_ADTYPE_KIOWA:
6778 case IPS_ADTYPE_SERVERAID3L:
6779 case IPS_ADTYPE_SERVERAID3:
6780 case IPS_ADTYPE_SERVERAID4H:
6781 if (nvram->adapter_order[i] == 'A') {
6782 ips_shift_controllers(position,
6783 j);
6784 position++;
6785 }
6786 break;
6787 default:
6788 break;
6789 }
6790 }
6791 }
6792 /* if adapter_order[0], then ordering is complete */
6793 return;
6794 }
6795 /* old bios, use older ordering */
6796 tmp = 0;
6797 for (i = position; i < ips_num_controllers; i++) {
6798 if (ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID5I2 ||
6799 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID5I1) {
6800 ips_shift_controllers(position, i);
6801 position++;
6802 tmp = 1;
6803 }
6804 }
6805 /* if there were no 5I cards, then don't do any extra ordering */
6806 if (!tmp)
6807 return;
6808 for (i = position; i < ips_num_controllers; i++) {
6809 if (ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4L ||
6810 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4M ||
6811 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4LX ||
6812 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4MX) {
6813 ips_shift_controllers(position, i);
6814 position++;
6815 }
6816 }
6817
6818 return;
6819}
6820
6821/****************************************************************************/
6822/* */
6823/* Routine Name: ips_register_scsi */
6824/* */
6825/* Routine Description: */
6826/* perform any registration and setup with the scsi layer */
6827/****************************************************************************/
6828static int
6829ips_register_scsi(int index)
6830{
6831 struct Scsi_Host *sh;
6832 ips_ha_t *ha, *oldha = ips_ha[index];
6833 sh = scsi_host_alloc(&ips_driver_template, sizeof (ips_ha_t));
6834 if (!sh) {
6835 IPS_PRINTK(KERN_WARNING, oldha->pcidev,
6836 "Unable to register controller with SCSI subsystem\n");
6837 return -1;
6838 }
6839 ha = IPS_HA(sh);
6840 memcpy(ha, oldha, sizeof (ips_ha_t));
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006841 free_irq(oldha->pcidev->irq, oldha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006842 /* Install the interrupt handler with the new ha */
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006843 if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006844 IPS_PRINTK(KERN_WARNING, ha->pcidev,
6845 "Unable to install interrupt handler\n");
6846 scsi_host_put(sh);
6847 return -1;
6848 }
6849
6850 kfree(oldha);
6851 ips_sh[index] = sh;
6852 ips_ha[index] = ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006853
6854 /* Store away needed values for later use */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006855 sh->unique_id = (ha->io_addr) ? ha->io_addr : ha->mem_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006856 sh->sg_tablesize = sh->hostt->sg_tablesize;
6857 sh->can_queue = sh->hostt->can_queue;
6858 sh->cmd_per_lun = sh->hostt->cmd_per_lun;
6859 sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
6860 sh->use_clustering = sh->hostt->use_clustering;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006861 sh->max_sectors = 128;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862
6863 sh->max_id = ha->ntargets;
6864 sh->max_lun = ha->nlun;
6865 sh->max_channel = ha->nbus - 1;
6866 sh->can_queue = ha->max_cmds - 1;
6867
Adrian Bunkc6a6c812007-05-23 14:41:46 -07006868 scsi_add_host(sh, NULL);
6869 scsi_scan_host(sh);
6870
Linus Torvalds1da177e2005-04-16 15:20:36 -07006871 return 0;
6872}
6873
6874/*---------------------------------------------------------------------------*/
6875/* Routine Name: ips_remove_device */
6876/* */
6877/* Routine Description: */
6878/* Remove one Adapter ( Hot Plugging ) */
6879/*---------------------------------------------------------------------------*/
6880static void __devexit
6881ips_remove_device(struct pci_dev *pci_dev)
6882{
6883 int i;
6884 struct Scsi_Host *sh;
6885 ips_ha_t *ha;
6886
6887 for (i = 0; i < IPS_MAX_ADAPTERS; i++) {
6888 ha = ips_ha[i];
6889 if (ha) {
6890 if ((pci_dev->bus->number == ha->pcidev->bus->number) &&
6891 (pci_dev->devfn == ha->pcidev->devfn)) {
6892 sh = ips_sh[i];
6893 ips_release(sh);
6894 }
6895 }
6896 }
6897}
6898
6899/****************************************************************************/
6900/* */
6901/* Routine Name: ips_module_init */
6902/* */
6903/* Routine Description: */
6904/* function called on module load */
6905/****************************************************************************/
6906static int __init
6907ips_module_init(void)
6908{
Alan Cox02a0fa62006-09-25 23:45:51 +01006909 if (pci_register_driver(&ips_pci_driver) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006910 return -ENODEV;
6911 ips_driver_template.module = THIS_MODULE;
6912 ips_order_controllers();
Adrian Bunkc6a6c812007-05-23 14:41:46 -07006913 if (!ips_detect(&ips_driver_template)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914 pci_unregister_driver(&ips_pci_driver);
6915 return -ENODEV;
6916 }
6917 register_reboot_notifier(&ips_notifier);
6918 return 0;
6919}
6920
6921/****************************************************************************/
6922/* */
6923/* Routine Name: ips_module_exit */
6924/* */
6925/* Routine Description: */
6926/* function called on module unload */
6927/****************************************************************************/
6928static void __exit
6929ips_module_exit(void)
6930{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006931 pci_unregister_driver(&ips_pci_driver);
6932 unregister_reboot_notifier(&ips_notifier);
6933}
6934
6935module_init(ips_module_init);
6936module_exit(ips_module_exit);
6937
6938/*---------------------------------------------------------------------------*/
6939/* Routine Name: ips_insert_device */
6940/* */
6941/* Routine Description: */
6942/* Add One Adapter ( Hot Plug ) */
6943/* */
6944/* Return Value: */
6945/* 0 if Successful, else non-zero */
6946/*---------------------------------------------------------------------------*/
6947static int __devinit
6948ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
6949{
Andrew Morton305aad02007-08-10 14:50:52 -07006950 int uninitialized_var(index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006951 int rc;
6952
6953 METHOD_TRACE("ips_insert_device", 1);
6954 if (pci_enable_device(pci_dev))
6955 return -1;
6956
6957 rc = ips_init_phase1(pci_dev, &index);
6958 if (rc == SUCCESS)
6959 rc = ips_init_phase2(index);
6960
6961 if (ips_hotplug)
6962 if (ips_register_scsi(index)) {
6963 ips_free(ips_ha[index]);
6964 rc = -1;
6965 }
6966
6967 if (rc == SUCCESS)
6968 ips_num_controllers++;
6969
6970 ips_next_controller = ips_num_controllers;
6971 return rc;
6972}
6973
6974/*---------------------------------------------------------------------------*/
6975/* Routine Name: ips_init_phase1 */
6976/* */
6977/* Routine Description: */
6978/* Adapter Initialization */
6979/* */
6980/* Return Value: */
6981/* 0 if Successful, else non-zero */
6982/*---------------------------------------------------------------------------*/
6983static int
6984ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
6985{
6986 ips_ha_t *ha;
6987 uint32_t io_addr;
6988 uint32_t mem_addr;
6989 uint32_t io_len;
6990 uint32_t mem_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006991 uint8_t bus;
6992 uint8_t func;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993 int j;
6994 int index;
6995 dma_addr_t dma_address;
6996 char __iomem *ioremap_ptr;
6997 char __iomem *mem_ptr;
6998 uint32_t IsDead;
6999
7000 METHOD_TRACE("ips_init_phase1", 1);
7001 index = IPS_MAX_ADAPTERS;
7002 for (j = 0; j < IPS_MAX_ADAPTERS; j++) {
7003 if (ips_ha[j] == 0) {
7004 index = j;
7005 break;
7006 }
7007 }
7008
7009 if (index >= IPS_MAX_ADAPTERS)
7010 return -1;
7011
7012 /* stuff that we get in dev */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007013 bus = pci_dev->bus->number;
7014 func = pci_dev->devfn;
7015
7016 /* Init MEM/IO addresses to 0 */
7017 mem_addr = 0;
7018 io_addr = 0;
7019 mem_len = 0;
7020 io_len = 0;
7021
7022 for (j = 0; j < 2; j++) {
7023 if (!pci_resource_start(pci_dev, j))
7024 break;
7025
7026 if (pci_resource_flags(pci_dev, j) & IORESOURCE_IO) {
7027 io_addr = pci_resource_start(pci_dev, j);
7028 io_len = pci_resource_len(pci_dev, j);
7029 } else {
7030 mem_addr = pci_resource_start(pci_dev, j);
7031 mem_len = pci_resource_len(pci_dev, j);
7032 }
7033 }
7034
7035 /* setup memory mapped area (if applicable) */
7036 if (mem_addr) {
7037 uint32_t base;
7038 uint32_t offs;
7039
7040 if (!request_mem_region(mem_addr, mem_len, "ips")) {
7041 IPS_PRINTK(KERN_WARNING, pci_dev,
7042 "Couldn't allocate IO Memory space %x len %d.\n",
7043 mem_addr, mem_len);
7044 return -1;
7045 }
7046
7047 base = mem_addr & PAGE_MASK;
7048 offs = mem_addr - base;
7049 ioremap_ptr = ioremap(base, PAGE_SIZE);
7050 mem_ptr = ioremap_ptr + offs;
7051 } else {
7052 ioremap_ptr = NULL;
7053 mem_ptr = NULL;
7054 }
7055
7056 /* setup I/O mapped area (if applicable) */
7057 if (io_addr) {
7058 if (!request_region(io_addr, io_len, "ips")) {
7059 IPS_PRINTK(KERN_WARNING, pci_dev,
7060 "Couldn't allocate IO space %x len %d.\n",
7061 io_addr, io_len);
7062 return -1;
7063 }
7064 }
7065
Linus Torvalds1da177e2005-04-16 15:20:36 -07007066 /* found a controller */
Yoann Padioleaudd00cc42007-07-19 01:49:03 -07007067 ha = kzalloc(sizeof (ips_ha_t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068 if (ha == NULL) {
7069 IPS_PRINTK(KERN_WARNING, pci_dev,
7070 "Unable to allocate temporary ha struct\n");
7071 return -1;
7072 }
7073
Linus Torvalds1da177e2005-04-16 15:20:36 -07007074
7075 ips_sh[index] = NULL;
7076 ips_ha[index] = ha;
7077 ha->active = 1;
7078
7079 /* Store info in HA structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007080 ha->io_addr = io_addr;
7081 ha->io_len = io_len;
7082 ha->mem_addr = mem_addr;
7083 ha->mem_len = mem_len;
7084 ha->mem_ptr = mem_ptr;
7085 ha->ioremap_ptr = ioremap_ptr;
7086 ha->host_num = (uint32_t) index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007087 ha->slot_num = PCI_SLOT(pci_dev->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007088 ha->pcidev = pci_dev;
7089
7090 /*
7091 * Set the pci_dev's dma_mask. Not all adapters support 64bit
7092 * addressing so don't enable it if the adapter can't support
7093 * it! Also, don't use 64bit addressing if dma addresses
7094 * are guaranteed to be < 4G.
7095 */
7096 if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
Matthias Gehre910638a2006-03-28 01:56:48 -08007097 !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007098 (ha)->flags |= IPS_HA_ENH_SG;
7099 } else {
Matthias Gehre910638a2006-03-28 01:56:48 -08007100 if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101 printk(KERN_WARNING "Unable to set DMA Mask\n");
7102 return ips_abort_init(ha, index);
7103 }
7104 }
7105 if(ips_cd_boot && !ips_FlashData){
7106 ips_FlashData = pci_alloc_consistent(pci_dev, PAGE_SIZE << 7,
7107 &ips_flashbusaddr);
7108 }
7109
7110 ha->enq = pci_alloc_consistent(pci_dev, sizeof (IPS_ENQ),
7111 &ha->enq_busaddr);
7112 if (!ha->enq) {
7113 IPS_PRINTK(KERN_WARNING, pci_dev,
7114 "Unable to allocate host inquiry structure\n");
7115 return ips_abort_init(ha, index);
7116 }
7117
7118 ha->adapt = pci_alloc_consistent(pci_dev, sizeof (IPS_ADAPTER) +
7119 sizeof (IPS_IO_CMD), &dma_address);
7120 if (!ha->adapt) {
7121 IPS_PRINTK(KERN_WARNING, pci_dev,
7122 "Unable to allocate host adapt & dummy structures\n");
7123 return ips_abort_init(ha, index);
7124 }
7125 ha->adapt->hw_status_start = dma_address;
7126 ha->dummy = (void *) (ha->adapt + 1);
7127
7128
7129
7130 ha->logical_drive_info = pci_alloc_consistent(pci_dev, sizeof (IPS_LD_INFO), &dma_address);
7131 if (!ha->logical_drive_info) {
7132 IPS_PRINTK(KERN_WARNING, pci_dev,
7133 "Unable to allocate logical drive info structure\n");
7134 return ips_abort_init(ha, index);
7135 }
7136 ha->logical_drive_info_dma_addr = dma_address;
7137
7138
7139 ha->conf = kmalloc(sizeof (IPS_CONF), GFP_KERNEL);
7140
7141 if (!ha->conf) {
7142 IPS_PRINTK(KERN_WARNING, pci_dev,
7143 "Unable to allocate host conf structure\n");
7144 return ips_abort_init(ha, index);
7145 }
7146
7147 ha->nvram = kmalloc(sizeof (IPS_NVRAM_P5), GFP_KERNEL);
7148
7149 if (!ha->nvram) {
7150 IPS_PRINTK(KERN_WARNING, pci_dev,
7151 "Unable to allocate host NVRAM structure\n");
7152 return ips_abort_init(ha, index);
7153 }
7154
7155 ha->subsys = kmalloc(sizeof (IPS_SUBSYS), GFP_KERNEL);
7156
7157 if (!ha->subsys) {
7158 IPS_PRINTK(KERN_WARNING, pci_dev,
7159 "Unable to allocate host subsystem structure\n");
7160 return ips_abort_init(ha, index);
7161 }
7162
7163 /* the ioctl buffer is now used during adapter initialization, so its
7164 * successful allocation is now required */
7165 if (ips_ioctlsize < PAGE_SIZE)
7166 ips_ioctlsize = PAGE_SIZE;
7167
7168 ha->ioctl_data = pci_alloc_consistent(pci_dev, ips_ioctlsize,
7169 &ha->ioctl_busaddr);
7170 ha->ioctl_len = ips_ioctlsize;
7171 if (!ha->ioctl_data) {
7172 IPS_PRINTK(KERN_WARNING, pci_dev,
7173 "Unable to allocate IOCTL data\n");
7174 return ips_abort_init(ha, index);
7175 }
7176
7177 /*
7178 * Setup Functions
7179 */
7180 ips_setup_funclist(ha);
7181
7182 if ((IPS_IS_MORPHEUS(ha)) || (IPS_IS_MARCO(ha))) {
7183 /* If Morpheus appears dead, reset it */
7184 IsDead = readl(ha->mem_ptr + IPS_REG_I960_MSG1);
7185 if (IsDead == 0xDEADBEEF) {
7186 ips_reset_morpheus(ha);
7187 }
7188 }
7189
7190 /*
7191 * Initialize the card if it isn't already
7192 */
7193
7194 if (!(*ha->func.isinit) (ha)) {
7195 if (!(*ha->func.init) (ha)) {
7196 /*
7197 * Initialization failed
7198 */
7199 IPS_PRINTK(KERN_WARNING, pci_dev,
7200 "Unable to initialize controller\n");
7201 return ips_abort_init(ha, index);
7202 }
7203 }
7204
7205 *indexPtr = index;
7206 return SUCCESS;
7207}
7208
7209/*---------------------------------------------------------------------------*/
7210/* Routine Name: ips_init_phase2 */
7211/* */
7212/* Routine Description: */
7213/* Adapter Initialization Phase 2 */
7214/* */
7215/* Return Value: */
7216/* 0 if Successful, else non-zero */
7217/*---------------------------------------------------------------------------*/
7218static int
7219ips_init_phase2(int index)
7220{
7221 ips_ha_t *ha;
7222
7223 ha = ips_ha[index];
7224
7225 METHOD_TRACE("ips_init_phase2", 1);
7226 if (!ha->active) {
7227 ips_ha[index] = NULL;
7228 return -1;
7229 }
7230
7231 /* Install the interrupt handler */
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007232 if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7234 "Unable to install interrupt handler\n");
7235 return ips_abort_init(ha, index);
7236 }
7237
7238 /*
7239 * Allocate a temporary SCB for initialization
7240 */
7241 ha->max_cmds = 1;
7242 if (!ips_allocatescbs(ha)) {
7243 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7244 "Unable to allocate a CCB\n");
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007245 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007246 return ips_abort_init(ha, index);
7247 }
7248
7249 if (!ips_hainit(ha)) {
7250 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7251 "Unable to initialize controller\n");
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007252 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253 return ips_abort_init(ha, index);
7254 }
7255 /* Free the temporary SCB */
7256 ips_deallocatescbs(ha, 1);
7257
7258 /* allocate CCBs */
7259 if (!ips_allocatescbs(ha)) {
7260 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7261 "Unable to allocate CCBs\n");
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007262 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007263 return ips_abort_init(ha, index);
7264 }
7265
7266 return SUCCESS;
7267}
7268
Linus Torvalds1da177e2005-04-16 15:20:36 -07007269MODULE_LICENSE("GPL");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007270MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007271MODULE_VERSION(IPS_VER_STRING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007272
7273
7274/*
7275 * Overrides for Emacs so that we almost follow Linus's tabbing style.
7276 * Emacs will notice this stuff at the end of the file and automatically
7277 * adjust the settings for this buffer only. This must remain at the end
7278 * of the file.
7279 * ---------------------------------------------------------------------------
7280 * Local variables:
7281 * c-indent-level: 2
7282 * c-brace-imaginary-offset: 0
7283 * c-brace-offset: -2
7284 * c-argdecl-indent: 2
7285 * c-label-offset: -2
7286 * c-continued-statement-offset: 2
7287 * c-continued-brace-offset: 0
7288 * indent-tabs-mode: nil
7289 * tab-width: 8
7290 * End:
7291 */