blob: 5f194a807f9400a52d0520649d03caf11a0c73ce [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 /* free IRQ */
Jeff Garzik8a694cc2007-12-13 16:14:07 -0800706 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 scsi_host_put(sh);
709
710 ips_released_controllers++;
711
712 return (FALSE);
713}
714
715/****************************************************************************/
716/* */
717/* Routine Name: ips_halt */
718/* */
719/* Routine Description: */
720/* */
721/* Perform cleanup when the system reboots */
722/* */
723/****************************************************************************/
724static int
725ips_halt(struct notifier_block *nb, ulong event, void *buf)
726{
727 ips_scb_t *scb;
728 ips_ha_t *ha;
729 int i;
730
731 if ((event != SYS_RESTART) && (event != SYS_HALT) &&
732 (event != SYS_POWER_OFF))
733 return (NOTIFY_DONE);
734
735 for (i = 0; i < ips_next_controller; i++) {
736 ha = (ips_ha_t *) ips_ha[i];
737
738 if (!ha)
739 continue;
740
741 if (!ha->active)
742 continue;
743
744 /* flush the cache on the controller */
745 scb = &ha->scbs[ha->max_cmds - 1];
746
747 ips_init_scb(ha, scb);
748
749 scb->timeout = ips_cmd_timeout;
750 scb->cdb[0] = IPS_CMD_FLUSH;
751
752 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
753 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
754 scb->cmd.flush_cache.state = IPS_NORM_STATE;
755 scb->cmd.flush_cache.reserved = 0;
756 scb->cmd.flush_cache.reserved2 = 0;
757 scb->cmd.flush_cache.reserved3 = 0;
758 scb->cmd.flush_cache.reserved4 = 0;
759
760 IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n");
761
762 /* send command */
763 if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) ==
764 IPS_FAILURE)
765 IPS_PRINTK(KERN_WARNING, ha->pcidev,
766 "Incomplete Flush.\n");
767 else
768 IPS_PRINTK(KERN_WARNING, ha->pcidev,
769 "Flushing Complete.\n");
770 }
771
772 return (NOTIFY_OK);
773}
774
775/****************************************************************************/
776/* */
777/* Routine Name: ips_eh_abort */
778/* */
779/* Routine Description: */
780/* */
781/* Abort a command (using the new error code stuff) */
782/* Note: this routine is called under the io_request_lock */
783/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +0200784int ips_eh_abort(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 ips_ha_t *ha;
787 ips_copp_wait_item_t *item;
788 int ret;
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400789 struct Scsi_Host *host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 METHOD_TRACE("ips_eh_abort", 1);
792
793 if (!SC)
794 return (FAILED);
795
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400796 host = SC->device->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 ha = (ips_ha_t *) SC->device->host->hostdata;
798
799 if (!ha)
800 return (FAILED);
801
802 if (!ha->active)
803 return (FAILED);
804
Adrian Bunkc6a6c812007-05-23 14:41:46 -0700805 spin_lock(host->host_lock);
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* See if the command is on the copp queue */
808 item = ha->copp_waitlist.head;
809 while ((item) && (item->scsi_cmd != SC))
810 item = item->next;
811
812 if (item) {
813 /* Found it */
814 ips_removeq_copp(&ha->copp_waitlist, item);
815 ret = (SUCCESS);
816
817 /* See if the command is on the wait queue */
818 } else if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
819 /* command not sent yet */
820 ret = (SUCCESS);
821 } else {
822 /* command must have already been sent */
823 ret = (FAILED);
824 }
Jeff Garzik 8fa728a2005-05-28 07:54:40 -0400825
Adrian Bunkc6a6c812007-05-23 14:41:46 -0700826 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return ret;
828}
829
830/****************************************************************************/
831/* */
832/* Routine Name: ips_eh_reset */
833/* */
834/* Routine Description: */
835/* */
836/* Reset the controller (with new eh error code) */
837/* */
838/* NOTE: this routine is called under the io_request_lock spinlock */
839/* */
840/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +0200841static int __ips_eh_reset(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842{
843 int ret;
844 int i;
845 ips_ha_t *ha;
846 ips_scb_t *scb;
847 ips_copp_wait_item_t *item;
848
849 METHOD_TRACE("ips_eh_reset", 1);
850
851#ifdef NO_IPS_RESET
852 return (FAILED);
853#else
854
855 if (!SC) {
856 DEBUG(1, "Reset called with NULL scsi command");
857
858 return (FAILED);
859 }
860
861 ha = (ips_ha_t *) SC->device->host->hostdata;
862
863 if (!ha) {
864 DEBUG(1, "Reset called with NULL ha struct");
865
866 return (FAILED);
867 }
868
869 if (!ha->active)
870 return (FAILED);
871
872 /* See if the command is on the copp queue */
873 item = ha->copp_waitlist.head;
874 while ((item) && (item->scsi_cmd != SC))
875 item = item->next;
876
877 if (item) {
878 /* Found it */
879 ips_removeq_copp(&ha->copp_waitlist, item);
880 return (SUCCESS);
881 }
882
883 /* See if the command is on the wait queue */
884 if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
885 /* command not sent yet */
886 return (SUCCESS);
887 }
888
889 /* An explanation for the casual observer: */
890 /* Part of the function of a RAID controller is automatic error */
891 /* detection and recovery. As such, the only problem that physically */
892 /* resetting an adapter will ever fix is when, for some reason, */
893 /* the driver is not successfully communicating with the adapter. */
894 /* Therefore, we will attempt to flush this adapter. If that succeeds, */
895 /* then there's no real purpose in a physical reset. This will complete */
896 /* much faster and avoids any problems that might be caused by a */
897 /* physical reset ( such as having to fail all the outstanding I/O's ). */
898
899 if (ha->ioctl_reset == 0) { /* IF Not an IOCTL Requested Reset */
900 scb = &ha->scbs[ha->max_cmds - 1];
901
902 ips_init_scb(ha, scb);
903
904 scb->timeout = ips_cmd_timeout;
905 scb->cdb[0] = IPS_CMD_FLUSH;
906
907 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
908 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
909 scb->cmd.flush_cache.state = IPS_NORM_STATE;
910 scb->cmd.flush_cache.reserved = 0;
911 scb->cmd.flush_cache.reserved2 = 0;
912 scb->cmd.flush_cache.reserved3 = 0;
913 scb->cmd.flush_cache.reserved4 = 0;
914
915 /* Attempt the flush command */
916 ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL);
917 if (ret == IPS_SUCCESS) {
918 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
919 "Reset Request - Flushed Cache\n");
920 return (SUCCESS);
921 }
922 }
923
924 /* Either we can't communicate with the adapter or it's an IOCTL request */
925 /* from a utility. A physical reset is needed at this point. */
926
927 ha->ioctl_reset = 0; /* Reset the IOCTL Requested Reset Flag */
928
929 /*
930 * command must have already been sent
931 * reset the controller
932 */
933 IPS_PRINTK(KERN_NOTICE, ha->pcidev, "Resetting controller.\n");
934 ret = (*ha->func.reset) (ha);
935
936 if (!ret) {
Henne1516b552006-10-02 14:56:23 +0200937 struct scsi_cmnd *scsi_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
939 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
940 "Controller reset failed - controller now offline.\n");
941
942 /* Now fail all of the active commands */
943 DEBUG_VAR(1, "(%s%d) Failing active commands",
944 ips_name, ha->host_num);
945
946 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
947 scb->scsi_cmd->result = DID_ERROR << 16;
948 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
949 ips_freescb(ha, scb);
950 }
951
952 /* Now fail all of the pending commands */
953 DEBUG_VAR(1, "(%s%d) Failing pending commands",
954 ips_name, ha->host_num);
955
956 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
957 scsi_cmd->result = DID_ERROR;
958 scsi_cmd->scsi_done(scsi_cmd);
959 }
960
961 ha->active = FALSE;
962 return (FAILED);
963 }
964
965 if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
Henne1516b552006-10-02 14:56:23 +0200966 struct scsi_cmnd *scsi_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968 IPS_PRINTK(KERN_NOTICE, ha->pcidev,
969 "Controller reset failed - controller now offline.\n");
970
971 /* Now fail all of the active commands */
972 DEBUG_VAR(1, "(%s%d) Failing active commands",
973 ips_name, ha->host_num);
974
975 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
976 scb->scsi_cmd->result = DID_ERROR << 16;
977 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
978 ips_freescb(ha, scb);
979 }
980
981 /* Now fail all of the pending commands */
982 DEBUG_VAR(1, "(%s%d) Failing pending commands",
983 ips_name, ha->host_num);
984
985 while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) {
986 scsi_cmd->result = DID_ERROR << 16;
987 scsi_cmd->scsi_done(scsi_cmd);
988 }
989
990 ha->active = FALSE;
991 return (FAILED);
992 }
993
994 /* FFDC */
995 if (le32_to_cpu(ha->subsys->param[3]) & 0x300000) {
996 struct timeval tv;
997
998 do_gettimeofday(&tv);
999 ha->last_ffdc = tv.tv_sec;
1000 ha->reset_count++;
1001 ips_ffdc_reset(ha, IPS_INTR_IORL);
1002 }
1003
1004 /* Now fail all of the active commands */
1005 DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num);
1006
1007 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
1008 scb->scsi_cmd->result =
1009 (DID_RESET << 16) | (SUGGEST_RETRY << 24);
1010 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1011 ips_freescb(ha, scb);
1012 }
1013
1014 /* Reset DCDB active command bits */
1015 for (i = 1; i < ha->nbus; i++)
1016 ha->dcdb_active[i - 1] = 0;
1017
1018 /* Reset the number of active IOCTLs */
1019 ha->num_ioctl = 0;
1020
1021 ips_next(ha, IPS_INTR_IORL);
1022
1023 return (SUCCESS);
1024#endif /* NO_IPS_RESET */
1025
1026}
1027
Henne1516b552006-10-02 14:56:23 +02001028static int ips_eh_reset(struct scsi_cmnd *SC)
Jeff Garzik df0ae242005-05-28 07:57:14 -04001029{
1030 int rc;
1031
1032 spin_lock_irq(SC->device->host->host_lock);
1033 rc = __ips_eh_reset(SC);
1034 spin_unlock_irq(SC->device->host->host_lock);
1035
1036 return rc;
1037}
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039/****************************************************************************/
1040/* */
1041/* Routine Name: ips_queue */
1042/* */
1043/* Routine Description: */
1044/* */
1045/* Send a command to the controller */
1046/* */
1047/* NOTE: */
1048/* Linux obtains io_request_lock before calling this function */
1049/* */
1050/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02001051static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
1053 ips_ha_t *ha;
1054 ips_passthru_t *pt;
1055
1056 METHOD_TRACE("ips_queue", 1);
1057
1058 ha = (ips_ha_t *) SC->device->host->hostdata;
1059
1060 if (!ha)
1061 return (1);
1062
1063 if (!ha->active)
1064 return (DID_ERROR);
1065
1066 if (ips_is_passthru(SC)) {
1067 if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
1068 SC->result = DID_BUS_BUSY << 16;
1069 done(SC);
1070
1071 return (0);
1072 }
1073 } else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
1074 SC->result = DID_BUS_BUSY << 16;
1075 done(SC);
1076
1077 return (0);
1078 }
1079
1080 SC->scsi_done = done;
1081
1082 DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)",
1083 ips_name,
1084 ha->host_num,
1085 SC->cmnd[0],
1086 SC->device->channel, SC->device->id, SC->device->lun);
1087
1088 /* Check for command to initiator IDs */
Jeff Garzik422c0d62005-10-24 18:05:09 -04001089 if ((scmd_channel(SC) > 0)
1090 && (scmd_id(SC) == ha->ha_id[scmd_channel(SC)])) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 SC->result = DID_NO_CONNECT << 16;
1092 done(SC);
1093
1094 return (0);
1095 }
1096
1097 if (ips_is_passthru(SC)) {
1098
1099 ips_copp_wait_item_t *scratch;
1100
1101 /* A Reset IOCTL is only sent by the boot CD in extreme cases. */
1102 /* There can never be any system activity ( network or disk ), but check */
1103 /* anyway just as a good practice. */
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001104 pt = (ips_passthru_t *) scsi_sglist(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
1106 (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
1107 if (ha->scb_activelist.count != 0) {
1108 SC->result = DID_BUS_BUSY << 16;
1109 done(SC);
1110 return (0);
1111 }
1112 ha->ioctl_reset = 1; /* This reset request is from an IOCTL */
Mike Christieba3af0a2006-02-22 02:11:59 -06001113 __ips_eh_reset(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 SC->result = DID_OK << 16;
1115 SC->scsi_done(SC);
1116 return (0);
1117 }
1118
1119 /* allocate space for the scribble */
1120 scratch = kmalloc(sizeof (ips_copp_wait_item_t), GFP_ATOMIC);
1121
1122 if (!scratch) {
1123 SC->result = DID_ERROR << 16;
1124 done(SC);
1125
1126 return (0);
1127 }
1128
1129 scratch->scsi_cmd = SC;
1130 scratch->next = NULL;
1131
1132 ips_putq_copp_tail(&ha->copp_waitlist, scratch);
1133 } else {
1134 ips_putq_wait_tail(&ha->scb_waitlist, SC);
1135 }
1136
1137 ips_next(ha, IPS_INTR_IORL);
1138
1139 return (0);
1140}
1141
1142/****************************************************************************/
1143/* */
1144/* Routine Name: ips_biosparam */
1145/* */
1146/* Routine Description: */
1147/* */
1148/* Set bios geometry for the controller */
1149/* */
1150/****************************************************************************/
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001151static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1152 sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
1154 ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 int heads;
1156 int sectors;
1157 int cylinders;
1158
1159 METHOD_TRACE("ips_biosparam", 1);
1160
1161 if (!ha)
1162 /* ?!?! host adater info invalid */
1163 return (0);
1164
1165 if (!ha->active)
1166 return (0);
1167
1168 if (!ips_read_adapter_status(ha, IPS_INTR_ON))
1169 /* ?!?! Enquiry command failed */
1170 return (0);
1171
1172 if ((capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) {
1173 heads = IPS_NORM_HEADS;
1174 sectors = IPS_NORM_SECTORS;
1175 } else {
1176 heads = IPS_COMP_HEADS;
1177 sectors = IPS_COMP_SECTORS;
1178 }
1179
1180 cylinders = (unsigned long) capacity / (heads * sectors);
1181
1182 DEBUG_VAR(2, "Geometry: heads: %d, sectors: %d, cylinders: %d",
1183 heads, sectors, cylinders);
1184
1185 geom[0] = heads;
1186 geom[1] = sectors;
1187 geom[2] = cylinders;
1188
1189 return (0);
1190}
1191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192/****************************************************************************/
1193/* */
1194/* Routine Name: ips_slave_configure */
1195/* */
1196/* Routine Description: */
1197/* */
1198/* Set queue depths on devices once scan is complete */
1199/* */
1200/****************************************************************************/
1201static int
Christoph Hellwigf64a1812005-10-31 18:32:08 +01001202ips_slave_configure(struct scsi_device * SDptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
1204 ips_ha_t *ha;
1205 int min;
1206
1207 ha = IPS_HA(SDptr->host);
1208 if (SDptr->tagged_supported && SDptr->type == TYPE_DISK) {
1209 min = ha->max_cmds / 2;
1210 if (ha->enq->ucLogDriveCount <= 2)
1211 min = ha->max_cmds - 1;
1212 scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
1213 }
Jack Hammer560c26c2006-01-13 10:06:50 -05001214
1215 SDptr->skip_ms_page_8 = 1;
1216 SDptr->skip_ms_page_3f = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 return 0;
1218}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220/****************************************************************************/
1221/* */
1222/* Routine Name: do_ipsintr */
1223/* */
1224/* Routine Description: */
1225/* */
1226/* Wrapper for the interrupt handler */
1227/* */
1228/****************************************************************************/
1229static irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +01001230do_ipsintr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231{
1232 ips_ha_t *ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 struct Scsi_Host *host;
1234 int irqstatus;
1235
1236 METHOD_TRACE("do_ipsintr", 2);
1237
1238 ha = (ips_ha_t *) dev_id;
1239 if (!ha)
1240 return IRQ_NONE;
1241 host = ips_sh[ha->host_num];
1242 /* interrupt during initialization */
1243 if (!host) {
1244 (*ha->func.intr) (ha);
1245 return IRQ_HANDLED;
1246 }
1247
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001248 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250 if (!ha->active) {
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001251 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 return IRQ_HANDLED;
1253 }
1254
1255 irqstatus = (*ha->func.intr) (ha);
1256
Adrian Bunkc6a6c812007-05-23 14:41:46 -07001257 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 /* start the next command */
1260 ips_next(ha, IPS_INTR_ON);
1261 return IRQ_RETVAL(irqstatus);
1262}
1263
1264/****************************************************************************/
1265/* */
1266/* Routine Name: ips_intr_copperhead */
1267/* */
1268/* Routine Description: */
1269/* */
1270/* Polling interrupt handler */
1271/* */
1272/* ASSUMES interrupts are disabled */
1273/* */
1274/****************************************************************************/
1275int
1276ips_intr_copperhead(ips_ha_t * ha)
1277{
1278 ips_stat_t *sp;
1279 ips_scb_t *scb;
1280 IPS_STATUS cstatus;
1281 int intrstatus;
1282
1283 METHOD_TRACE("ips_intr", 2);
1284
1285 if (!ha)
1286 return 0;
1287
1288 if (!ha->active)
1289 return 0;
1290
1291 intrstatus = (*ha->func.isintr) (ha);
1292
1293 if (!intrstatus) {
1294 /*
1295 * Unexpected/Shared interrupt
1296 */
1297
1298 return 0;
1299 }
1300
1301 while (TRUE) {
1302 sp = &ha->sp;
1303
1304 intrstatus = (*ha->func.isintr) (ha);
1305
1306 if (!intrstatus)
1307 break;
1308 else
1309 cstatus.value = (*ha->func.statupd) (ha);
1310
1311 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1312 /* Spurious Interupt ? */
1313 continue;
1314 }
1315
1316 ips_chkstatus(ha, &cstatus);
1317 scb = (ips_scb_t *) sp->scb_addr;
1318
1319 /*
1320 * use the callback function to finish things up
1321 * NOTE: interrupts are OFF for this
1322 */
1323 (*scb->callback) (ha, scb);
1324 } /* end while */
1325 return 1;
1326}
1327
1328/****************************************************************************/
1329/* */
1330/* Routine Name: ips_intr_morpheus */
1331/* */
1332/* Routine Description: */
1333/* */
1334/* Polling interrupt handler */
1335/* */
1336/* ASSUMES interrupts are disabled */
1337/* */
1338/****************************************************************************/
1339int
1340ips_intr_morpheus(ips_ha_t * ha)
1341{
1342 ips_stat_t *sp;
1343 ips_scb_t *scb;
1344 IPS_STATUS cstatus;
1345 int intrstatus;
1346
1347 METHOD_TRACE("ips_intr_morpheus", 2);
1348
1349 if (!ha)
1350 return 0;
1351
1352 if (!ha->active)
1353 return 0;
1354
1355 intrstatus = (*ha->func.isintr) (ha);
1356
1357 if (!intrstatus) {
1358 /*
1359 * Unexpected/Shared interrupt
1360 */
1361
1362 return 0;
1363 }
1364
1365 while (TRUE) {
1366 sp = &ha->sp;
1367
1368 intrstatus = (*ha->func.isintr) (ha);
1369
1370 if (!intrstatus)
1371 break;
1372 else
1373 cstatus.value = (*ha->func.statupd) (ha);
1374
1375 if (cstatus.value == 0xffffffff)
1376 /* No more to process */
1377 break;
1378
1379 if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
1380 IPS_PRINTK(KERN_WARNING, ha->pcidev,
1381 "Spurious interrupt; no ccb.\n");
1382
1383 continue;
1384 }
1385
1386 ips_chkstatus(ha, &cstatus);
1387 scb = (ips_scb_t *) sp->scb_addr;
1388
1389 /*
1390 * use the callback function to finish things up
1391 * NOTE: interrupts are OFF for this
1392 */
1393 (*scb->callback) (ha, scb);
1394 } /* end while */
1395 return 1;
1396}
1397
1398/****************************************************************************/
1399/* */
1400/* Routine Name: ips_info */
1401/* */
1402/* Routine Description: */
1403/* */
1404/* Return info about the driver */
1405/* */
1406/****************************************************************************/
1407static const char *
1408ips_info(struct Scsi_Host *SH)
1409{
1410 static char buffer[256];
1411 char *bp;
1412 ips_ha_t *ha;
1413
1414 METHOD_TRACE("ips_info", 1);
1415
1416 ha = IPS_HA(SH);
1417
1418 if (!ha)
1419 return (NULL);
1420
1421 bp = &buffer[0];
1422 memset(bp, 0, sizeof (buffer));
1423
1424 sprintf(bp, "%s%s%s Build %d", "IBM PCI ServeRAID ",
1425 IPS_VERSION_HIGH, IPS_VERSION_LOW, IPS_BUILD_IDENT);
1426
1427 if (ha->ad_type > 0 && ha->ad_type <= MAX_ADAPTER_NAME) {
1428 strcat(bp, " <");
1429 strcat(bp, ips_adapter_name[ha->ad_type - 1]);
1430 strcat(bp, ">");
1431 }
1432
1433 return (bp);
1434}
1435
1436/****************************************************************************/
1437/* */
1438/* Routine Name: ips_proc_info */
1439/* */
1440/* Routine Description: */
1441/* */
1442/* The passthru interface for the driver */
1443/* */
1444/****************************************************************************/
1445static int
1446ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1447 int length, int func)
1448{
1449 int i;
1450 int ret;
1451 ips_ha_t *ha = NULL;
1452
1453 METHOD_TRACE("ips_proc_info", 1);
1454
1455 /* Find our host structure */
1456 for (i = 0; i < ips_next_controller; i++) {
1457 if (ips_sh[i]) {
1458 if (ips_sh[i] == host) {
1459 ha = (ips_ha_t *) ips_sh[i]->hostdata;
1460 break;
1461 }
1462 }
1463 }
1464
1465 if (!ha)
1466 return (-EINVAL);
1467
1468 if (func) {
1469 /* write */
1470 return (0);
1471 } else {
1472 /* read */
1473 if (start)
1474 *start = buffer;
1475
1476 ret = ips_host_info(ha, buffer, offset, length);
1477
1478 return (ret);
1479 }
1480}
1481
1482/*--------------------------------------------------------------------------*/
1483/* Helper Functions */
1484/*--------------------------------------------------------------------------*/
1485
1486/****************************************************************************/
1487/* */
1488/* Routine Name: ips_is_passthru */
1489/* */
1490/* Routine Description: */
1491/* */
1492/* Determine if the specified SCSI command is really a passthru command */
1493/* */
1494/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02001495static int ips_is_passthru(struct scsi_cmnd *SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496{
Jack Hammera3632fa2005-10-25 14:13:03 -04001497 unsigned long flags;
1498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 METHOD_TRACE("ips_is_passthru", 1);
1500
1501 if (!SC)
1502 return (0);
1503
1504 if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
1505 (SC->device->channel == 0) &&
1506 (SC->device->id == IPS_ADAPTER_ID) &&
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001507 (SC->device->lun == 0) && scsi_sglist(SC)) {
1508 struct scatterlist *sg = scsi_sglist(SC);
1509 char *buffer;
Jack Hammera3632fa2005-10-25 14:13:03 -04001510
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001511 /* kmap_atomic() ensures addressability of the user buffer.*/
1512 /* local_irq_save() protects the KM_IRQ0 address slot. */
1513 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02001514 buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001515 if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
1516 buffer[2] == 'P' && buffer[3] == 'P') {
1517 kunmap_atomic(buffer - sg->offset, KM_IRQ0);
1518 local_irq_restore(flags);
1519 return 1;
1520 }
1521 kunmap_atomic(buffer - sg->offset, KM_IRQ0);
1522 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 }
1524 return 0;
1525}
1526
1527/****************************************************************************/
1528/* */
1529/* Routine Name: ips_alloc_passthru_buffer */
1530/* */
1531/* Routine Description: */
1532/* allocate a buffer large enough for the ioctl data if the ioctl buffer */
1533/* is too small or doesn't exist */
1534/****************************************************************************/
1535static int
1536ips_alloc_passthru_buffer(ips_ha_t * ha, int length)
1537{
1538 void *bigger_buf;
1539 dma_addr_t dma_busaddr;
1540
1541 if (ha->ioctl_data && length <= ha->ioctl_len)
1542 return 0;
1543 /* there is no buffer or it's not big enough, allocate a new one */
1544 bigger_buf = pci_alloc_consistent(ha->pcidev, length, &dma_busaddr);
1545 if (bigger_buf) {
1546 /* free the old memory */
1547 pci_free_consistent(ha->pcidev, ha->ioctl_len, ha->ioctl_data,
1548 ha->ioctl_busaddr);
1549 /* use the new memory */
1550 ha->ioctl_data = (char *) bigger_buf;
1551 ha->ioctl_len = length;
1552 ha->ioctl_busaddr = dma_busaddr;
1553 } else {
1554 return -1;
1555 }
1556 return 0;
1557}
1558
1559/****************************************************************************/
1560/* */
1561/* Routine Name: ips_make_passthru */
1562/* */
1563/* Routine Description: */
1564/* */
1565/* Make a passthru command out of the info in the Scsi block */
1566/* */
1567/****************************************************************************/
1568static int
Henne1516b552006-10-02 14:56:23 +02001569ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570{
1571 ips_passthru_t *pt;
1572 int length = 0;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001573 int i, ret;
1574 struct scatterlist *sg = scsi_sglist(SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576 METHOD_TRACE("ips_make_passthru", 1);
1577
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09001578 scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
1579 length += sg[i].length;
1580
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 if (length < sizeof (ips_passthru_t)) {
1582 /* wrong size */
1583 DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
1584 ips_name, ha->host_num);
1585 return (IPS_FAILURE);
1586 }
1587 if (ips_alloc_passthru_buffer(ha, length)) {
1588 /* allocation failure! If ha->ioctl_data exists, use it to return
1589 some error codes. Return a failed command to the scsi layer. */
1590 if (ha->ioctl_data) {
1591 pt = (ips_passthru_t *) ha->ioctl_data;
1592 ips_scmd_buf_read(SC, pt, sizeof (ips_passthru_t));
1593 pt->BasicStatus = 0x0B;
1594 pt->ExtendedStatus = 0x00;
1595 ips_scmd_buf_write(SC, pt, sizeof (ips_passthru_t));
1596 }
1597 return IPS_FAILURE;
1598 }
1599 ha->ioctl_datasize = length;
1600
1601 ips_scmd_buf_read(SC, ha->ioctl_data, ha->ioctl_datasize);
1602 pt = (ips_passthru_t *) ha->ioctl_data;
1603
1604 /*
1605 * Some notes about the passthru interface used
1606 *
1607 * IF the scsi op_code == 0x0d then we assume
1608 * that the data came along with/goes with the
1609 * packet we received from the sg driver. In this
1610 * case the CmdBSize field of the pt structure is
1611 * used for the size of the buffer.
1612 */
1613
1614 switch (pt->CoppCmd) {
1615 case IPS_NUMCTRLS:
1616 memcpy(ha->ioctl_data + sizeof (ips_passthru_t),
1617 &ips_num_controllers, sizeof (int));
1618 ips_scmd_buf_write(SC, ha->ioctl_data,
1619 sizeof (ips_passthru_t) + sizeof (int));
1620 SC->result = DID_OK << 16;
1621
1622 return (IPS_SUCCESS_IMM);
1623
1624 case IPS_COPPUSRCMD:
1625 case IPS_COPPIOCCMD:
1626 if (SC->cmnd[0] == IPS_IOCTL_COMMAND) {
1627 if (length < (sizeof (ips_passthru_t) + pt->CmdBSize)) {
1628 /* wrong size */
1629 DEBUG_VAR(1,
1630 "(%s%d) Passthru structure wrong size",
1631 ips_name, ha->host_num);
1632
1633 return (IPS_FAILURE);
1634 }
1635
Jeff Garzik8a694cc2007-12-13 16:14:07 -08001636 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 pt->CoppCP.cmd.flashfw.op_code ==
1638 IPS_CMD_RW_BIOSFW) {
1639 ret = ips_flash_copperhead(ha, pt, scb);
1640 ips_scmd_buf_write(SC, ha->ioctl_data,
1641 sizeof (ips_passthru_t));
1642 return ret;
1643 }
1644 if (ips_usrcmd(ha, pt, scb))
1645 return (IPS_SUCCESS);
1646 else
1647 return (IPS_FAILURE);
1648 }
1649
1650 break;
1651
1652 } /* end switch */
1653
1654 return (IPS_FAILURE);
1655}
1656
1657/****************************************************************************/
1658/* Routine Name: ips_flash_copperhead */
1659/* Routine Description: */
1660/* Flash the BIOS/FW on a Copperhead style controller */
1661/****************************************************************************/
1662static int
1663ips_flash_copperhead(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1664{
1665 int datasize;
1666
1667 /* Trombone is the only copperhead that can do packet flash, but only
1668 * for firmware. No one said it had to make sence. */
1669 if (IPS_IS_TROMBONE(ha) && pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE) {
1670 if (ips_usrcmd(ha, pt, scb))
1671 return IPS_SUCCESS;
1672 else
1673 return IPS_FAILURE;
1674 }
1675 pt->BasicStatus = 0x0B;
1676 pt->ExtendedStatus = 0;
1677 scb->scsi_cmd->result = DID_OK << 16;
1678 /* IF it's OK to Use the "CD BOOT" Flash Buffer, then you can */
1679 /* avoid allocating a huge buffer per adapter ( which can fail ). */
1680 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1681 pt->CoppCP.cmd.flashfw.direction == IPS_ERASE_BIOS) {
1682 pt->BasicStatus = 0;
1683 return ips_flash_bios(ha, pt, scb);
1684 } else if (pt->CoppCP.cmd.flashfw.packet_num == 0) {
1685 if (ips_FlashData && !test_and_set_bit(0, &ips_FlashDataInUse)){
1686 ha->flash_data = ips_FlashData;
1687 ha->flash_busaddr = ips_flashbusaddr;
1688 ha->flash_len = PAGE_SIZE << 7;
1689 ha->flash_datasize = 0;
1690 } else if (!ha->flash_data) {
1691 datasize = pt->CoppCP.cmd.flashfw.total_packets *
1692 pt->CoppCP.cmd.flashfw.count;
1693 ha->flash_data = pci_alloc_consistent(ha->pcidev,
1694 datasize,
1695 &ha->flash_busaddr);
1696 if (!ha->flash_data){
1697 printk(KERN_WARNING "Unable to allocate a flash buffer\n");
1698 return IPS_FAILURE;
1699 }
1700 ha->flash_datasize = 0;
1701 ha->flash_len = datasize;
1702 } else
1703 return IPS_FAILURE;
1704 } else {
1705 if (pt->CoppCP.cmd.flashfw.count + ha->flash_datasize >
1706 ha->flash_len) {
1707 ips_free_flash_copperhead(ha);
1708 IPS_PRINTK(KERN_WARNING, ha->pcidev,
1709 "failed size sanity check\n");
1710 return IPS_FAILURE;
1711 }
1712 }
1713 if (!ha->flash_data)
1714 return IPS_FAILURE;
1715 pt->BasicStatus = 0;
1716 memcpy(&ha->flash_data[ha->flash_datasize], pt + 1,
1717 pt->CoppCP.cmd.flashfw.count);
1718 ha->flash_datasize += pt->CoppCP.cmd.flashfw.count;
1719 if (pt->CoppCP.cmd.flashfw.packet_num ==
1720 pt->CoppCP.cmd.flashfw.total_packets - 1) {
1721 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE)
1722 return ips_flash_bios(ha, pt, scb);
1723 else if (pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE)
1724 return ips_flash_firmware(ha, pt, scb);
1725 }
1726 return IPS_SUCCESS_IMM;
1727}
1728
1729/****************************************************************************/
1730/* Routine Name: ips_flash_bios */
1731/* Routine Description: */
1732/* flashes the bios of a copperhead adapter */
1733/****************************************************************************/
1734static int
1735ips_flash_bios(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1736{
1737
1738 if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1739 pt->CoppCP.cmd.flashfw.direction == IPS_WRITE_BIOS) {
1740 if ((!ha->func.programbios) || (!ha->func.erasebios) ||
1741 (!ha->func.verifybios))
1742 goto error;
1743 if ((*ha->func.erasebios) (ha)) {
1744 DEBUG_VAR(1,
1745 "(%s%d) flash bios failed - unable to erase flash",
1746 ips_name, ha->host_num);
1747 goto error;
1748 } else
1749 if ((*ha->func.programbios) (ha,
1750 ha->flash_data +
1751 IPS_BIOS_HEADER,
1752 ha->flash_datasize -
1753 IPS_BIOS_HEADER, 0)) {
1754 DEBUG_VAR(1,
1755 "(%s%d) flash bios failed - unable to flash",
1756 ips_name, ha->host_num);
1757 goto error;
1758 } else
1759 if ((*ha->func.verifybios) (ha,
1760 ha->flash_data +
1761 IPS_BIOS_HEADER,
1762 ha->flash_datasize -
1763 IPS_BIOS_HEADER, 0)) {
1764 DEBUG_VAR(1,
1765 "(%s%d) flash bios failed - unable to verify flash",
1766 ips_name, ha->host_num);
1767 goto error;
1768 }
1769 ips_free_flash_copperhead(ha);
1770 return IPS_SUCCESS_IMM;
1771 } else if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
1772 pt->CoppCP.cmd.flashfw.direction == IPS_ERASE_BIOS) {
1773 if (!ha->func.erasebios)
1774 goto error;
1775 if ((*ha->func.erasebios) (ha)) {
1776 DEBUG_VAR(1,
1777 "(%s%d) flash bios failed - unable to erase flash",
1778 ips_name, ha->host_num);
1779 goto error;
1780 }
1781 return IPS_SUCCESS_IMM;
1782 }
1783 error:
1784 pt->BasicStatus = 0x0B;
1785 pt->ExtendedStatus = 0x00;
1786 ips_free_flash_copperhead(ha);
1787 return IPS_FAILURE;
1788}
1789
1790/****************************************************************************/
1791/* */
1792/* Routine Name: ips_fill_scb_sg_single */
1793/* */
1794/* Routine Description: */
1795/* Fill in a single scb sg_list element from an address */
1796/* return a -1 if a breakup occurred */
1797/****************************************************************************/
1798static int
1799ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
1800 ips_scb_t * scb, int indx, unsigned int e_len)
1801{
1802
1803 int ret_val = 0;
1804
1805 if ((scb->data_len + e_len) > ha->max_xfer) {
1806 e_len = ha->max_xfer - scb->data_len;
1807 scb->breakup = indx;
1808 ++scb->sg_break;
1809 ret_val = -1;
1810 } else {
1811 scb->breakup = 0;
1812 scb->sg_break = 0;
1813 }
1814 if (IPS_USE_ENH_SGLIST(ha)) {
1815 scb->sg_list.enh_list[indx].address_lo =
1816 cpu_to_le32(pci_dma_lo32(busaddr));
1817 scb->sg_list.enh_list[indx].address_hi =
1818 cpu_to_le32(pci_dma_hi32(busaddr));
1819 scb->sg_list.enh_list[indx].length = cpu_to_le32(e_len);
1820 } else {
1821 scb->sg_list.std_list[indx].address =
1822 cpu_to_le32(pci_dma_lo32(busaddr));
1823 scb->sg_list.std_list[indx].length = cpu_to_le32(e_len);
1824 }
1825
1826 ++scb->sg_len;
1827 scb->data_len += e_len;
1828 return ret_val;
1829}
1830
1831/****************************************************************************/
1832/* Routine Name: ips_flash_firmware */
1833/* Routine Description: */
1834/* flashes the firmware of a copperhead adapter */
1835/****************************************************************************/
1836static int
1837ips_flash_firmware(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1838{
1839 IPS_SG_LIST sg_list;
1840 uint32_t cmd_busaddr;
1841
1842 if (pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE &&
1843 pt->CoppCP.cmd.flashfw.direction == IPS_WRITE_FW) {
1844 memset(&pt->CoppCP.cmd, 0, sizeof (IPS_HOST_COMMAND));
1845 pt->CoppCP.cmd.flashfw.op_code = IPS_CMD_DOWNLOAD;
1846 pt->CoppCP.cmd.flashfw.count = cpu_to_le32(ha->flash_datasize);
1847 } else {
1848 pt->BasicStatus = 0x0B;
1849 pt->ExtendedStatus = 0x00;
1850 ips_free_flash_copperhead(ha);
1851 return IPS_FAILURE;
1852 }
1853 /* Save the S/G list pointer so it doesn't get clobbered */
1854 sg_list.list = scb->sg_list.list;
1855 cmd_busaddr = scb->scb_busaddr;
1856 /* copy in the CP */
1857 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof (IPS_IOCTL_CMD));
1858 /* FIX stuff that might be wrong */
1859 scb->sg_list.list = sg_list.list;
1860 scb->scb_busaddr = cmd_busaddr;
1861 scb->bus = scb->scsi_cmd->device->channel;
1862 scb->target_id = scb->scsi_cmd->device->id;
1863 scb->lun = scb->scsi_cmd->device->lun;
1864 scb->sg_len = 0;
1865 scb->data_len = 0;
1866 scb->flags = 0;
1867 scb->op_code = 0;
1868 scb->callback = ipsintr_done;
1869 scb->timeout = ips_cmd_timeout;
1870
1871 scb->data_len = ha->flash_datasize;
1872 scb->data_busaddr =
1873 pci_map_single(ha->pcidev, ha->flash_data, scb->data_len,
1874 IPS_DMA_DIR(scb));
1875 scb->flags |= IPS_SCB_MAP_SINGLE;
1876 scb->cmd.flashfw.command_id = IPS_COMMAND_ID(ha, scb);
1877 scb->cmd.flashfw.buffer_addr = cpu_to_le32(scb->data_busaddr);
1878 if (pt->TimeOut)
1879 scb->timeout = pt->TimeOut;
1880 scb->scsi_cmd->result = DID_OK << 16;
1881 return IPS_SUCCESS;
1882}
1883
1884/****************************************************************************/
1885/* Routine Name: ips_free_flash_copperhead */
1886/* Routine Description: */
1887/* release the memory resources used to hold the flash image */
1888/****************************************************************************/
1889static void
1890ips_free_flash_copperhead(ips_ha_t * ha)
1891{
1892 if (ha->flash_data == ips_FlashData)
1893 test_and_clear_bit(0, &ips_FlashDataInUse);
1894 else if (ha->flash_data)
1895 pci_free_consistent(ha->pcidev, ha->flash_len, ha->flash_data,
1896 ha->flash_busaddr);
1897 ha->flash_data = NULL;
1898}
1899
1900/****************************************************************************/
1901/* */
1902/* Routine Name: ips_usrcmd */
1903/* */
1904/* Routine Description: */
1905/* */
1906/* Process a user command and make it ready to send */
1907/* */
1908/****************************************************************************/
1909static int
1910ips_usrcmd(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
1911{
1912 IPS_SG_LIST sg_list;
1913 uint32_t cmd_busaddr;
1914
1915 METHOD_TRACE("ips_usrcmd", 1);
1916
1917 if ((!scb) || (!pt) || (!ha))
1918 return (0);
1919
1920 /* Save the S/G list pointer so it doesn't get clobbered */
1921 sg_list.list = scb->sg_list.list;
1922 cmd_busaddr = scb->scb_busaddr;
1923 /* copy in the CP */
1924 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof (IPS_IOCTL_CMD));
1925 memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof (IPS_DCDB_TABLE));
1926
1927 /* FIX stuff that might be wrong */
1928 scb->sg_list.list = sg_list.list;
1929 scb->scb_busaddr = cmd_busaddr;
1930 scb->bus = scb->scsi_cmd->device->channel;
1931 scb->target_id = scb->scsi_cmd->device->id;
1932 scb->lun = scb->scsi_cmd->device->lun;
1933 scb->sg_len = 0;
1934 scb->data_len = 0;
1935 scb->flags = 0;
1936 scb->op_code = 0;
1937 scb->callback = ipsintr_done;
1938 scb->timeout = ips_cmd_timeout;
1939 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
1940
1941 /* we don't support DCDB/READ/WRITE Scatter Gather */
1942 if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) ||
1943 (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) ||
1944 (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG))
1945 return (0);
1946
1947 if (pt->CmdBSize) {
1948 scb->data_len = pt->CmdBSize;
1949 scb->data_busaddr = ha->ioctl_busaddr + sizeof (ips_passthru_t);
1950 } else {
1951 scb->data_busaddr = 0L;
1952 }
1953
1954 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
1955 scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr +
1956 (unsigned long) &scb->
1957 dcdb -
1958 (unsigned long) scb);
1959
1960 if (pt->CmdBSize) {
1961 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB)
1962 scb->dcdb.buffer_pointer =
1963 cpu_to_le32(scb->data_busaddr);
1964 else
1965 scb->cmd.basic_io.sg_addr =
1966 cpu_to_le32(scb->data_busaddr);
1967 }
1968
1969 /* set timeouts */
1970 if (pt->TimeOut) {
1971 scb->timeout = pt->TimeOut;
1972
1973 if (pt->TimeOut <= 10)
1974 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10;
1975 else if (pt->TimeOut <= 60)
1976 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60;
1977 else
1978 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M;
1979 }
1980
1981 /* assume success */
1982 scb->scsi_cmd->result = DID_OK << 16;
1983
1984 /* success */
1985 return (1);
1986}
1987
1988/****************************************************************************/
1989/* */
1990/* Routine Name: ips_cleanup_passthru */
1991/* */
1992/* Routine Description: */
1993/* */
1994/* Cleanup after a passthru command */
1995/* */
1996/****************************************************************************/
1997static void
1998ips_cleanup_passthru(ips_ha_t * ha, ips_scb_t * scb)
1999{
2000 ips_passthru_t *pt;
2001
2002 METHOD_TRACE("ips_cleanup_passthru", 1);
2003
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002004 if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
2006 ips_name, ha->host_num);
2007
2008 return;
2009 }
2010 pt = (ips_passthru_t *) ha->ioctl_data;
2011
2012 /* Copy data back to the user */
2013 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) /* Copy DCDB Back to Caller's Area */
2014 memcpy(&pt->CoppCP.dcdb, &scb->dcdb, sizeof (IPS_DCDB_TABLE));
2015
2016 pt->BasicStatus = scb->basic_status;
2017 pt->ExtendedStatus = scb->extended_status;
2018 pt->AdapterType = ha->ad_type;
2019
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002020 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 (scb->cmd.flashfw.op_code == IPS_CMD_DOWNLOAD ||
2022 scb->cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW))
2023 ips_free_flash_copperhead(ha);
2024
2025 ips_scmd_buf_write(scb->scsi_cmd, ha->ioctl_data, ha->ioctl_datasize);
2026}
2027
2028/****************************************************************************/
2029/* */
2030/* Routine Name: ips_host_info */
2031/* */
2032/* Routine Description: */
2033/* */
2034/* The passthru interface for the driver */
2035/* */
2036/****************************************************************************/
2037static int
2038ips_host_info(ips_ha_t * ha, char *ptr, off_t offset, int len)
2039{
2040 IPS_INFOSTR info;
2041
2042 METHOD_TRACE("ips_host_info", 1);
2043
2044 info.buffer = ptr;
2045 info.length = len;
2046 info.offset = offset;
2047 info.pos = 0;
2048 info.localpos = 0;
2049
2050 copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
2051
2052 if ((le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) &&
2053 (le16_to_cpu(ha->nvram->adapter_type) != 0))
2054 copy_info(&info, "\tController Type : %s\n",
2055 ips_adapter_name[ha->ad_type - 1]);
2056 else
2057 copy_info(&info,
2058 "\tController Type : Unknown\n");
2059
2060 if (ha->io_addr)
2061 copy_info(&info,
2062 "\tIO region : 0x%lx (%d bytes)\n",
2063 ha->io_addr, ha->io_len);
2064
2065 if (ha->mem_addr) {
2066 copy_info(&info,
2067 "\tMemory region : 0x%lx (%d bytes)\n",
2068 ha->mem_addr, ha->mem_len);
2069 copy_info(&info,
2070 "\tShared memory address : 0x%lx\n",
2071 ha->mem_ptr);
2072 }
2073
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002074 copy_info(&info, "\tIRQ number : %d\n", ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
2076 /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
2077 /* That keeps everything happy for "text" operations on the proc file. */
2078
2079 if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08002080 if (ha->nvram->bios_low[3] == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 copy_info(&info,
2082 "\tBIOS Version : %c%c%c%c%c%c%c\n",
2083 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
2084 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
2085 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
2086 ha->nvram->bios_low[2]);
2087
2088 } else {
2089 copy_info(&info,
2090 "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
2091 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
2092 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
2093 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
2094 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
2095 }
2096
2097 }
2098
2099 if (ha->enq->CodeBlkVersion[7] == 0) {
2100 copy_info(&info,
2101 "\tFirmware Version : %c%c%c%c%c%c%c\n",
2102 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
2103 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
2104 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
2105 ha->enq->CodeBlkVersion[6]);
2106 } else {
2107 copy_info(&info,
2108 "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
2109 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
2110 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
2111 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
2112 ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
2113 }
2114
2115 if (ha->enq->BootBlkVersion[7] == 0) {
2116 copy_info(&info,
2117 "\tBoot Block Version : %c%c%c%c%c%c%c\n",
2118 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
2119 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
2120 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
2121 ha->enq->BootBlkVersion[6]);
2122 } else {
2123 copy_info(&info,
2124 "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
2125 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
2126 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
2127 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
2128 ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
2129 }
2130
2131 copy_info(&info, "\tDriver Version : %s%s\n",
2132 IPS_VERSION_HIGH, IPS_VERSION_LOW);
2133
2134 copy_info(&info, "\tDriver Build : %d\n",
2135 IPS_BUILD_IDENT);
2136
2137 copy_info(&info, "\tMax Physical Devices : %d\n",
2138 ha->enq->ucMaxPhysicalDevices);
2139 copy_info(&info, "\tMax Active Commands : %d\n",
2140 ha->max_cmds);
2141 copy_info(&info, "\tCurrent Queued Commands : %d\n",
2142 ha->scb_waitlist.count);
2143 copy_info(&info, "\tCurrent Active Commands : %d\n",
2144 ha->scb_activelist.count - ha->num_ioctl);
2145 copy_info(&info, "\tCurrent Queued PT Commands : %d\n",
2146 ha->copp_waitlist.count);
2147 copy_info(&info, "\tCurrent Active PT Commands : %d\n",
2148 ha->num_ioctl);
2149
2150 copy_info(&info, "\n");
2151
2152 return (info.localpos);
2153}
2154
2155/****************************************************************************/
2156/* */
2157/* Routine Name: copy_mem_info */
2158/* */
2159/* Routine Description: */
2160/* */
2161/* Copy data into an IPS_INFOSTR structure */
2162/* */
2163/****************************************************************************/
2164static void
2165copy_mem_info(IPS_INFOSTR * info, char *data, int len)
2166{
2167 METHOD_TRACE("copy_mem_info", 1);
2168
2169 if (info->pos + len < info->offset) {
2170 info->pos += len;
2171 return;
2172 }
2173
2174 if (info->pos < info->offset) {
2175 data += (info->offset - info->pos);
2176 len -= (info->offset - info->pos);
2177 info->pos += (info->offset - info->pos);
2178 }
2179
2180 if (info->localpos + len > info->length)
2181 len = info->length - info->localpos;
2182
2183 if (len > 0) {
2184 memcpy(info->buffer + info->localpos, data, len);
2185 info->pos += len;
2186 info->localpos += len;
2187 }
2188}
2189
2190/****************************************************************************/
2191/* */
2192/* Routine Name: copy_info */
2193/* */
2194/* Routine Description: */
2195/* */
2196/* printf style wrapper for an info structure */
2197/* */
2198/****************************************************************************/
2199static int
2200copy_info(IPS_INFOSTR * info, char *fmt, ...)
2201{
2202 va_list args;
2203 char buf[128];
2204 int len;
2205
2206 METHOD_TRACE("copy_info", 1);
2207
2208 va_start(args, fmt);
2209 len = vsprintf(buf, fmt, args);
2210 va_end(args);
2211
2212 copy_mem_info(info, buf, len);
2213
2214 return (len);
2215}
2216
2217/****************************************************************************/
2218/* */
2219/* Routine Name: ips_identify_controller */
2220/* */
2221/* Routine Description: */
2222/* */
2223/* Identify this controller */
2224/* */
2225/****************************************************************************/
2226static void
2227ips_identify_controller(ips_ha_t * ha)
2228{
2229 METHOD_TRACE("ips_identify_controller", 1);
2230
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002231 switch (ha->pcidev->device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 case IPS_DEVICEID_COPPERHEAD:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002233 if (ha->pcidev->revision <= IPS_REVID_SERVERAID) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 ha->ad_type = IPS_ADTYPE_SERVERAID;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002235 } else if (ha->pcidev->revision == IPS_REVID_SERVERAID2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 ha->ad_type = IPS_ADTYPE_SERVERAID2;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002237 } else if (ha->pcidev->revision == IPS_REVID_NAVAJO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 ha->ad_type = IPS_ADTYPE_NAVAJO;
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->slot_num == 0)) {
2241 ha->ad_type = IPS_ADTYPE_KIOWA;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002242 } else if ((ha->pcidev->revision >= IPS_REVID_CLARINETP1) &&
2243 (ha->pcidev->revision <= IPS_REVID_CLARINETP3)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 if (ha->enq->ucMaxPhysicalDevices == 15)
2245 ha->ad_type = IPS_ADTYPE_SERVERAID3L;
2246 else
2247 ha->ad_type = IPS_ADTYPE_SERVERAID3;
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002248 } else if ((ha->pcidev->revision >= IPS_REVID_TROMBONE32) &&
2249 (ha->pcidev->revision <= IPS_REVID_TROMBONE64)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 ha->ad_type = IPS_ADTYPE_SERVERAID4H;
2251 }
2252 break;
2253
2254 case IPS_DEVICEID_MORPHEUS:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002255 switch (ha->pcidev->subsystem_device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 case IPS_SUBDEVICEID_4L:
2257 ha->ad_type = IPS_ADTYPE_SERVERAID4L;
2258 break;
2259
2260 case IPS_SUBDEVICEID_4M:
2261 ha->ad_type = IPS_ADTYPE_SERVERAID4M;
2262 break;
2263
2264 case IPS_SUBDEVICEID_4MX:
2265 ha->ad_type = IPS_ADTYPE_SERVERAID4MX;
2266 break;
2267
2268 case IPS_SUBDEVICEID_4LX:
2269 ha->ad_type = IPS_ADTYPE_SERVERAID4LX;
2270 break;
2271
2272 case IPS_SUBDEVICEID_5I2:
2273 ha->ad_type = IPS_ADTYPE_SERVERAID5I2;
2274 break;
2275
2276 case IPS_SUBDEVICEID_5I1:
2277 ha->ad_type = IPS_ADTYPE_SERVERAID5I1;
2278 break;
2279 }
2280
2281 break;
2282
2283 case IPS_DEVICEID_MARCO:
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002284 switch (ha->pcidev->subsystem_device) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 case IPS_SUBDEVICEID_6M:
2286 ha->ad_type = IPS_ADTYPE_SERVERAID6M;
2287 break;
2288 case IPS_SUBDEVICEID_6I:
2289 ha->ad_type = IPS_ADTYPE_SERVERAID6I;
2290 break;
2291 case IPS_SUBDEVICEID_7k:
2292 ha->ad_type = IPS_ADTYPE_SERVERAID7k;
2293 break;
2294 case IPS_SUBDEVICEID_7M:
2295 ha->ad_type = IPS_ADTYPE_SERVERAID7M;
2296 break;
2297 }
2298 break;
2299 }
2300}
2301
2302/****************************************************************************/
2303/* */
2304/* Routine Name: ips_get_bios_version */
2305/* */
2306/* Routine Description: */
2307/* */
2308/* Get the BIOS revision number */
2309/* */
2310/****************************************************************************/
2311static void
2312ips_get_bios_version(ips_ha_t * ha, int intr)
2313{
2314 ips_scb_t *scb;
2315 int ret;
2316 uint8_t major;
2317 uint8_t minor;
2318 uint8_t subminor;
2319 uint8_t *buffer;
2320 char hexDigits[] =
2321 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
2322 'D', 'E', 'F' };
2323
2324 METHOD_TRACE("ips_get_bios_version", 1);
2325
2326 major = 0;
2327 minor = 0;
2328
2329 strncpy(ha->bios_version, " ?", 8);
2330
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002331 if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 if (IPS_USE_MEMIO(ha)) {
2333 /* Memory Mapped I/O */
2334
2335 /* test 1st byte */
2336 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002337 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 udelay(25); /* 25 us */
2339
2340 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
2341 return;
2342
2343 writel(1, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002344 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 udelay(25); /* 25 us */
2346
2347 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
2348 return;
2349
2350 /* Get Major version */
2351 writel(0x1FF, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002352 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 udelay(25); /* 25 us */
2354
2355 major = readb(ha->mem_ptr + IPS_REG_FLDP);
2356
2357 /* Get Minor version */
2358 writel(0x1FE, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002359 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 udelay(25); /* 25 us */
2361 minor = readb(ha->mem_ptr + IPS_REG_FLDP);
2362
2363 /* Get SubMinor version */
2364 writel(0x1FD, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002365 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 udelay(25); /* 25 us */
2367 subminor = readb(ha->mem_ptr + IPS_REG_FLDP);
2368
2369 } else {
2370 /* Programmed I/O */
2371
2372 /* test 1st byte */
2373 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002374 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 udelay(25); /* 25 us */
2376
2377 if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
2378 return;
2379
2380 outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002381 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 udelay(25); /* 25 us */
2383
2384 if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
2385 return;
2386
2387 /* Get Major version */
2388 outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002389 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 udelay(25); /* 25 us */
2391
2392 major = inb(ha->io_addr + IPS_REG_FLDP);
2393
2394 /* Get Minor version */
2395 outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002396 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 udelay(25); /* 25 us */
2398
2399 minor = inb(ha->io_addr + IPS_REG_FLDP);
2400
2401 /* Get SubMinor version */
2402 outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08002403 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 udelay(25); /* 25 us */
2405
2406 subminor = inb(ha->io_addr + IPS_REG_FLDP);
2407
2408 }
2409 } else {
2410 /* Morpheus Family - Send Command to the card */
2411
2412 buffer = ha->ioctl_data;
2413
2414 memset(buffer, 0, 0x1000);
2415
2416 scb = &ha->scbs[ha->max_cmds - 1];
2417
2418 ips_init_scb(ha, scb);
2419
2420 scb->timeout = ips_cmd_timeout;
2421 scb->cdb[0] = IPS_CMD_RW_BIOSFW;
2422
2423 scb->cmd.flashfw.op_code = IPS_CMD_RW_BIOSFW;
2424 scb->cmd.flashfw.command_id = IPS_COMMAND_ID(ha, scb);
2425 scb->cmd.flashfw.type = 1;
2426 scb->cmd.flashfw.direction = 0;
2427 scb->cmd.flashfw.count = cpu_to_le32(0x800);
2428 scb->cmd.flashfw.total_packets = 1;
2429 scb->cmd.flashfw.packet_num = 0;
2430 scb->data_len = 0x1000;
2431 scb->cmd.flashfw.buffer_addr = ha->ioctl_busaddr;
2432
2433 /* issue the command */
2434 if (((ret =
2435 ips_send_wait(ha, scb, ips_cmd_timeout,
2436 intr)) == IPS_FAILURE)
2437 || (ret == IPS_SUCCESS_IMM)
2438 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
2439 /* Error occurred */
2440
2441 return;
2442 }
2443
2444 if ((buffer[0xC0] == 0x55) && (buffer[0xC1] == 0xAA)) {
2445 major = buffer[0x1ff + 0xC0]; /* Offset 0x1ff after the header (0xc0) */
2446 minor = buffer[0x1fe + 0xC0]; /* Offset 0x1fe after the header (0xc0) */
2447 subminor = buffer[0x1fd + 0xC0]; /* Offset 0x1fd after the header (0xc0) */
2448 } else {
2449 return;
2450 }
2451 }
2452
2453 ha->bios_version[0] = hexDigits[(major & 0xF0) >> 4];
2454 ha->bios_version[1] = '.';
2455 ha->bios_version[2] = hexDigits[major & 0x0F];
2456 ha->bios_version[3] = hexDigits[subminor];
2457 ha->bios_version[4] = '.';
2458 ha->bios_version[5] = hexDigits[(minor & 0xF0) >> 4];
2459 ha->bios_version[6] = hexDigits[minor & 0x0F];
2460 ha->bios_version[7] = 0;
2461}
2462
2463/****************************************************************************/
2464/* */
2465/* Routine Name: ips_hainit */
2466/* */
2467/* Routine Description: */
2468/* */
2469/* Initialize the controller */
2470/* */
2471/* NOTE: Assumes to be called from with a lock */
2472/* */
2473/****************************************************************************/
2474static int
2475ips_hainit(ips_ha_t * ha)
2476{
2477 int i;
2478 struct timeval tv;
2479
2480 METHOD_TRACE("ips_hainit", 1);
2481
2482 if (!ha)
2483 return (0);
2484
2485 if (ha->func.statinit)
2486 (*ha->func.statinit) (ha);
2487
2488 if (ha->func.enableint)
2489 (*ha->func.enableint) (ha);
2490
2491 /* Send FFDC */
2492 ha->reset_count = 1;
2493 do_gettimeofday(&tv);
2494 ha->last_ffdc = tv.tv_sec;
2495 ips_ffdc_reset(ha, IPS_INTR_IORL);
2496
2497 if (!ips_read_config(ha, IPS_INTR_IORL)) {
2498 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2499 "unable to read config from controller.\n");
2500
2501 return (0);
2502 }
2503 /* end if */
2504 if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) {
2505 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2506 "unable to read controller status.\n");
2507
2508 return (0);
2509 }
2510
2511 /* Identify this controller */
2512 ips_identify_controller(ha);
2513
2514 if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
2515 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2516 "unable to read subsystem parameters.\n");
2517
2518 return (0);
2519 }
2520
2521 /* write nvram user page 5 */
2522 if (!ips_write_driver_status(ha, IPS_INTR_IORL)) {
2523 IPS_PRINTK(KERN_WARNING, ha->pcidev,
2524 "unable to write driver info to controller.\n");
2525
2526 return (0);
2527 }
2528
2529 /* If there are Logical Drives and a Reset Occurred, then an EraseStripeLock is Needed */
2530 if ((ha->conf->ucLogDriveCount > 0) && (ha->requires_esl == 1))
2531 ips_clear_adapter(ha, IPS_INTR_IORL);
2532
2533 /* set limits on SID, LUN, BUS */
2534 ha->ntargets = IPS_MAX_TARGETS + 1;
2535 ha->nlun = 1;
2536 ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS) + 1;
2537
2538 switch (ha->conf->logical_drive[0].ucStripeSize) {
2539 case 4:
2540 ha->max_xfer = 0x10000;
2541 break;
2542
2543 case 5:
2544 ha->max_xfer = 0x20000;
2545 break;
2546
2547 case 6:
2548 ha->max_xfer = 0x40000;
2549 break;
2550
2551 case 7:
2552 default:
2553 ha->max_xfer = 0x80000;
2554 break;
2555 }
2556
2557 /* setup max concurrent commands */
2558 if (le32_to_cpu(ha->subsys->param[4]) & 0x1) {
2559 /* Use the new method */
2560 ha->max_cmds = ha->enq->ucConcurrentCmdCount;
2561 } else {
2562 /* use the old method */
2563 switch (ha->conf->logical_drive[0].ucStripeSize) {
2564 case 4:
2565 ha->max_cmds = 32;
2566 break;
2567
2568 case 5:
2569 ha->max_cmds = 16;
2570 break;
2571
2572 case 6:
2573 ha->max_cmds = 8;
2574 break;
2575
2576 case 7:
2577 default:
2578 ha->max_cmds = 4;
2579 break;
2580 }
2581 }
2582
2583 /* Limit the Active Commands on a Lite Adapter */
2584 if ((ha->ad_type == IPS_ADTYPE_SERVERAID3L) ||
2585 (ha->ad_type == IPS_ADTYPE_SERVERAID4L) ||
2586 (ha->ad_type == IPS_ADTYPE_SERVERAID4LX)) {
2587 if ((ha->max_cmds > MaxLiteCmds) && (MaxLiteCmds))
2588 ha->max_cmds = MaxLiteCmds;
2589 }
2590
2591 /* set controller IDs */
2592 ha->ha_id[0] = IPS_ADAPTER_ID;
2593 for (i = 1; i < ha->nbus; i++) {
2594 ha->ha_id[i] = ha->conf->init_id[i - 1] & 0x1f;
2595 ha->dcdb_active[i - 1] = 0;
2596 }
2597
2598 return (1);
2599}
2600
2601/****************************************************************************/
2602/* */
2603/* Routine Name: ips_next */
2604/* */
2605/* Routine Description: */
2606/* */
2607/* Take the next command off the queue and send it to the controller */
2608/* */
2609/****************************************************************************/
2610static void
2611ips_next(ips_ha_t * ha, int intr)
2612{
2613 ips_scb_t *scb;
Henne1516b552006-10-02 14:56:23 +02002614 struct scsi_cmnd *SC;
2615 struct scsi_cmnd *p;
2616 struct scsi_cmnd *q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 ips_copp_wait_item_t *item;
2618 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 struct Scsi_Host *host;
2620 METHOD_TRACE("ips_next", 1);
2621
2622 if (!ha)
2623 return;
2624 host = ips_sh[ha->host_num];
2625 /*
2626 * Block access to the queue function so
2627 * this command won't time out
2628 */
2629 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002630 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
2632 if ((ha->subsys->param[3] & 0x300000)
2633 && (ha->scb_activelist.count == 0)) {
2634 struct timeval tv;
2635
2636 do_gettimeofday(&tv);
2637
2638 if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
2639 ha->last_ffdc = tv.tv_sec;
2640 ips_ffdc_time(ha);
2641 }
2642 }
2643
2644 /*
2645 * Send passthru commands
2646 * These have priority over normal I/O
2647 * but shouldn't affect performance too much
2648 * since we limit the number that can be active
2649 * on the card at any one time
2650 */
2651 while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
2652 (ha->copp_waitlist.head) && (scb = ips_getscb(ha))) {
2653
2654 item = ips_removeq_copp_head(&ha->copp_waitlist);
2655 ha->num_ioctl++;
2656 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002657 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 scb->scsi_cmd = item->scsi_cmd;
2659 kfree(item);
2660
2661 ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
2662
2663 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002664 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 switch (ret) {
2666 case IPS_FAILURE:
2667 if (scb->scsi_cmd) {
2668 scb->scsi_cmd->result = DID_ERROR << 16;
2669 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2670 }
2671
2672 ips_freescb(ha, scb);
2673 break;
2674 case IPS_SUCCESS_IMM:
2675 if (scb->scsi_cmd) {
2676 scb->scsi_cmd->result = DID_OK << 16;
2677 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2678 }
2679
2680 ips_freescb(ha, scb);
2681 break;
2682 default:
2683 break;
2684 } /* end case */
2685
2686 if (ret != IPS_SUCCESS) {
2687 ha->num_ioctl--;
2688 continue;
2689 }
2690
2691 ret = ips_send_cmd(ha, scb);
2692
2693 if (ret == IPS_SUCCESS)
2694 ips_putq_scb_head(&ha->scb_activelist, scb);
2695 else
2696 ha->num_ioctl--;
2697
2698 switch (ret) {
2699 case IPS_FAILURE:
2700 if (scb->scsi_cmd) {
2701 scb->scsi_cmd->result = DID_ERROR << 16;
2702 }
2703
2704 ips_freescb(ha, scb);
2705 break;
2706 case IPS_SUCCESS_IMM:
2707 ips_freescb(ha, scb);
2708 break;
2709 default:
2710 break;
2711 } /* end case */
2712
2713 }
2714
2715 /*
2716 * Send "Normal" I/O commands
2717 */
2718
2719 p = ha->scb_waitlist.head;
2720 while ((p) && (scb = ips_getscb(ha))) {
Jeff Garzik422c0d62005-10-24 18:05:09 -04002721 if ((scmd_channel(p) > 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 && (ha->
Jeff Garzik422c0d62005-10-24 18:05:09 -04002723 dcdb_active[scmd_channel(p) -
2724 1] & (1 << scmd_id(p)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 ips_freescb(ha, scb);
Henne1516b552006-10-02 14:56:23 +02002726 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 continue;
2728 }
2729
2730 q = p;
2731 SC = ips_removeq_wait(&ha->scb_waitlist, q);
2732
2733 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002734 spin_unlock(host->host_lock); /* Unlock HA after command is taken off queue */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735
2736 SC->result = DID_OK;
2737 SC->host_scribble = NULL;
2738
2739 memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer));
2740
2741 scb->target_id = SC->device->id;
2742 scb->lun = SC->device->lun;
2743 scb->bus = SC->device->channel;
2744 scb->scsi_cmd = SC;
2745 scb->breakup = 0;
2746 scb->data_len = 0;
2747 scb->callback = ipsintr_done;
2748 scb->timeout = ips_cmd_timeout;
2749 memset(&scb->cmd, 0, 16);
2750
2751 /* copy in the CDB */
2752 memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
2753
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002754 scb->sg_count = scsi_dma_map(SC);
2755 BUG_ON(scb->sg_count < 0);
2756 if (scb->sg_count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 struct scatterlist *sg;
2758 int i;
2759
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 scb->flags |= IPS_SCB_MAP_SG;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002761
2762 scsi_for_each_sg(SC, sg, scb->sg_count, i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 if (ips_fill_scb_sg_single
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002764 (ha, sg_dma_address(sg), scb, i,
2765 sg_dma_len(sg)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 break;
2767 }
2768 scb->dcdb.transfer_length = scb->data_len;
2769 } else {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09002770 scb->data_busaddr = 0L;
2771 scb->sg_len = 0;
2772 scb->data_len = 0;
2773 scb->dcdb.transfer_length = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 }
2775
2776 scb->dcdb.cmd_attribute =
2777 ips_command_direction[scb->scsi_cmd->cmnd[0]];
2778
Jeff Garzik2f277d62007-12-13 16:14:08 -08002779 /* Allow a WRITE BUFFER Command to Have no Data */
2780 /* This is Used by Tape Flash Utilites */
2781 if ((scb->scsi_cmd->cmnd[0] == WRITE_BUFFER) &&
2782 (scb->data_len == 0))
2783 scb->dcdb.cmd_attribute = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784
2785 if (!(scb->dcdb.cmd_attribute & 0x3))
2786 scb->dcdb.transfer_length = 0;
2787
2788 if (scb->data_len >= IPS_MAX_XFER) {
2789 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
2790 scb->dcdb.transfer_length = 0;
2791 }
2792 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002793 spin_lock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
2795 ret = ips_send_cmd(ha, scb);
2796
2797 switch (ret) {
2798 case IPS_SUCCESS:
2799 ips_putq_scb_head(&ha->scb_activelist, scb);
2800 break;
2801 case IPS_FAILURE:
2802 if (scb->scsi_cmd) {
2803 scb->scsi_cmd->result = DID_ERROR << 16;
2804 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2805 }
2806
2807 if (scb->bus)
2808 ha->dcdb_active[scb->bus - 1] &=
2809 ~(1 << scb->target_id);
2810
2811 ips_freescb(ha, scb);
2812 break;
2813 case IPS_SUCCESS_IMM:
2814 if (scb->scsi_cmd)
2815 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2816
2817 if (scb->bus)
2818 ha->dcdb_active[scb->bus - 1] &=
2819 ~(1 << scb->target_id);
2820
2821 ips_freescb(ha, scb);
2822 break;
2823 default:
2824 break;
2825 } /* end case */
2826
Henne1516b552006-10-02 14:56:23 +02002827 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828
2829 } /* end while */
2830
2831 if (intr == IPS_INTR_ON)
Adrian Bunkc6a6c812007-05-23 14:41:46 -07002832 spin_unlock(host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833}
2834
2835/****************************************************************************/
2836/* */
2837/* Routine Name: ips_putq_scb_head */
2838/* */
2839/* Routine Description: */
2840/* */
2841/* Add an item to the head of the queue */
2842/* */
2843/* ASSUMED to be called from within the HA lock */
2844/* */
2845/****************************************************************************/
2846static void
2847ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
2848{
2849 METHOD_TRACE("ips_putq_scb_head", 1);
2850
2851 if (!item)
2852 return;
2853
2854 item->q_next = queue->head;
2855 queue->head = item;
2856
2857 if (!queue->tail)
2858 queue->tail = item;
2859
2860 queue->count++;
2861}
2862
2863/****************************************************************************/
2864/* */
2865/* Routine Name: ips_removeq_scb_head */
2866/* */
2867/* Routine Description: */
2868/* */
2869/* Remove the head of the queue */
2870/* */
2871/* ASSUMED to be called from within the HA lock */
2872/* */
2873/****************************************************************************/
2874static ips_scb_t *
2875ips_removeq_scb_head(ips_scb_queue_t * queue)
2876{
2877 ips_scb_t *item;
2878
2879 METHOD_TRACE("ips_removeq_scb_head", 1);
2880
2881 item = queue->head;
2882
2883 if (!item) {
2884 return (NULL);
2885 }
2886
2887 queue->head = item->q_next;
2888 item->q_next = NULL;
2889
2890 if (queue->tail == item)
2891 queue->tail = NULL;
2892
2893 queue->count--;
2894
2895 return (item);
2896}
2897
2898/****************************************************************************/
2899/* */
2900/* Routine Name: ips_removeq_scb */
2901/* */
2902/* Routine Description: */
2903/* */
2904/* Remove an item from a queue */
2905/* */
2906/* ASSUMED to be called from within the HA lock */
2907/* */
2908/****************************************************************************/
2909static ips_scb_t *
2910ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
2911{
2912 ips_scb_t *p;
2913
2914 METHOD_TRACE("ips_removeq_scb", 1);
2915
2916 if (!item)
2917 return (NULL);
2918
2919 if (item == queue->head) {
2920 return (ips_removeq_scb_head(queue));
2921 }
2922
2923 p = queue->head;
2924
2925 while ((p) && (item != p->q_next))
2926 p = p->q_next;
2927
2928 if (p) {
2929 /* found a match */
2930 p->q_next = item->q_next;
2931
2932 if (!item->q_next)
2933 queue->tail = p;
2934
2935 item->q_next = NULL;
2936 queue->count--;
2937
2938 return (item);
2939 }
2940
2941 return (NULL);
2942}
2943
2944/****************************************************************************/
2945/* */
2946/* Routine Name: ips_putq_wait_tail */
2947/* */
2948/* Routine Description: */
2949/* */
2950/* Add an item to the tail of the queue */
2951/* */
2952/* ASSUMED to be called from within the HA lock */
2953/* */
2954/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02002955static void ips_putq_wait_tail(ips_wait_queue_t *queue, struct scsi_cmnd *item)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956{
2957 METHOD_TRACE("ips_putq_wait_tail", 1);
2958
2959 if (!item)
2960 return;
2961
2962 item->host_scribble = NULL;
2963
2964 if (queue->tail)
2965 queue->tail->host_scribble = (char *) item;
2966
2967 queue->tail = item;
2968
2969 if (!queue->head)
2970 queue->head = item;
2971
2972 queue->count++;
2973}
2974
2975/****************************************************************************/
2976/* */
2977/* Routine Name: ips_removeq_wait_head */
2978/* */
2979/* Routine Description: */
2980/* */
2981/* Remove the head of the queue */
2982/* */
2983/* ASSUMED to be called from within the HA lock */
2984/* */
2985/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02002986static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *queue)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987{
Henne1516b552006-10-02 14:56:23 +02002988 struct scsi_cmnd *item;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
2990 METHOD_TRACE("ips_removeq_wait_head", 1);
2991
2992 item = queue->head;
2993
2994 if (!item) {
2995 return (NULL);
2996 }
2997
Henne1516b552006-10-02 14:56:23 +02002998 queue->head = (struct scsi_cmnd *) item->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 item->host_scribble = NULL;
3000
3001 if (queue->tail == item)
3002 queue->tail = NULL;
3003
3004 queue->count--;
3005
3006 return (item);
3007}
3008
3009/****************************************************************************/
3010/* */
3011/* Routine Name: ips_removeq_wait */
3012/* */
3013/* Routine Description: */
3014/* */
3015/* Remove an item from a queue */
3016/* */
3017/* ASSUMED to be called from within the HA lock */
3018/* */
3019/****************************************************************************/
Henne1516b552006-10-02 14:56:23 +02003020static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *queue,
3021 struct scsi_cmnd *item)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022{
Henne1516b552006-10-02 14:56:23 +02003023 struct scsi_cmnd *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025 METHOD_TRACE("ips_removeq_wait", 1);
3026
3027 if (!item)
3028 return (NULL);
3029
3030 if (item == queue->head) {
3031 return (ips_removeq_wait_head(queue));
3032 }
3033
3034 p = queue->head;
3035
Henne1516b552006-10-02 14:56:23 +02003036 while ((p) && (item != (struct scsi_cmnd *) p->host_scribble))
3037 p = (struct scsi_cmnd *) p->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
3039 if (p) {
3040 /* found a match */
3041 p->host_scribble = item->host_scribble;
3042
3043 if (!item->host_scribble)
3044 queue->tail = p;
3045
3046 item->host_scribble = NULL;
3047 queue->count--;
3048
3049 return (item);
3050 }
3051
3052 return (NULL);
3053}
3054
3055/****************************************************************************/
3056/* */
3057/* Routine Name: ips_putq_copp_tail */
3058/* */
3059/* Routine Description: */
3060/* */
3061/* Add an item to the tail of the queue */
3062/* */
3063/* ASSUMED to be called from within the HA lock */
3064/* */
3065/****************************************************************************/
3066static void
3067ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
3068{
3069 METHOD_TRACE("ips_putq_copp_tail", 1);
3070
3071 if (!item)
3072 return;
3073
3074 item->next = NULL;
3075
3076 if (queue->tail)
3077 queue->tail->next = item;
3078
3079 queue->tail = item;
3080
3081 if (!queue->head)
3082 queue->head = item;
3083
3084 queue->count++;
3085}
3086
3087/****************************************************************************/
3088/* */
3089/* Routine Name: ips_removeq_copp_head */
3090/* */
3091/* Routine Description: */
3092/* */
3093/* Remove the head of the queue */
3094/* */
3095/* ASSUMED to be called from within the HA lock */
3096/* */
3097/****************************************************************************/
3098static ips_copp_wait_item_t *
3099ips_removeq_copp_head(ips_copp_queue_t * queue)
3100{
3101 ips_copp_wait_item_t *item;
3102
3103 METHOD_TRACE("ips_removeq_copp_head", 1);
3104
3105 item = queue->head;
3106
3107 if (!item) {
3108 return (NULL);
3109 }
3110
3111 queue->head = item->next;
3112 item->next = NULL;
3113
3114 if (queue->tail == item)
3115 queue->tail = NULL;
3116
3117 queue->count--;
3118
3119 return (item);
3120}
3121
3122/****************************************************************************/
3123/* */
3124/* Routine Name: ips_removeq_copp */
3125/* */
3126/* Routine Description: */
3127/* */
3128/* Remove an item from a queue */
3129/* */
3130/* ASSUMED to be called from within the HA lock */
3131/* */
3132/****************************************************************************/
3133static ips_copp_wait_item_t *
3134ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
3135{
3136 ips_copp_wait_item_t *p;
3137
3138 METHOD_TRACE("ips_removeq_copp", 1);
3139
3140 if (!item)
3141 return (NULL);
3142
3143 if (item == queue->head) {
3144 return (ips_removeq_copp_head(queue));
3145 }
3146
3147 p = queue->head;
3148
3149 while ((p) && (item != p->next))
3150 p = p->next;
3151
3152 if (p) {
3153 /* found a match */
3154 p->next = item->next;
3155
3156 if (!item->next)
3157 queue->tail = p;
3158
3159 item->next = NULL;
3160 queue->count--;
3161
3162 return (item);
3163 }
3164
3165 return (NULL);
3166}
3167
3168/****************************************************************************/
3169/* */
3170/* Routine Name: ipsintr_blocking */
3171/* */
3172/* Routine Description: */
3173/* */
3174/* Finalize an interrupt for internal commands */
3175/* */
3176/****************************************************************************/
3177static void
3178ipsintr_blocking(ips_ha_t * ha, ips_scb_t * scb)
3179{
3180 METHOD_TRACE("ipsintr_blocking", 2);
3181
3182 ips_freescb(ha, scb);
3183 if ((ha->waitflag == TRUE) && (ha->cmd_in_progress == scb->cdb[0])) {
3184 ha->waitflag = FALSE;
3185
3186 return;
3187 }
3188}
3189
3190/****************************************************************************/
3191/* */
3192/* Routine Name: ipsintr_done */
3193/* */
3194/* Routine Description: */
3195/* */
3196/* Finalize an interrupt for non-internal commands */
3197/* */
3198/****************************************************************************/
3199static void
3200ipsintr_done(ips_ha_t * ha, ips_scb_t * scb)
3201{
3202 METHOD_TRACE("ipsintr_done", 2);
3203
3204 if (!scb) {
3205 IPS_PRINTK(KERN_WARNING, ha->pcidev,
3206 "Spurious interrupt; scb NULL.\n");
3207
3208 return;
3209 }
3210
3211 if (scb->scsi_cmd == NULL) {
3212 /* unexpected interrupt */
3213 IPS_PRINTK(KERN_WARNING, ha->pcidev,
3214 "Spurious interrupt; scsi_cmd not set.\n");
3215
3216 return;
3217 }
3218
3219 ips_done(ha, scb);
3220}
3221
3222/****************************************************************************/
3223/* */
3224/* Routine Name: ips_done */
3225/* */
3226/* Routine Description: */
3227/* */
3228/* Do housekeeping on completed commands */
3229/* ASSUMED to be called form within the request lock */
3230/****************************************************************************/
3231static void
3232ips_done(ips_ha_t * ha, ips_scb_t * scb)
3233{
3234 int ret;
3235
3236 METHOD_TRACE("ips_done", 1);
3237
3238 if (!scb)
3239 return;
3240
3241 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
3242 ips_cleanup_passthru(ha, scb);
3243 ha->num_ioctl--;
3244 } else {
3245 /*
3246 * Check to see if this command had too much
3247 * data and had to be broke up. If so, queue
3248 * the rest of the data and continue.
3249 */
3250 if ((scb->breakup) || (scb->sg_break)) {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003251 struct scatterlist *sg;
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003252 int i, sg_dma_index, ips_sg_index = 0;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003253
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 /* we had a data breakup */
3255 scb->data_len = 0;
3256
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003257 sg = scsi_sglist(scb->scsi_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003259 /* Spin forward to last dma chunk */
3260 sg_dma_index = scb->breakup;
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003261 for (i = 0; i < scb->breakup; i++)
3262 sg = sg_next(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003264 /* Take care of possible partial on last chunk */
3265 ips_fill_scb_sg_single(ha,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003266 sg_dma_address(sg),
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003267 scb, ips_sg_index++,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003268 sg_dma_len(sg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003270 for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003271 sg_dma_index++, sg = sg_next(sg)) {
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003272 if (ips_fill_scb_sg_single
3273 (ha,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003274 sg_dma_address(sg),
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003275 scb, ips_sg_index++,
FUJITA Tomonorie0eaf882007-07-16 15:24:14 +02003276 sg_dma_len(sg)) < 0)
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003277 break;
3278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
3280 scb->dcdb.transfer_length = scb->data_len;
3281 scb->dcdb.cmd_attribute |=
3282 ips_command_direction[scb->scsi_cmd->cmnd[0]];
3283
3284 if (!(scb->dcdb.cmd_attribute & 0x3))
3285 scb->dcdb.transfer_length = 0;
3286
3287 if (scb->data_len >= IPS_MAX_XFER) {
3288 scb->dcdb.cmd_attribute |= IPS_TRANSFER64K;
3289 scb->dcdb.transfer_length = 0;
3290 }
3291
3292 ret = ips_send_cmd(ha, scb);
3293
3294 switch (ret) {
3295 case IPS_FAILURE:
3296 if (scb->scsi_cmd) {
3297 scb->scsi_cmd->result = DID_ERROR << 16;
3298 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3299 }
3300
3301 ips_freescb(ha, scb);
3302 break;
3303 case IPS_SUCCESS_IMM:
3304 if (scb->scsi_cmd) {
3305 scb->scsi_cmd->result = DID_ERROR << 16;
3306 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3307 }
3308
3309 ips_freescb(ha, scb);
3310 break;
3311 default:
3312 break;
3313 } /* end case */
3314
3315 return;
3316 }
3317 } /* end if passthru */
3318
3319 if (scb->bus) {
3320 ha->dcdb_active[scb->bus - 1] &= ~(1 << scb->target_id);
3321 }
3322
3323 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
3324
3325 ips_freescb(ha, scb);
3326}
3327
3328/****************************************************************************/
3329/* */
3330/* Routine Name: ips_map_status */
3331/* */
3332/* Routine Description: */
3333/* */
3334/* Map Controller Error codes to Linux Error Codes */
3335/* */
3336/****************************************************************************/
3337static int
3338ips_map_status(ips_ha_t * ha, ips_scb_t * scb, ips_stat_t * sp)
3339{
3340 int errcode;
3341 int device_error;
3342 uint32_t transfer_len;
3343 IPS_DCDB_TABLE_TAPE *tapeDCDB;
Jack Hammera5b3c862006-01-31 13:17:55 -05003344 IPS_SCSI_INQ_DATA inquiryData;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
3346 METHOD_TRACE("ips_map_status", 1);
3347
3348 if (scb->bus) {
3349 DEBUG_VAR(2,
3350 "(%s%d) Physical device error (%d %d %d): %x %x, Sense Key: %x, ASC: %x, ASCQ: %x",
3351 ips_name, ha->host_num,
3352 scb->scsi_cmd->device->channel,
3353 scb->scsi_cmd->device->id, scb->scsi_cmd->device->lun,
3354 scb->basic_status, scb->extended_status,
3355 scb->extended_status ==
3356 IPS_ERR_CKCOND ? scb->dcdb.sense_info[2] & 0xf : 0,
3357 scb->extended_status ==
3358 IPS_ERR_CKCOND ? scb->dcdb.sense_info[12] : 0,
3359 scb->extended_status ==
3360 IPS_ERR_CKCOND ? scb->dcdb.sense_info[13] : 0);
3361 }
3362
3363 /* default driver error */
3364 errcode = DID_ERROR;
3365 device_error = 0;
3366
3367 switch (scb->basic_status & IPS_GSC_STATUS_MASK) {
3368 case IPS_CMD_TIMEOUT:
3369 errcode = DID_TIME_OUT;
3370 break;
3371
3372 case IPS_INVAL_OPCO:
3373 case IPS_INVAL_CMD_BLK:
3374 case IPS_INVAL_PARM_BLK:
3375 case IPS_LD_ERROR:
3376 case IPS_CMD_CMPLT_WERROR:
3377 break;
3378
3379 case IPS_PHYS_DRV_ERROR:
3380 switch (scb->extended_status) {
3381 case IPS_ERR_SEL_TO:
3382 if (scb->bus)
3383 errcode = DID_NO_CONNECT;
3384
3385 break;
3386
3387 case IPS_ERR_OU_RUN:
3388 if ((scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB) ||
3389 (scb->cmd.dcdb.op_code ==
3390 IPS_CMD_EXTENDED_DCDB_SG)) {
3391 tapeDCDB = (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
3392 transfer_len = tapeDCDB->transfer_length;
3393 } else {
3394 transfer_len =
3395 (uint32_t) scb->dcdb.transfer_length;
3396 }
3397
3398 if ((scb->bus) && (transfer_len < scb->data_len)) {
3399 /* Underrun - set default to no error */
3400 errcode = DID_OK;
3401
3402 /* Restrict access to physical DASD */
Jack Hammera5b3c862006-01-31 13:17:55 -05003403 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08003404 ips_scmd_buf_read(scb->scsi_cmd,
Jack Hammera5b3c862006-01-31 13:17:55 -05003405 &inquiryData, sizeof (inquiryData));
3406 if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK) {
3407 errcode = DID_TIME_OUT;
3408 break;
3409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 }
3411 } else
3412 errcode = DID_ERROR;
3413
3414 break;
3415
3416 case IPS_ERR_RECOVERY:
3417 /* don't fail recovered errors */
3418 if (scb->bus)
3419 errcode = DID_OK;
3420
3421 break;
3422
3423 case IPS_ERR_HOST_RESET:
3424 case IPS_ERR_DEV_RESET:
3425 errcode = DID_RESET;
3426 break;
3427
3428 case IPS_ERR_CKCOND:
3429 if (scb->bus) {
3430 if ((scb->cmd.dcdb.op_code ==
3431 IPS_CMD_EXTENDED_DCDB)
3432 || (scb->cmd.dcdb.op_code ==
3433 IPS_CMD_EXTENDED_DCDB_SG)) {
3434 tapeDCDB =
3435 (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
3436 memcpy(scb->scsi_cmd->sense_buffer,
3437 tapeDCDB->sense_info,
3438 sizeof (scb->scsi_cmd->
3439 sense_buffer));
3440 } else {
3441 memcpy(scb->scsi_cmd->sense_buffer,
3442 scb->dcdb.sense_info,
3443 sizeof (scb->scsi_cmd->
3444 sense_buffer));
3445 }
3446 device_error = 2; /* check condition */
3447 }
3448
3449 errcode = DID_OK;
3450
3451 break;
3452
3453 default:
3454 errcode = DID_ERROR;
3455 break;
3456
3457 } /* end switch */
3458 } /* end switch */
3459
3460 scb->scsi_cmd->result = device_error | (errcode << 16);
3461
3462 return (1);
3463}
3464
3465/****************************************************************************/
3466/* */
3467/* Routine Name: ips_send_wait */
3468/* */
3469/* Routine Description: */
3470/* */
3471/* Send a command to the controller and wait for it to return */
3472/* */
3473/* The FFDC Time Stamp use this function for the callback, but doesn't */
3474/* actually need to wait. */
3475/****************************************************************************/
3476static int
3477ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
3478{
3479 int ret;
3480
3481 METHOD_TRACE("ips_send_wait", 1);
3482
3483 if (intr != IPS_FFDC) { /* Won't be Waiting if this is a Time Stamp */
3484 ha->waitflag = TRUE;
3485 ha->cmd_in_progress = scb->cdb[0];
3486 }
3487 scb->callback = ipsintr_blocking;
3488 ret = ips_send_cmd(ha, scb);
3489
3490 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3491 return (ret);
3492
3493 if (intr != IPS_FFDC) /* Don't Wait around if this is a Time Stamp */
3494 ret = ips_wait(ha, timeout, intr);
3495
3496 return (ret);
3497}
3498
3499/****************************************************************************/
3500/* */
3501/* Routine Name: ips_scmd_buf_write */
3502/* */
3503/* Routine Description: */
Henne1516b552006-10-02 14:56:23 +02003504/* Write data to struct scsi_cmnd request_buffer at proper offsets */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505/****************************************************************************/
3506static void
Henne1516b552006-10-02 14:56:23 +02003507ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508{
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003509 int i;
3510 unsigned int min_cnt, xfer_cnt;
3511 char *cdata = (char *) data;
3512 unsigned char *buffer;
3513 unsigned long flags;
3514 struct scatterlist *sg = scsi_sglist(scmd);
Jack Hammera3632fa2005-10-25 14:13:03 -04003515
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003516 for (i = 0, xfer_cnt = 0;
3517 (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
3518 min_cnt = min(count - xfer_cnt, sg[i].length);
Jack Hammera3632fa2005-10-25 14:13:03 -04003519
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003520 /* kmap_atomic() ensures addressability of the data buffer.*/
3521 /* local_irq_save() protects the KM_IRQ0 address slot. */
3522 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02003523 buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003524 memcpy(buffer, &cdata[xfer_cnt], min_cnt);
3525 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
3526 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003528 xfer_cnt += min_cnt;
3529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530}
3531
3532/****************************************************************************/
3533/* */
3534/* Routine Name: ips_scmd_buf_read */
3535/* */
3536/* Routine Description: */
Henne1516b552006-10-02 14:56:23 +02003537/* Copy data from a struct scsi_cmnd to a new, linear buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538/****************************************************************************/
3539static void
Henne1516b552006-10-02 14:56:23 +02003540ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541{
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003542 int i;
3543 unsigned int min_cnt, xfer_cnt;
3544 char *cdata = (char *) data;
3545 unsigned char *buffer;
3546 unsigned long flags;
3547 struct scatterlist *sg = scsi_sglist(scmd);
Jack Hammera3632fa2005-10-25 14:13:03 -04003548
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003549 for (i = 0, xfer_cnt = 0;
3550 (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
3551 min_cnt = min(count - xfer_cnt, sg[i].length);
Jack Hammera3632fa2005-10-25 14:13:03 -04003552
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003553 /* kmap_atomic() ensures addressability of the data buffer.*/
3554 /* local_irq_save() protects the KM_IRQ0 address slot. */
3555 local_irq_save(flags);
Jens Axboe45711f12007-10-22 21:19:53 +02003556 buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003557 memcpy(&cdata[xfer_cnt], buffer, min_cnt);
3558 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
3559 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09003561 xfer_cnt += min_cnt;
3562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563}
3564
3565/****************************************************************************/
3566/* */
3567/* Routine Name: ips_send_cmd */
3568/* */
3569/* Routine Description: */
3570/* */
3571/* Map SCSI commands to ServeRAID commands for logical drives */
3572/* */
3573/****************************************************************************/
3574static int
3575ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
3576{
3577 int ret;
3578 char *sp;
3579 int device_error;
3580 IPS_DCDB_TABLE_TAPE *tapeDCDB;
3581 int TimeOut;
3582
3583 METHOD_TRACE("ips_send_cmd", 1);
3584
3585 ret = IPS_SUCCESS;
3586
3587 if (!scb->scsi_cmd) {
3588 /* internal command */
3589
3590 if (scb->bus > 0) {
3591 /* Controller commands can't be issued */
3592 /* to real devices -- fail them */
3593 if ((ha->waitflag == TRUE) &&
3594 (ha->cmd_in_progress == scb->cdb[0])) {
3595 ha->waitflag = FALSE;
3596 }
3597
3598 return (1);
3599 }
3600 } else if ((scb->bus == 0) && (!ips_is_passthru(scb->scsi_cmd))) {
3601 /* command to logical bus -- interpret */
3602 ret = IPS_SUCCESS_IMM;
3603
3604 switch (scb->scsi_cmd->cmnd[0]) {
3605 case ALLOW_MEDIUM_REMOVAL:
3606 case REZERO_UNIT:
3607 case ERASE:
3608 case WRITE_FILEMARKS:
3609 case SPACE:
3610 scb->scsi_cmd->result = DID_ERROR << 16;
3611 break;
3612
3613 case START_STOP:
3614 scb->scsi_cmd->result = DID_OK << 16;
3615
3616 case TEST_UNIT_READY:
3617 case INQUIRY:
3618 if (scb->target_id == IPS_ADAPTER_ID) {
3619 /*
3620 * Either we have a TUR
3621 * or we have a SCSI inquiry
3622 */
3623 if (scb->scsi_cmd->cmnd[0] == TEST_UNIT_READY)
3624 scb->scsi_cmd->result = DID_OK << 16;
3625
3626 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
3627 IPS_SCSI_INQ_DATA inquiry;
3628
3629 memset(&inquiry, 0,
3630 sizeof (IPS_SCSI_INQ_DATA));
3631
3632 inquiry.DeviceType =
3633 IPS_SCSI_INQ_TYPE_PROCESSOR;
3634 inquiry.DeviceTypeQualifier =
3635 IPS_SCSI_INQ_LU_CONNECTED;
3636 inquiry.Version = IPS_SCSI_INQ_REV2;
3637 inquiry.ResponseDataFormat =
3638 IPS_SCSI_INQ_RD_REV2;
3639 inquiry.AdditionalLength = 31;
3640 inquiry.Flags[0] =
3641 IPS_SCSI_INQ_Address16;
3642 inquiry.Flags[1] =
3643 IPS_SCSI_INQ_WBus16 |
3644 IPS_SCSI_INQ_Sync;
3645 strncpy(inquiry.VendorId, "IBM ",
3646 8);
3647 strncpy(inquiry.ProductId,
3648 "SERVERAID ", 16);
3649 strncpy(inquiry.ProductRevisionLevel,
3650 "1.00", 4);
3651
3652 ips_scmd_buf_write(scb->scsi_cmd,
3653 &inquiry,
3654 sizeof (inquiry));
3655
3656 scb->scsi_cmd->result = DID_OK << 16;
3657 }
3658 } else {
3659 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
3660 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
3661 scb->cmd.logical_info.reserved = 0;
3662 scb->cmd.logical_info.reserved2 = 0;
3663 scb->data_len = sizeof (IPS_LD_INFO);
3664 scb->data_busaddr = ha->logical_drive_info_dma_addr;
3665 scb->flags = 0;
3666 scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
3667 ret = IPS_SUCCESS;
3668 }
3669
3670 break;
3671
3672 case REQUEST_SENSE:
3673 ips_reqsen(ha, scb);
3674 scb->scsi_cmd->result = DID_OK << 16;
3675 break;
3676
3677 case READ_6:
3678 case WRITE_6:
3679 if (!scb->sg_len) {
3680 scb->cmd.basic_io.op_code =
3681 (scb->scsi_cmd->cmnd[0] ==
3682 READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE;
3683 scb->cmd.basic_io.enhanced_sg = 0;
3684 scb->cmd.basic_io.sg_addr =
3685 cpu_to_le32(scb->data_busaddr);
3686 } else {
3687 scb->cmd.basic_io.op_code =
3688 (scb->scsi_cmd->cmnd[0] ==
3689 READ_6) ? IPS_CMD_READ_SG :
3690 IPS_CMD_WRITE_SG;
3691 scb->cmd.basic_io.enhanced_sg =
3692 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3693 scb->cmd.basic_io.sg_addr =
3694 cpu_to_le32(scb->sg_busaddr);
3695 }
3696
3697 scb->cmd.basic_io.segment_4G = 0;
3698 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3699 scb->cmd.basic_io.log_drv = scb->target_id;
3700 scb->cmd.basic_io.sg_count = scb->sg_len;
3701
3702 if (scb->cmd.basic_io.lba)
3703 scb->cmd.basic_io.lba =
3704 cpu_to_le32(le32_to_cpu
3705 (scb->cmd.basic_io.lba) +
3706 le16_to_cpu(scb->cmd.basic_io.
3707 sector_count));
3708 else
3709 scb->cmd.basic_io.lba =
3710 (((scb->scsi_cmd->
3711 cmnd[1] & 0x1f) << 16) | (scb->scsi_cmd->
3712 cmnd[2] << 8) |
3713 (scb->scsi_cmd->cmnd[3]));
3714
3715 scb->cmd.basic_io.sector_count =
3716 cpu_to_le16(scb->data_len / IPS_BLKSIZE);
3717
3718 if (le16_to_cpu(scb->cmd.basic_io.sector_count) == 0)
3719 scb->cmd.basic_io.sector_count =
3720 cpu_to_le16(256);
3721
3722 ret = IPS_SUCCESS;
3723 break;
3724
3725 case READ_10:
3726 case WRITE_10:
3727 if (!scb->sg_len) {
3728 scb->cmd.basic_io.op_code =
3729 (scb->scsi_cmd->cmnd[0] ==
3730 READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE;
3731 scb->cmd.basic_io.enhanced_sg = 0;
3732 scb->cmd.basic_io.sg_addr =
3733 cpu_to_le32(scb->data_busaddr);
3734 } else {
3735 scb->cmd.basic_io.op_code =
3736 (scb->scsi_cmd->cmnd[0] ==
3737 READ_10) ? IPS_CMD_READ_SG :
3738 IPS_CMD_WRITE_SG;
3739 scb->cmd.basic_io.enhanced_sg =
3740 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3741 scb->cmd.basic_io.sg_addr =
3742 cpu_to_le32(scb->sg_busaddr);
3743 }
3744
3745 scb->cmd.basic_io.segment_4G = 0;
3746 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3747 scb->cmd.basic_io.log_drv = scb->target_id;
3748 scb->cmd.basic_io.sg_count = scb->sg_len;
3749
3750 if (scb->cmd.basic_io.lba)
3751 scb->cmd.basic_io.lba =
3752 cpu_to_le32(le32_to_cpu
3753 (scb->cmd.basic_io.lba) +
3754 le16_to_cpu(scb->cmd.basic_io.
3755 sector_count));
3756 else
3757 scb->cmd.basic_io.lba =
3758 ((scb->scsi_cmd->cmnd[2] << 24) | (scb->
3759 scsi_cmd->
3760 cmnd[3]
3761 << 16) |
3762 (scb->scsi_cmd->cmnd[4] << 8) | scb->
3763 scsi_cmd->cmnd[5]);
3764
3765 scb->cmd.basic_io.sector_count =
3766 cpu_to_le16(scb->data_len / IPS_BLKSIZE);
3767
3768 if (cpu_to_le16(scb->cmd.basic_io.sector_count) == 0) {
3769 /*
3770 * This is a null condition
3771 * we don't have to do anything
3772 * so just return
3773 */
3774 scb->scsi_cmd->result = DID_OK << 16;
3775 } else
3776 ret = IPS_SUCCESS;
3777
3778 break;
3779
3780 case RESERVE:
3781 case RELEASE:
3782 scb->scsi_cmd->result = DID_OK << 16;
3783 break;
3784
3785 case MODE_SENSE:
3786 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
3787 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3788 scb->cmd.basic_io.segment_4G = 0;
3789 scb->cmd.basic_io.enhanced_sg = 0;
3790 scb->data_len = sizeof (*ha->enq);
3791 scb->cmd.basic_io.sg_addr = ha->enq_busaddr;
3792 ret = IPS_SUCCESS;
3793 break;
3794
3795 case READ_CAPACITY:
3796 scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO;
3797 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
3798 scb->cmd.logical_info.reserved = 0;
3799 scb->cmd.logical_info.reserved2 = 0;
3800 scb->cmd.logical_info.reserved3 = 0;
3801 scb->data_len = sizeof (IPS_LD_INFO);
3802 scb->data_busaddr = ha->logical_drive_info_dma_addr;
3803 scb->flags = 0;
3804 scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
3805 ret = IPS_SUCCESS;
3806 break;
3807
3808 case SEND_DIAGNOSTIC:
3809 case REASSIGN_BLOCKS:
3810 case FORMAT_UNIT:
3811 case SEEK_10:
3812 case VERIFY:
3813 case READ_DEFECT_DATA:
3814 case READ_BUFFER:
3815 case WRITE_BUFFER:
3816 scb->scsi_cmd->result = DID_OK << 16;
3817 break;
3818
3819 default:
3820 /* Set the Return Info to appear like the Command was */
3821 /* attempted, a Check Condition occurred, and Sense */
3822 /* Data indicating an Invalid CDB OpCode is returned. */
3823 sp = (char *) scb->scsi_cmd->sense_buffer;
3824 memset(sp, 0, sizeof (scb->scsi_cmd->sense_buffer));
3825
3826 sp[0] = 0x70; /* Error Code */
3827 sp[2] = ILLEGAL_REQUEST; /* Sense Key 5 Illegal Req. */
3828 sp[7] = 0x0A; /* Additional Sense Length */
3829 sp[12] = 0x20; /* ASC = Invalid OpCode */
3830 sp[13] = 0x00; /* ASCQ */
3831
3832 device_error = 2; /* Indicate Check Condition */
3833 scb->scsi_cmd->result = device_error | (DID_OK << 16);
3834 break;
3835 } /* end switch */
3836 }
3837 /* end if */
3838 if (ret == IPS_SUCCESS_IMM)
3839 return (ret);
3840
3841 /* setup DCDB */
3842 if (scb->bus > 0) {
3843
3844 /* If we already know the Device is Not there, no need to attempt a Command */
3845 /* This also protects an NT FailOver Controller from getting CDB's sent to it */
3846 if (ha->conf->dev[scb->bus - 1][scb->target_id].ucState == 0) {
3847 scb->scsi_cmd->result = DID_NO_CONNECT << 16;
3848 return (IPS_SUCCESS_IMM);
3849 }
3850
3851 ha->dcdb_active[scb->bus - 1] |= (1 << scb->target_id);
3852 scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
3853 scb->cmd.dcdb.dcdb_address = cpu_to_le32(scb->scb_busaddr +
3854 (unsigned long) &scb->
3855 dcdb -
3856 (unsigned long) scb);
3857 scb->cmd.dcdb.reserved = 0;
3858 scb->cmd.dcdb.reserved2 = 0;
3859 scb->cmd.dcdb.reserved3 = 0;
3860 scb->cmd.dcdb.segment_4G = 0;
3861 scb->cmd.dcdb.enhanced_sg = 0;
3862
3863 TimeOut = scb->scsi_cmd->timeout_per_command;
3864
3865 if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */
3866 if (!scb->sg_len) {
3867 scb->cmd.dcdb.op_code = IPS_CMD_EXTENDED_DCDB;
3868 } else {
3869 scb->cmd.dcdb.op_code =
3870 IPS_CMD_EXTENDED_DCDB_SG;
3871 scb->cmd.dcdb.enhanced_sg =
3872 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3873 }
3874
3875 tapeDCDB = (IPS_DCDB_TABLE_TAPE *) & scb->dcdb; /* Use Same Data Area as Old DCDB Struct */
3876 tapeDCDB->device_address =
3877 ((scb->bus - 1) << 4) | scb->target_id;
3878 tapeDCDB->cmd_attribute |= IPS_DISCONNECT_ALLOWED;
3879 tapeDCDB->cmd_attribute &= ~IPS_TRANSFER64K; /* Always Turn OFF 64K Size Flag */
3880
3881 if (TimeOut) {
3882 if (TimeOut < (10 * HZ))
3883 tapeDCDB->cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
3884 else if (TimeOut < (60 * HZ))
3885 tapeDCDB->cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
3886 else if (TimeOut < (1200 * HZ))
3887 tapeDCDB->cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
3888 }
3889
3890 tapeDCDB->cdb_length = scb->scsi_cmd->cmd_len;
3891 tapeDCDB->reserved_for_LUN = 0;
3892 tapeDCDB->transfer_length = scb->data_len;
3893 if (scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB_SG)
3894 tapeDCDB->buffer_pointer =
3895 cpu_to_le32(scb->sg_busaddr);
3896 else
3897 tapeDCDB->buffer_pointer =
3898 cpu_to_le32(scb->data_busaddr);
3899 tapeDCDB->sg_count = scb->sg_len;
3900 tapeDCDB->sense_length = sizeof (tapeDCDB->sense_info);
3901 tapeDCDB->scsi_status = 0;
3902 tapeDCDB->reserved = 0;
3903 memcpy(tapeDCDB->scsi_cdb, scb->scsi_cmd->cmnd,
3904 scb->scsi_cmd->cmd_len);
3905 } else {
3906 if (!scb->sg_len) {
3907 scb->cmd.dcdb.op_code = IPS_CMD_DCDB;
3908 } else {
3909 scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG;
3910 scb->cmd.dcdb.enhanced_sg =
3911 IPS_USE_ENH_SGLIST(ha) ? 0xFF : 0;
3912 }
3913
3914 scb->dcdb.device_address =
3915 ((scb->bus - 1) << 4) | scb->target_id;
3916 scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED;
3917
3918 if (TimeOut) {
3919 if (TimeOut < (10 * HZ))
3920 scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; /* TimeOut is 10 Seconds */
3921 else if (TimeOut < (60 * HZ))
3922 scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; /* TimeOut is 60 Seconds */
3923 else if (TimeOut < (1200 * HZ))
3924 scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; /* TimeOut is 20 Minutes */
3925 }
3926
3927 scb->dcdb.transfer_length = scb->data_len;
3928 if (scb->dcdb.cmd_attribute & IPS_TRANSFER64K)
3929 scb->dcdb.transfer_length = 0;
3930 if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB_SG)
3931 scb->dcdb.buffer_pointer =
3932 cpu_to_le32(scb->sg_busaddr);
3933 else
3934 scb->dcdb.buffer_pointer =
3935 cpu_to_le32(scb->data_busaddr);
3936 scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
3937 scb->dcdb.sense_length = sizeof (scb->dcdb.sense_info);
3938 scb->dcdb.sg_count = scb->sg_len;
3939 scb->dcdb.reserved = 0;
3940 memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd,
3941 scb->scsi_cmd->cmd_len);
3942 scb->dcdb.scsi_status = 0;
3943 scb->dcdb.reserved2[0] = 0;
3944 scb->dcdb.reserved2[1] = 0;
3945 scb->dcdb.reserved2[2] = 0;
3946 }
3947 }
3948
3949 return ((*ha->func.issue) (ha, scb));
3950}
3951
3952/****************************************************************************/
3953/* */
3954/* Routine Name: ips_chk_status */
3955/* */
3956/* Routine Description: */
3957/* */
3958/* Check the status of commands to logical drives */
3959/* Assumed to be called with the HA lock */
3960/****************************************************************************/
3961static void
3962ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus)
3963{
3964 ips_scb_t *scb;
3965 ips_stat_t *sp;
3966 uint8_t basic_status;
3967 uint8_t ext_status;
3968 int errcode;
Jack Hammera5b3c862006-01-31 13:17:55 -05003969 IPS_SCSI_INQ_DATA inquiryData;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
3971 METHOD_TRACE("ips_chkstatus", 1);
3972
3973 scb = &ha->scbs[pstatus->fields.command_id];
3974 scb->basic_status = basic_status =
3975 pstatus->fields.basic_status & IPS_BASIC_STATUS_MASK;
3976 scb->extended_status = ext_status = pstatus->fields.extended_status;
3977
3978 sp = &ha->sp;
3979 sp->residue_len = 0;
3980 sp->scb_addr = (void *) scb;
3981
3982 /* Remove the item from the active queue */
3983 ips_removeq_scb(&ha->scb_activelist, scb);
3984
3985 if (!scb->scsi_cmd)
3986 /* internal commands are handled in do_ipsintr */
3987 return;
3988
3989 DEBUG_VAR(2, "(%s%d) ips_chkstatus: cmd 0x%X id %d (%d %d %d)",
3990 ips_name,
3991 ha->host_num,
3992 scb->cdb[0],
3993 scb->cmd.basic_io.command_id,
3994 scb->bus, scb->target_id, scb->lun);
3995
3996 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
3997 /* passthru - just returns the raw result */
3998 return;
3999
4000 errcode = DID_OK;
4001
4002 if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) ||
4003 ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) {
4004
4005 if (scb->bus == 0) {
4006 if ((basic_status & IPS_GSC_STATUS_MASK) ==
4007 IPS_CMD_RECOVERED_ERROR) {
4008 DEBUG_VAR(1,
4009 "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4010 ips_name, ha->host_num,
4011 scb->cmd.basic_io.op_code,
4012 basic_status, ext_status);
4013 }
4014
4015 switch (scb->scsi_cmd->cmnd[0]) {
4016 case ALLOW_MEDIUM_REMOVAL:
4017 case REZERO_UNIT:
4018 case ERASE:
4019 case WRITE_FILEMARKS:
4020 case SPACE:
4021 errcode = DID_ERROR;
4022 break;
4023
4024 case START_STOP:
4025 break;
4026
4027 case TEST_UNIT_READY:
4028 if (!ips_online(ha, scb)) {
4029 errcode = DID_TIME_OUT;
4030 }
4031 break;
4032
4033 case INQUIRY:
4034 if (ips_online(ha, scb)) {
4035 ips_inquiry(ha, scb);
4036 } else {
4037 errcode = DID_TIME_OUT;
4038 }
4039 break;
4040
4041 case REQUEST_SENSE:
4042 ips_reqsen(ha, scb);
4043 break;
4044
4045 case READ_6:
4046 case WRITE_6:
4047 case READ_10:
4048 case WRITE_10:
4049 case RESERVE:
4050 case RELEASE:
4051 break;
4052
4053 case MODE_SENSE:
4054 if (!ips_online(ha, scb)
4055 || !ips_msense(ha, scb)) {
4056 errcode = DID_ERROR;
4057 }
4058 break;
4059
4060 case READ_CAPACITY:
4061 if (ips_online(ha, scb))
4062 ips_rdcap(ha, scb);
4063 else {
4064 errcode = DID_TIME_OUT;
4065 }
4066 break;
4067
4068 case SEND_DIAGNOSTIC:
4069 case REASSIGN_BLOCKS:
4070 break;
4071
4072 case FORMAT_UNIT:
4073 errcode = DID_ERROR;
4074 break;
4075
4076 case SEEK_10:
4077 case VERIFY:
4078 case READ_DEFECT_DATA:
4079 case READ_BUFFER:
4080 case WRITE_BUFFER:
4081 break;
4082
4083 default:
4084 errcode = DID_ERROR;
4085 } /* end switch */
4086
4087 scb->scsi_cmd->result = errcode << 16;
4088 } else { /* bus == 0 */
4089 /* restrict access to physical drives */
Jeff Garzik2f277d62007-12-13 16:14:08 -08004090 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
4091 ips_scmd_buf_read(scb->scsi_cmd,
Jack Hammera5b3c862006-01-31 13:17:55 -05004092 &inquiryData, sizeof (inquiryData));
Jeff Garzik2f277d62007-12-13 16:14:08 -08004093 if ((inquiryData.DeviceType & 0x1f) == TYPE_DISK)
Jack Hammera5b3c862006-01-31 13:17:55 -05004094 scb->scsi_cmd->result = DID_TIME_OUT << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 }
4096 } /* else */
4097 } else { /* recovered error / success */
4098 if (scb->bus == 0) {
4099 DEBUG_VAR(1,
4100 "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
4101 ips_name, ha->host_num,
4102 scb->cmd.basic_io.op_code, basic_status,
4103 ext_status);
4104 }
4105
4106 ips_map_status(ha, scb, sp);
4107 } /* else */
4108}
4109
4110/****************************************************************************/
4111/* */
4112/* Routine Name: ips_online */
4113/* */
4114/* Routine Description: */
4115/* */
4116/* Determine if a logical drive is online */
4117/* */
4118/****************************************************************************/
4119static int
4120ips_online(ips_ha_t * ha, ips_scb_t * scb)
4121{
4122 METHOD_TRACE("ips_online", 1);
4123
4124 if (scb->target_id >= IPS_MAX_LD)
4125 return (0);
4126
4127 if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
4128 memset(ha->logical_drive_info, 0, sizeof (IPS_LD_INFO));
4129 return (0);
4130 }
4131
4132 if (ha->logical_drive_info->drive_info[scb->target_id].state !=
4133 IPS_LD_OFFLINE
4134 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4135 IPS_LD_FREE
4136 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4137 IPS_LD_CRS
4138 && ha->logical_drive_info->drive_info[scb->target_id].state !=
4139 IPS_LD_SYS)
4140 return (1);
4141 else
4142 return (0);
4143}
4144
4145/****************************************************************************/
4146/* */
4147/* Routine Name: ips_inquiry */
4148/* */
4149/* Routine Description: */
4150/* */
4151/* Simulate an inquiry command to a logical drive */
4152/* */
4153/****************************************************************************/
4154static int
4155ips_inquiry(ips_ha_t * ha, ips_scb_t * scb)
4156{
4157 IPS_SCSI_INQ_DATA inquiry;
4158
4159 METHOD_TRACE("ips_inquiry", 1);
4160
4161 memset(&inquiry, 0, sizeof (IPS_SCSI_INQ_DATA));
4162
4163 inquiry.DeviceType = IPS_SCSI_INQ_TYPE_DASD;
4164 inquiry.DeviceTypeQualifier = IPS_SCSI_INQ_LU_CONNECTED;
4165 inquiry.Version = IPS_SCSI_INQ_REV2;
4166 inquiry.ResponseDataFormat = IPS_SCSI_INQ_RD_REV2;
4167 inquiry.AdditionalLength = 31;
4168 inquiry.Flags[0] = IPS_SCSI_INQ_Address16;
4169 inquiry.Flags[1] =
4170 IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync | IPS_SCSI_INQ_CmdQue;
4171 strncpy(inquiry.VendorId, "IBM ", 8);
4172 strncpy(inquiry.ProductId, "SERVERAID ", 16);
4173 strncpy(inquiry.ProductRevisionLevel, "1.00", 4);
4174
4175 ips_scmd_buf_write(scb->scsi_cmd, &inquiry, sizeof (inquiry));
4176
4177 return (1);
4178}
4179
4180/****************************************************************************/
4181/* */
4182/* Routine Name: ips_rdcap */
4183/* */
4184/* Routine Description: */
4185/* */
4186/* Simulate a read capacity command to a logical drive */
4187/* */
4188/****************************************************************************/
4189static int
4190ips_rdcap(ips_ha_t * ha, ips_scb_t * scb)
4191{
4192 IPS_SCSI_CAPACITY cap;
4193
4194 METHOD_TRACE("ips_rdcap", 1);
4195
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09004196 if (scsi_bufflen(scb->scsi_cmd) < 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197 return (0);
4198
4199 cap.lba =
4200 cpu_to_be32(le32_to_cpu
4201 (ha->logical_drive_info->
4202 drive_info[scb->target_id].sector_count) - 1);
4203 cap.len = cpu_to_be32((uint32_t) IPS_BLKSIZE);
4204
4205 ips_scmd_buf_write(scb->scsi_cmd, &cap, sizeof (cap));
4206
4207 return (1);
4208}
4209
4210/****************************************************************************/
4211/* */
4212/* Routine Name: ips_msense */
4213/* */
4214/* Routine Description: */
4215/* */
4216/* Simulate a mode sense command to a logical drive */
4217/* */
4218/****************************************************************************/
4219static int
4220ips_msense(ips_ha_t * ha, ips_scb_t * scb)
4221{
4222 uint16_t heads;
4223 uint16_t sectors;
4224 uint32_t cylinders;
4225 IPS_SCSI_MODE_PAGE_DATA mdata;
4226
4227 METHOD_TRACE("ips_msense", 1);
4228
4229 if (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) > 0x400000 &&
4230 (ha->enq->ucMiscFlag & 0x8) == 0) {
4231 heads = IPS_NORM_HEADS;
4232 sectors = IPS_NORM_SECTORS;
4233 } else {
4234 heads = IPS_COMP_HEADS;
4235 sectors = IPS_COMP_SECTORS;
4236 }
4237
4238 cylinders =
4239 (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) -
4240 1) / (heads * sectors);
4241
4242 memset(&mdata, 0, sizeof (IPS_SCSI_MODE_PAGE_DATA));
4243
4244 mdata.hdr.BlockDescLength = 8;
4245
4246 switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
4247 case 0x03: /* page 3 */
4248 mdata.pdata.pg3.PageCode = 3;
4249 mdata.pdata.pg3.PageLength = sizeof (IPS_SCSI_MODE_PAGE3);
4250 mdata.hdr.DataLength =
4251 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg3.PageLength;
4252 mdata.pdata.pg3.TracksPerZone = 0;
4253 mdata.pdata.pg3.AltSectorsPerZone = 0;
4254 mdata.pdata.pg3.AltTracksPerZone = 0;
4255 mdata.pdata.pg3.AltTracksPerVolume = 0;
4256 mdata.pdata.pg3.SectorsPerTrack = cpu_to_be16(sectors);
4257 mdata.pdata.pg3.BytesPerSector = cpu_to_be16(IPS_BLKSIZE);
4258 mdata.pdata.pg3.Interleave = cpu_to_be16(1);
4259 mdata.pdata.pg3.TrackSkew = 0;
4260 mdata.pdata.pg3.CylinderSkew = 0;
4261 mdata.pdata.pg3.flags = IPS_SCSI_MP3_SoftSector;
4262 break;
4263
4264 case 0x4:
4265 mdata.pdata.pg4.PageCode = 4;
4266 mdata.pdata.pg4.PageLength = sizeof (IPS_SCSI_MODE_PAGE4);
4267 mdata.hdr.DataLength =
4268 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg4.PageLength;
4269 mdata.pdata.pg4.CylindersHigh =
4270 cpu_to_be16((cylinders >> 8) & 0xFFFF);
4271 mdata.pdata.pg4.CylindersLow = (cylinders & 0xFF);
4272 mdata.pdata.pg4.Heads = heads;
4273 mdata.pdata.pg4.WritePrecompHigh = 0;
4274 mdata.pdata.pg4.WritePrecompLow = 0;
4275 mdata.pdata.pg4.ReducedWriteCurrentHigh = 0;
4276 mdata.pdata.pg4.ReducedWriteCurrentLow = 0;
4277 mdata.pdata.pg4.StepRate = cpu_to_be16(1);
4278 mdata.pdata.pg4.LandingZoneHigh = 0;
4279 mdata.pdata.pg4.LandingZoneLow = 0;
4280 mdata.pdata.pg4.flags = 0;
4281 mdata.pdata.pg4.RotationalOffset = 0;
4282 mdata.pdata.pg4.MediumRotationRate = 0;
4283 break;
4284 case 0x8:
4285 mdata.pdata.pg8.PageCode = 8;
4286 mdata.pdata.pg8.PageLength = sizeof (IPS_SCSI_MODE_PAGE8);
4287 mdata.hdr.DataLength =
4288 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg8.PageLength;
4289 /* everything else is left set to 0 */
4290 break;
4291
4292 default:
4293 return (0);
4294 } /* end switch */
4295
4296 ips_scmd_buf_write(scb->scsi_cmd, &mdata, sizeof (mdata));
4297
4298 return (1);
4299}
4300
4301/****************************************************************************/
4302/* */
4303/* Routine Name: ips_reqsen */
4304/* */
4305/* Routine Description: */
4306/* */
4307/* Simulate a request sense command to a logical drive */
4308/* */
4309/****************************************************************************/
4310static int
4311ips_reqsen(ips_ha_t * ha, ips_scb_t * scb)
4312{
4313 IPS_SCSI_REQSEN reqsen;
4314
4315 METHOD_TRACE("ips_reqsen", 1);
4316
4317 memset(&reqsen, 0, sizeof (IPS_SCSI_REQSEN));
4318
4319 reqsen.ResponseCode =
4320 IPS_SCSI_REQSEN_VALID | IPS_SCSI_REQSEN_CURRENT_ERR;
4321 reqsen.AdditionalLength = 10;
4322 reqsen.AdditionalSenseCode = IPS_SCSI_REQSEN_NO_SENSE;
4323 reqsen.AdditionalSenseCodeQual = IPS_SCSI_REQSEN_NO_SENSE;
4324
4325 ips_scmd_buf_write(scb->scsi_cmd, &reqsen, sizeof (reqsen));
4326
4327 return (1);
4328}
4329
4330/****************************************************************************/
4331/* */
4332/* Routine Name: ips_free */
4333/* */
4334/* Routine Description: */
4335/* */
4336/* Free any allocated space for this controller */
4337/* */
4338/****************************************************************************/
4339static void
4340ips_free(ips_ha_t * ha)
4341{
4342
4343 METHOD_TRACE("ips_free", 1);
4344
4345 if (ha) {
4346 if (ha->enq) {
4347 pci_free_consistent(ha->pcidev, sizeof(IPS_ENQ),
4348 ha->enq, ha->enq_busaddr);
4349 ha->enq = NULL;
4350 }
4351
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004352 kfree(ha->conf);
4353 ha->conf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
4355 if (ha->adapt) {
4356 pci_free_consistent(ha->pcidev,
4357 sizeof (IPS_ADAPTER) +
4358 sizeof (IPS_IO_CMD), ha->adapt,
4359 ha->adapt->hw_status_start);
4360 ha->adapt = NULL;
4361 }
4362
4363 if (ha->logical_drive_info) {
4364 pci_free_consistent(ha->pcidev,
4365 sizeof (IPS_LD_INFO),
4366 ha->logical_drive_info,
4367 ha->logical_drive_info_dma_addr);
4368 ha->logical_drive_info = NULL;
4369 }
4370
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004371 kfree(ha->nvram);
4372 ha->nvram = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004374 kfree(ha->subsys);
4375 ha->subsys = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
4377 if (ha->ioctl_data) {
4378 pci_free_consistent(ha->pcidev, ha->ioctl_len,
4379 ha->ioctl_data, ha->ioctl_busaddr);
4380 ha->ioctl_data = NULL;
4381 ha->ioctl_datasize = 0;
4382 ha->ioctl_len = 0;
4383 }
4384 ips_deallocatescbs(ha, ha->max_cmds);
4385
4386 /* free memory mapped (if applicable) */
4387 if (ha->mem_ptr) {
4388 iounmap(ha->ioremap_ptr);
4389 ha->ioremap_ptr = NULL;
4390 ha->mem_ptr = NULL;
4391 }
4392
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 ha->mem_addr = 0;
4394
4395 }
4396}
4397
4398/****************************************************************************/
4399/* */
4400/* Routine Name: ips_deallocatescbs */
4401/* */
4402/* Routine Description: */
4403/* */
4404/* Free the command blocks */
4405/* */
4406/****************************************************************************/
4407static int
4408ips_deallocatescbs(ips_ha_t * ha, int cmds)
4409{
4410 if (ha->scbs) {
4411 pci_free_consistent(ha->pcidev,
4412 IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * cmds,
4413 ha->scbs->sg_list.list,
4414 ha->scbs->sg_busaddr);
4415 pci_free_consistent(ha->pcidev, sizeof (ips_scb_t) * cmds,
4416 ha->scbs, ha->scbs->scb_busaddr);
4417 ha->scbs = NULL;
4418 } /* end if */
4419 return 1;
4420}
4421
4422/****************************************************************************/
4423/* */
4424/* Routine Name: ips_allocatescbs */
4425/* */
4426/* Routine Description: */
4427/* */
4428/* Allocate the command blocks */
4429/* */
4430/****************************************************************************/
4431static int
4432ips_allocatescbs(ips_ha_t * ha)
4433{
4434 ips_scb_t *scb_p;
4435 IPS_SG_LIST ips_sg;
4436 int i;
4437 dma_addr_t command_dma, sg_dma;
4438
4439 METHOD_TRACE("ips_allocatescbs", 1);
4440
4441 /* Allocate memory for the SCBs */
4442 ha->scbs =
4443 pci_alloc_consistent(ha->pcidev, ha->max_cmds * sizeof (ips_scb_t),
4444 &command_dma);
4445 if (ha->scbs == NULL)
4446 return 0;
4447 ips_sg.list =
4448 pci_alloc_consistent(ha->pcidev,
4449 IPS_SGLIST_SIZE(ha) * IPS_MAX_SG *
4450 ha->max_cmds, &sg_dma);
4451 if (ips_sg.list == NULL) {
4452 pci_free_consistent(ha->pcidev,
4453 ha->max_cmds * sizeof (ips_scb_t), ha->scbs,
4454 command_dma);
4455 return 0;
4456 }
4457
4458 memset(ha->scbs, 0, ha->max_cmds * sizeof (ips_scb_t));
4459
4460 for (i = 0; i < ha->max_cmds; i++) {
4461 scb_p = &ha->scbs[i];
4462 scb_p->scb_busaddr = command_dma + sizeof (ips_scb_t) * i;
4463 /* set up S/G list */
4464 if (IPS_USE_ENH_SGLIST(ha)) {
4465 scb_p->sg_list.enh_list =
4466 ips_sg.enh_list + i * IPS_MAX_SG;
4467 scb_p->sg_busaddr =
4468 sg_dma + IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * i;
4469 } else {
4470 scb_p->sg_list.std_list =
4471 ips_sg.std_list + i * IPS_MAX_SG;
4472 scb_p->sg_busaddr =
4473 sg_dma + IPS_SGLIST_SIZE(ha) * IPS_MAX_SG * i;
4474 }
4475
4476 /* add to the free list */
4477 if (i < ha->max_cmds - 1) {
4478 scb_p->q_next = ha->scb_freelist;
4479 ha->scb_freelist = scb_p;
4480 }
4481 }
4482
4483 /* success */
4484 return (1);
4485}
4486
4487/****************************************************************************/
4488/* */
4489/* Routine Name: ips_init_scb */
4490/* */
4491/* Routine Description: */
4492/* */
4493/* Initialize a CCB to default values */
4494/* */
4495/****************************************************************************/
4496static void
4497ips_init_scb(ips_ha_t * ha, ips_scb_t * scb)
4498{
4499 IPS_SG_LIST sg_list;
4500 uint32_t cmd_busaddr, sg_busaddr;
4501 METHOD_TRACE("ips_init_scb", 1);
4502
4503 if (scb == NULL)
4504 return;
4505
4506 sg_list.list = scb->sg_list.list;
4507 cmd_busaddr = scb->scb_busaddr;
4508 sg_busaddr = scb->sg_busaddr;
4509 /* zero fill */
4510 memset(scb, 0, sizeof (ips_scb_t));
4511 memset(ha->dummy, 0, sizeof (IPS_IO_CMD));
4512
4513 /* Initialize dummy command bucket */
4514 ha->dummy->op_code = 0xFF;
4515 ha->dummy->ccsar = cpu_to_le32(ha->adapt->hw_status_start
4516 + sizeof (IPS_ADAPTER));
4517 ha->dummy->command_id = IPS_MAX_CMDS;
4518
4519 /* set bus address of scb */
4520 scb->scb_busaddr = cmd_busaddr;
4521 scb->sg_busaddr = sg_busaddr;
4522 scb->sg_list.list = sg_list.list;
4523
4524 /* Neptune Fix */
4525 scb->cmd.basic_io.cccr = cpu_to_le32((uint32_t) IPS_BIT_ILE);
4526 scb->cmd.basic_io.ccsar = cpu_to_le32(ha->adapt->hw_status_start
4527 + sizeof (IPS_ADAPTER));
4528}
4529
4530/****************************************************************************/
4531/* */
4532/* Routine Name: ips_get_scb */
4533/* */
4534/* Routine Description: */
4535/* */
4536/* Initialize a CCB to default values */
4537/* */
4538/* ASSUMED to be callled from within a lock */
4539/* */
4540/****************************************************************************/
4541static ips_scb_t *
4542ips_getscb(ips_ha_t * ha)
4543{
4544 ips_scb_t *scb;
4545
4546 METHOD_TRACE("ips_getscb", 1);
4547
4548 if ((scb = ha->scb_freelist) == NULL) {
4549
4550 return (NULL);
4551 }
4552
4553 ha->scb_freelist = scb->q_next;
4554 scb->flags = 0;
4555 scb->q_next = NULL;
4556
4557 ips_init_scb(ha, scb);
4558
4559 return (scb);
4560}
4561
4562/****************************************************************************/
4563/* */
4564/* Routine Name: ips_free_scb */
4565/* */
4566/* Routine Description: */
4567/* */
4568/* Return an unused CCB back to the free list */
4569/* */
4570/* ASSUMED to be called from within a lock */
4571/* */
4572/****************************************************************************/
4573static void
4574ips_freescb(ips_ha_t * ha, ips_scb_t * scb)
4575{
4576
4577 METHOD_TRACE("ips_freescb", 1);
4578 if (scb->flags & IPS_SCB_MAP_SG)
FUJITA Tomonori2f4cf912007-06-13 23:27:09 +09004579 scsi_dma_unmap(scb->scsi_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 else if (scb->flags & IPS_SCB_MAP_SINGLE)
4581 pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
4582 IPS_DMA_DIR(scb));
4583
4584 /* check to make sure this is not our "special" scb */
4585 if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
4586 scb->q_next = ha->scb_freelist;
4587 ha->scb_freelist = scb;
4588 }
4589}
4590
4591/****************************************************************************/
4592/* */
4593/* Routine Name: ips_isinit_copperhead */
4594/* */
4595/* Routine Description: */
4596/* */
4597/* Is controller initialized ? */
4598/* */
4599/****************************************************************************/
4600static int
4601ips_isinit_copperhead(ips_ha_t * ha)
4602{
4603 uint8_t scpr;
4604 uint8_t isr;
4605
4606 METHOD_TRACE("ips_isinit_copperhead", 1);
4607
4608 isr = inb(ha->io_addr + IPS_REG_HISR);
4609 scpr = inb(ha->io_addr + IPS_REG_SCPR);
4610
4611 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4612 return (0);
4613 else
4614 return (1);
4615}
4616
4617/****************************************************************************/
4618/* */
4619/* Routine Name: ips_isinit_copperhead_memio */
4620/* */
4621/* Routine Description: */
4622/* */
4623/* Is controller initialized ? */
4624/* */
4625/****************************************************************************/
4626static int
4627ips_isinit_copperhead_memio(ips_ha_t * ha)
4628{
4629 uint8_t isr = 0;
4630 uint8_t scpr;
4631
4632 METHOD_TRACE("ips_is_init_copperhead_memio", 1);
4633
4634 isr = readb(ha->mem_ptr + IPS_REG_HISR);
4635 scpr = readb(ha->mem_ptr + IPS_REG_SCPR);
4636
4637 if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
4638 return (0);
4639 else
4640 return (1);
4641}
4642
4643/****************************************************************************/
4644/* */
4645/* Routine Name: ips_isinit_morpheus */
4646/* */
4647/* Routine Description: */
4648/* */
4649/* Is controller initialized ? */
4650/* */
4651/****************************************************************************/
4652static int
4653ips_isinit_morpheus(ips_ha_t * ha)
4654{
4655 uint32_t post;
4656 uint32_t bits;
4657
4658 METHOD_TRACE("ips_is_init_morpheus", 1);
Jeff Garzik2f277d62007-12-13 16:14:08 -08004659
4660 if (ips_isintr_morpheus(ha))
Jack Hammeree807c22005-08-29 10:44:34 -04004661 ips_flush_and_reset(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662
4663 post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
4664 bits = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
4665
4666 if (post == 0)
4667 return (0);
4668 else if (bits & 0x3)
4669 return (0);
4670 else
4671 return (1);
4672}
4673
4674/****************************************************************************/
4675/* */
Jack Hammeree807c22005-08-29 10:44:34 -04004676/* Routine Name: ips_flush_and_reset */
4677/* */
4678/* Routine Description: */
4679/* */
4680/* Perform cleanup ( FLUSH and RESET ) when the adapter is in an unknown */
4681/* state ( was trying to INIT and an interrupt was already pending ) ... */
4682/* */
4683/****************************************************************************/
Jeff Garzik2f277d62007-12-13 16:14:08 -08004684static void
Jack Hammeree807c22005-08-29 10:44:34 -04004685ips_flush_and_reset(ips_ha_t *ha)
4686{
4687 ips_scb_t *scb;
4688 int ret;
4689 int time;
4690 int done;
4691 dma_addr_t command_dma;
4692
4693 /* Create a usuable SCB */
4694 scb = pci_alloc_consistent(ha->pcidev, sizeof(ips_scb_t), &command_dma);
4695 if (scb) {
4696 memset(scb, 0, sizeof(ips_scb_t));
4697 ips_init_scb(ha, scb);
4698 scb->scb_busaddr = command_dma;
4699
4700 scb->timeout = ips_cmd_timeout;
4701 scb->cdb[0] = IPS_CMD_FLUSH;
4702
4703 scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH;
4704 scb->cmd.flush_cache.command_id = IPS_MAX_CMDS; /* Use an ID that would otherwise not exist */
4705 scb->cmd.flush_cache.state = IPS_NORM_STATE;
4706 scb->cmd.flush_cache.reserved = 0;
4707 scb->cmd.flush_cache.reserved2 = 0;
4708 scb->cmd.flush_cache.reserved3 = 0;
4709 scb->cmd.flush_cache.reserved4 = 0;
4710
4711 ret = ips_send_cmd(ha, scb); /* Send the Flush Command */
4712
4713 if (ret == IPS_SUCCESS) {
4714 time = 60 * IPS_ONE_SEC; /* Max Wait time is 60 seconds */
4715 done = 0;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004716
Jack Hammeree807c22005-08-29 10:44:34 -04004717 while ((time > 0) && (!done)) {
Jeff Garzik2f277d62007-12-13 16:14:08 -08004718 done = ips_poll_for_flush_complete(ha);
Jack Hammeree807c22005-08-29 10:44:34 -04004719 /* This may look evil, but it's only done during extremely rare start-up conditions ! */
4720 udelay(1000);
4721 time--;
4722 }
4723 }
4724 }
4725
4726 /* Now RESET and INIT the adapter */
4727 (*ha->func.reset) (ha);
4728
4729 pci_free_consistent(ha->pcidev, sizeof(ips_scb_t), scb, command_dma);
4730 return;
4731}
4732
4733/****************************************************************************/
4734/* */
4735/* Routine Name: ips_poll_for_flush_complete */
4736/* */
4737/* Routine Description: */
4738/* */
4739/* Poll for the Flush Command issued by ips_flush_and_reset() to complete */
4740/* All other responses are just taken off the queue and ignored */
4741/* */
4742/****************************************************************************/
4743static int
4744ips_poll_for_flush_complete(ips_ha_t * ha)
4745{
4746 IPS_STATUS cstatus;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004747
Jack Hammeree807c22005-08-29 10:44:34 -04004748 while (TRUE) {
4749 cstatus.value = (*ha->func.statupd) (ha);
4750
4751 if (cstatus.value == 0xffffffff) /* If No Interrupt to process */
4752 break;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004753
Jack Hammeree807c22005-08-29 10:44:34 -04004754 /* Success is when we see the Flush Command ID */
Jeff Garzik2f277d62007-12-13 16:14:08 -08004755 if (cstatus.fields.command_id == IPS_MAX_CMDS)
Jack Hammeree807c22005-08-29 10:44:34 -04004756 return 1;
Jeff Garzik2f277d62007-12-13 16:14:08 -08004757 }
Jack Hammeree807c22005-08-29 10:44:34 -04004758
4759 return 0;
James Bottomley0ee957c2005-11-04 23:22:55 -06004760}
Jack Hammeree807c22005-08-29 10:44:34 -04004761
4762/****************************************************************************/
4763/* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764/* Routine Name: ips_enable_int_copperhead */
4765/* */
4766/* Routine Description: */
4767/* Turn on interrupts */
4768/* */
4769/****************************************************************************/
4770static void
4771ips_enable_int_copperhead(ips_ha_t * ha)
4772{
4773 METHOD_TRACE("ips_enable_int_copperhead", 1);
4774
4775 outb(ha->io_addr + IPS_REG_HISR, IPS_BIT_EI);
4776 inb(ha->io_addr + IPS_REG_HISR); /*Ensure PCI Posting Completes*/
4777}
4778
4779/****************************************************************************/
4780/* */
4781/* Routine Name: ips_enable_int_copperhead_memio */
4782/* */
4783/* Routine Description: */
4784/* Turn on interrupts */
4785/* */
4786/****************************************************************************/
4787static void
4788ips_enable_int_copperhead_memio(ips_ha_t * ha)
4789{
4790 METHOD_TRACE("ips_enable_int_copperhead_memio", 1);
4791
4792 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
4793 readb(ha->mem_ptr + IPS_REG_HISR); /*Ensure PCI Posting Completes*/
4794}
4795
4796/****************************************************************************/
4797/* */
4798/* Routine Name: ips_enable_int_morpheus */
4799/* */
4800/* Routine Description: */
4801/* Turn on interrupts */
4802/* */
4803/****************************************************************************/
4804static void
4805ips_enable_int_morpheus(ips_ha_t * ha)
4806{
4807 uint32_t Oimr;
4808
4809 METHOD_TRACE("ips_enable_int_morpheus", 1);
4810
4811 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
4812 Oimr &= ~0x08;
4813 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
4814 readl(ha->mem_ptr + IPS_REG_I960_OIMR); /*Ensure PCI Posting Completes*/
4815}
4816
4817/****************************************************************************/
4818/* */
4819/* Routine Name: ips_init_copperhead */
4820/* */
4821/* Routine Description: */
4822/* */
4823/* Initialize a copperhead controller */
4824/* */
4825/****************************************************************************/
4826static int
4827ips_init_copperhead(ips_ha_t * ha)
4828{
4829 uint8_t Isr;
4830 uint8_t Cbsp;
4831 uint8_t PostByte[IPS_MAX_POST_BYTES];
4832 uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
4833 int i, j;
4834
4835 METHOD_TRACE("ips_init_copperhead", 1);
4836
4837 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4838 for (j = 0; j < 45; j++) {
4839 Isr = inb(ha->io_addr + IPS_REG_HISR);
4840 if (Isr & IPS_BIT_GHI)
4841 break;
4842
4843 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004844 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845 }
4846
4847 if (j >= 45)
4848 /* error occurred */
4849 return (0);
4850
4851 PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4852 outb(Isr, ha->io_addr + IPS_REG_HISR);
4853 }
4854
4855 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4856 IPS_PRINTK(KERN_WARNING, ha->pcidev,
4857 "reset controller fails (post status %x %x).\n",
4858 PostByte[0], PostByte[1]);
4859
4860 return (0);
4861 }
4862
4863 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4864 for (j = 0; j < 240; j++) {
4865 Isr = inb(ha->io_addr + IPS_REG_HISR);
4866 if (Isr & IPS_BIT_GHI)
4867 break;
4868
4869 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004870 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004871 }
4872
4873 if (j >= 240)
4874 /* error occurred */
4875 return (0);
4876
4877 ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
4878 outb(Isr, ha->io_addr + IPS_REG_HISR);
4879 }
4880
4881 for (i = 0; i < 240; i++) {
4882 Cbsp = inb(ha->io_addr + IPS_REG_CBSP);
4883
4884 if ((Cbsp & IPS_BIT_OP) == 0)
4885 break;
4886
4887 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004888 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889 }
4890
4891 if (i >= 240)
4892 /* reset failed */
4893 return (0);
4894
4895 /* setup CCCR */
4896 outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
4897
4898 /* Enable busmastering */
4899 outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
4900
Jeff Garzik8a694cc2007-12-13 16:14:07 -08004901 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902 /* fix for anaconda64 */
4903 outl(0, ha->io_addr + IPS_REG_NDAE);
4904
4905 /* Enable interrupts */
4906 outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR);
4907
4908 return (1);
4909}
4910
4911/****************************************************************************/
4912/* */
4913/* Routine Name: ips_init_copperhead_memio */
4914/* */
4915/* Routine Description: */
4916/* */
4917/* Initialize a copperhead controller with memory mapped I/O */
4918/* */
4919/****************************************************************************/
4920static int
4921ips_init_copperhead_memio(ips_ha_t * ha)
4922{
4923 uint8_t Isr = 0;
4924 uint8_t Cbsp;
4925 uint8_t PostByte[IPS_MAX_POST_BYTES];
4926 uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
4927 int i, j;
4928
4929 METHOD_TRACE("ips_init_copperhead_memio", 1);
4930
4931 for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
4932 for (j = 0; j < 45; j++) {
4933 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4934 if (Isr & IPS_BIT_GHI)
4935 break;
4936
4937 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004938 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 }
4940
4941 if (j >= 45)
4942 /* error occurred */
4943 return (0);
4944
4945 PostByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4946 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4947 }
4948
4949 if (PostByte[0] < IPS_GOOD_POST_STATUS) {
4950 IPS_PRINTK(KERN_WARNING, ha->pcidev,
4951 "reset controller fails (post status %x %x).\n",
4952 PostByte[0], PostByte[1]);
4953
4954 return (0);
4955 }
4956
4957 for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
4958 for (j = 0; j < 240; j++) {
4959 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
4960 if (Isr & IPS_BIT_GHI)
4961 break;
4962
4963 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004964 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965 }
4966
4967 if (j >= 240)
4968 /* error occurred */
4969 return (0);
4970
4971 ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
4972 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
4973 }
4974
4975 for (i = 0; i < 240; i++) {
4976 Cbsp = readb(ha->mem_ptr + IPS_REG_CBSP);
4977
4978 if ((Cbsp & IPS_BIT_OP) == 0)
4979 break;
4980
4981 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08004982 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 }
4984
4985 if (i >= 240)
4986 /* error occurred */
4987 return (0);
4988
4989 /* setup CCCR */
4990 writel(0x1010, ha->mem_ptr + IPS_REG_CCCR);
4991
4992 /* Enable busmastering */
4993 writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
4994
Jeff Garzik8a694cc2007-12-13 16:14:07 -08004995 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996 /* fix for anaconda64 */
4997 writel(0, ha->mem_ptr + IPS_REG_NDAE);
4998
4999 /* Enable interrupts */
5000 writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
5001
5002 /* if we get here then everything went OK */
5003 return (1);
5004}
5005
5006/****************************************************************************/
5007/* */
5008/* Routine Name: ips_init_morpheus */
5009/* */
5010/* Routine Description: */
5011/* */
5012/* Initialize a morpheus controller */
5013/* */
5014/****************************************************************************/
5015static int
5016ips_init_morpheus(ips_ha_t * ha)
5017{
5018 uint32_t Post;
5019 uint32_t Config;
5020 uint32_t Isr;
5021 uint32_t Oimr;
5022 int i;
5023
5024 METHOD_TRACE("ips_init_morpheus", 1);
5025
5026 /* Wait up to 45 secs for Post */
5027 for (i = 0; i < 45; i++) {
5028 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5029
5030 if (Isr & IPS_BIT_I960_MSG0I)
5031 break;
5032
5033 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005034 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035 }
5036
5037 if (i >= 45) {
5038 /* error occurred */
5039 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5040 "timeout waiting for post.\n");
5041
5042 return (0);
5043 }
5044
5045 Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
5046
5047 if (Post == 0x4F00) { /* If Flashing the Battery PIC */
5048 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5049 "Flashing Battery PIC, Please wait ...\n");
5050
5051 /* Clear the interrupt bit */
5052 Isr = (uint32_t) IPS_BIT_I960_MSG0I;
5053 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5054
5055 for (i = 0; i < 120; i++) { /* Wait Up to 2 Min. for Completion */
5056 Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
5057 if (Post != 0x4F00)
5058 break;
5059 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005060 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 }
5062
5063 if (i >= 120) {
5064 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5065 "timeout waiting for Battery PIC Flash\n");
5066 return (0);
5067 }
5068
5069 }
5070
5071 /* Clear the interrupt bit */
5072 Isr = (uint32_t) IPS_BIT_I960_MSG0I;
5073 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5074
5075 if (Post < (IPS_GOOD_POST_STATUS << 8)) {
5076 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5077 "reset controller fails (post status %x).\n", Post);
5078
5079 return (0);
5080 }
5081
5082 /* Wait up to 240 secs for config bytes */
5083 for (i = 0; i < 240; i++) {
5084 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5085
5086 if (Isr & IPS_BIT_I960_MSG1I)
5087 break;
5088
5089 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005090 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091 }
5092
5093 if (i >= 240) {
5094 /* error occurred */
5095 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5096 "timeout waiting for config.\n");
5097
5098 return (0);
5099 }
5100
5101 Config = readl(ha->mem_ptr + IPS_REG_I960_MSG1);
5102
5103 /* Clear interrupt bit */
5104 Isr = (uint32_t) IPS_BIT_I960_MSG1I;
5105 writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
5106
5107 /* Turn on the interrupts */
5108 Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
5109 Oimr &= ~0x8;
5110 writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
5111
5112 /* if we get here then everything went OK */
5113
5114 /* Since we did a RESET, an EraseStripeLock may be needed */
5115 if (Post == 0xEF10) {
5116 if ((Config == 0x000F) || (Config == 0x0009))
5117 ha->requires_esl = 1;
5118 }
5119
5120 return (1);
5121}
5122
5123/****************************************************************************/
5124/* */
5125/* Routine Name: ips_reset_copperhead */
5126/* */
5127/* Routine Description: */
5128/* */
5129/* Reset the controller */
5130/* */
5131/****************************************************************************/
5132static int
5133ips_reset_copperhead(ips_ha_t * ha)
5134{
5135 int reset_counter;
5136
5137 METHOD_TRACE("ips_reset_copperhead", 1);
5138
5139 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005140 ips_name, ha->host_num, ha->io_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005141
5142 reset_counter = 0;
5143
5144 while (reset_counter < 2) {
5145 reset_counter++;
5146
5147 outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
5148
5149 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005150 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
5152 outb(0, ha->io_addr + IPS_REG_SCPR);
5153
5154 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005155 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
5157 if ((*ha->func.init) (ha))
5158 break;
5159 else if (reset_counter >= 2) {
5160
5161 return (0);
5162 }
5163 }
5164
5165 return (1);
5166}
5167
5168/****************************************************************************/
5169/* */
5170/* Routine Name: ips_reset_copperhead_memio */
5171/* */
5172/* Routine Description: */
5173/* */
5174/* Reset the controller */
5175/* */
5176/****************************************************************************/
5177static int
5178ips_reset_copperhead_memio(ips_ha_t * ha)
5179{
5180 int reset_counter;
5181
5182 METHOD_TRACE("ips_reset_copperhead_memio", 1);
5183
5184 DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005185 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005186
5187 reset_counter = 0;
5188
5189 while (reset_counter < 2) {
5190 reset_counter++;
5191
5192 writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
5193
5194 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005195 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
5197 writeb(0, ha->mem_ptr + IPS_REG_SCPR);
5198
5199 /* Delay for 1 Second */
Andrew Mortonbf471342006-11-08 19:56:24 -08005200 MDELAY(IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
5202 if ((*ha->func.init) (ha))
5203 break;
5204 else if (reset_counter >= 2) {
5205
5206 return (0);
5207 }
5208 }
5209
5210 return (1);
5211}
5212
5213/****************************************************************************/
5214/* */
5215/* Routine Name: ips_reset_morpheus */
5216/* */
5217/* Routine Description: */
5218/* */
5219/* Reset the controller */
5220/* */
5221/****************************************************************************/
5222static int
5223ips_reset_morpheus(ips_ha_t * ha)
5224{
5225 int reset_counter;
5226 uint8_t junk;
5227
5228 METHOD_TRACE("ips_reset_morpheus", 1);
5229
5230 DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
Jeff Garzik8a694cc2007-12-13 16:14:07 -08005231 ips_name, ha->host_num, ha->mem_addr, ha->pcidev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
5233 reset_counter = 0;
5234
5235 while (reset_counter < 2) {
5236 reset_counter++;
5237
5238 writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
5239
5240 /* Delay for 5 Seconds */
Andrew Mortonbf471342006-11-08 19:56:24 -08005241 MDELAY(5 * IPS_ONE_SEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
5243 /* Do a PCI config read to wait for adapter */
5244 pci_read_config_byte(ha->pcidev, 4, &junk);
5245
5246 if ((*ha->func.init) (ha))
5247 break;
5248 else if (reset_counter >= 2) {
5249
5250 return (0);
5251 }
5252 }
5253
5254 return (1);
5255}
5256
5257/****************************************************************************/
5258/* */
5259/* Routine Name: ips_statinit */
5260/* */
5261/* Routine Description: */
5262/* */
5263/* Initialize the status queues on the controller */
5264/* */
5265/****************************************************************************/
5266static void
5267ips_statinit(ips_ha_t * ha)
5268{
5269 uint32_t phys_status_start;
5270
5271 METHOD_TRACE("ips_statinit", 1);
5272
5273 ha->adapt->p_status_start = ha->adapt->status;
5274 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5275 ha->adapt->p_status_tail = ha->adapt->status;
5276
5277 phys_status_start = ha->adapt->hw_status_start;
5278 outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
5279 outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
5280 ha->io_addr + IPS_REG_SQER);
5281 outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
5282 ha->io_addr + IPS_REG_SQHR);
5283 outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
5284
5285 ha->adapt->hw_status_tail = phys_status_start;
5286}
5287
5288/****************************************************************************/
5289/* */
5290/* Routine Name: ips_statinit_memio */
5291/* */
5292/* Routine Description: */
5293/* */
5294/* Initialize the status queues on the controller */
5295/* */
5296/****************************************************************************/
5297static void
5298ips_statinit_memio(ips_ha_t * ha)
5299{
5300 uint32_t phys_status_start;
5301
5302 METHOD_TRACE("ips_statinit_memio", 1);
5303
5304 ha->adapt->p_status_start = ha->adapt->status;
5305 ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
5306 ha->adapt->p_status_tail = ha->adapt->status;
5307
5308 phys_status_start = ha->adapt->hw_status_start;
5309 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQSR);
5310 writel(phys_status_start + IPS_STATUS_Q_SIZE,
5311 ha->mem_ptr + IPS_REG_SQER);
5312 writel(phys_status_start + IPS_STATUS_SIZE, ha->mem_ptr + IPS_REG_SQHR);
5313 writel(phys_status_start, ha->mem_ptr + IPS_REG_SQTR);
5314
5315 ha->adapt->hw_status_tail = phys_status_start;
5316}
5317
5318/****************************************************************************/
5319/* */
5320/* Routine Name: ips_statupd_copperhead */
5321/* */
5322/* Routine Description: */
5323/* */
5324/* Remove an element from the status queue */
5325/* */
5326/****************************************************************************/
5327static uint32_t
5328ips_statupd_copperhead(ips_ha_t * ha)
5329{
5330 METHOD_TRACE("ips_statupd_copperhead", 1);
5331
5332 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5333 ha->adapt->p_status_tail++;
5334 ha->adapt->hw_status_tail += sizeof (IPS_STATUS);
5335 } else {
5336 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5337 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5338 }
5339
5340 outl(cpu_to_le32(ha->adapt->hw_status_tail),
5341 ha->io_addr + IPS_REG_SQTR);
5342
5343 return (ha->adapt->p_status_tail->value);
5344}
5345
5346/****************************************************************************/
5347/* */
5348/* Routine Name: ips_statupd_copperhead_memio */
5349/* */
5350/* Routine Description: */
5351/* */
5352/* Remove an element from the status queue */
5353/* */
5354/****************************************************************************/
5355static uint32_t
5356ips_statupd_copperhead_memio(ips_ha_t * ha)
5357{
5358 METHOD_TRACE("ips_statupd_copperhead_memio", 1);
5359
5360 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
5361 ha->adapt->p_status_tail++;
5362 ha->adapt->hw_status_tail += sizeof (IPS_STATUS);
5363 } else {
5364 ha->adapt->p_status_tail = ha->adapt->p_status_start;
5365 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
5366 }
5367
5368 writel(ha->adapt->hw_status_tail, ha->mem_ptr + IPS_REG_SQTR);
5369
5370 return (ha->adapt->p_status_tail->value);
5371}
5372
5373/****************************************************************************/
5374/* */
5375/* Routine Name: ips_statupd_morpheus */
5376/* */
5377/* Routine Description: */
5378/* */
5379/* Remove an element from the status queue */
5380/* */
5381/****************************************************************************/
5382static uint32_t
5383ips_statupd_morpheus(ips_ha_t * ha)
5384{
5385 uint32_t val;
5386
5387 METHOD_TRACE("ips_statupd_morpheus", 1);
5388
5389 val = readl(ha->mem_ptr + IPS_REG_I2O_OUTMSGQ);
5390
5391 return (val);
5392}
5393
5394/****************************************************************************/
5395/* */
5396/* Routine Name: ips_issue_copperhead */
5397/* */
5398/* Routine Description: */
5399/* */
5400/* Send a command down to the controller */
5401/* */
5402/****************************************************************************/
5403static int
5404ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
5405{
5406 uint32_t TimeOut;
5407 uint32_t val;
5408
5409 METHOD_TRACE("ips_issue_copperhead", 1);
5410
5411 if (scb->scsi_cmd) {
5412 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5413 ips_name,
5414 ha->host_num,
5415 scb->cdb[0],
5416 scb->cmd.basic_io.command_id,
5417 scb->bus, scb->target_id, scb->lun);
5418 } else {
5419 DEBUG_VAR(2, KERN_NOTICE "(%s%d) ips_issue: logical cmd id %d",
5420 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5421 }
5422
5423 TimeOut = 0;
5424
5425 while ((val =
5426 le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
5427 udelay(1000);
5428
5429 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5430 if (!(val & IPS_BIT_START_STOP))
5431 break;
5432
5433 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5434 "ips_issue val [0x%x].\n", val);
5435 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5436 "ips_issue semaphore chk timeout.\n");
5437
5438 return (IPS_FAILURE);
5439 } /* end if */
5440 } /* end while */
5441
5442 outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
5443 outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
5444
5445 return (IPS_SUCCESS);
5446}
5447
5448/****************************************************************************/
5449/* */
5450/* Routine Name: ips_issue_copperhead_memio */
5451/* */
5452/* Routine Description: */
5453/* */
5454/* Send a command down to the controller */
5455/* */
5456/****************************************************************************/
5457static int
5458ips_issue_copperhead_memio(ips_ha_t * ha, ips_scb_t * scb)
5459{
5460 uint32_t TimeOut;
5461 uint32_t val;
5462
5463 METHOD_TRACE("ips_issue_copperhead_memio", 1);
5464
5465 if (scb->scsi_cmd) {
5466 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5467 ips_name,
5468 ha->host_num,
5469 scb->cdb[0],
5470 scb->cmd.basic_io.command_id,
5471 scb->bus, scb->target_id, scb->lun);
5472 } else {
5473 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5474 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5475 }
5476
5477 TimeOut = 0;
5478
5479 while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
5480 udelay(1000);
5481
5482 if (++TimeOut >= IPS_SEM_TIMEOUT) {
5483 if (!(val & IPS_BIT_START_STOP))
5484 break;
5485
5486 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5487 "ips_issue val [0x%x].\n", val);
5488 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5489 "ips_issue semaphore chk timeout.\n");
5490
5491 return (IPS_FAILURE);
5492 } /* end if */
5493 } /* end while */
5494
5495 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_CCSAR);
5496 writel(IPS_BIT_START_CMD, ha->mem_ptr + IPS_REG_CCCR);
5497
5498 return (IPS_SUCCESS);
5499}
5500
5501/****************************************************************************/
5502/* */
5503/* Routine Name: ips_issue_i2o */
5504/* */
5505/* Routine Description: */
5506/* */
5507/* Send a command down to the controller */
5508/* */
5509/****************************************************************************/
5510static int
5511ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
5512{
5513
5514 METHOD_TRACE("ips_issue_i2o", 1);
5515
5516 if (scb->scsi_cmd) {
5517 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5518 ips_name,
5519 ha->host_num,
5520 scb->cdb[0],
5521 scb->cmd.basic_io.command_id,
5522 scb->bus, scb->target_id, scb->lun);
5523 } else {
5524 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5525 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5526 }
5527
5528 outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
5529
5530 return (IPS_SUCCESS);
5531}
5532
5533/****************************************************************************/
5534/* */
5535/* Routine Name: ips_issue_i2o_memio */
5536/* */
5537/* Routine Description: */
5538/* */
5539/* Send a command down to the controller */
5540/* */
5541/****************************************************************************/
5542static int
5543ips_issue_i2o_memio(ips_ha_t * ha, ips_scb_t * scb)
5544{
5545
5546 METHOD_TRACE("ips_issue_i2o_memio", 1);
5547
5548 if (scb->scsi_cmd) {
5549 DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
5550 ips_name,
5551 ha->host_num,
5552 scb->cdb[0],
5553 scb->cmd.basic_io.command_id,
5554 scb->bus, scb->target_id, scb->lun);
5555 } else {
5556 DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
5557 ips_name, ha->host_num, scb->cmd.basic_io.command_id);
5558 }
5559
5560 writel(scb->scb_busaddr, ha->mem_ptr + IPS_REG_I2O_INMSGQ);
5561
5562 return (IPS_SUCCESS);
5563}
5564
5565/****************************************************************************/
5566/* */
5567/* Routine Name: ips_isintr_copperhead */
5568/* */
5569/* Routine Description: */
5570/* */
5571/* Test to see if an interrupt is for us */
5572/* */
5573/****************************************************************************/
5574static int
5575ips_isintr_copperhead(ips_ha_t * ha)
5576{
5577 uint8_t Isr;
5578
5579 METHOD_TRACE("ips_isintr_copperhead", 2);
5580
5581 Isr = inb(ha->io_addr + IPS_REG_HISR);
5582
5583 if (Isr == 0xFF)
5584 /* ?!?! Nothing really there */
5585 return (0);
5586
5587 if (Isr & IPS_BIT_SCE)
5588 return (1);
5589 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5590 /* status queue overflow or GHI */
5591 /* just clear the interrupt */
5592 outb(Isr, ha->io_addr + IPS_REG_HISR);
5593 }
5594
5595 return (0);
5596}
5597
5598/****************************************************************************/
5599/* */
5600/* Routine Name: ips_isintr_copperhead_memio */
5601/* */
5602/* Routine Description: */
5603/* */
5604/* Test to see if an interrupt is for us */
5605/* */
5606/****************************************************************************/
5607static int
5608ips_isintr_copperhead_memio(ips_ha_t * ha)
5609{
5610 uint8_t Isr;
5611
5612 METHOD_TRACE("ips_isintr_memio", 2);
5613
5614 Isr = readb(ha->mem_ptr + IPS_REG_HISR);
5615
5616 if (Isr == 0xFF)
5617 /* ?!?! Nothing really there */
5618 return (0);
5619
5620 if (Isr & IPS_BIT_SCE)
5621 return (1);
5622 else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
5623 /* status queue overflow or GHI */
5624 /* just clear the interrupt */
5625 writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
5626 }
5627
5628 return (0);
5629}
5630
5631/****************************************************************************/
5632/* */
5633/* Routine Name: ips_isintr_morpheus */
5634/* */
5635/* Routine Description: */
5636/* */
5637/* Test to see if an interrupt is for us */
5638/* */
5639/****************************************************************************/
5640static int
5641ips_isintr_morpheus(ips_ha_t * ha)
5642{
5643 uint32_t Isr;
5644
5645 METHOD_TRACE("ips_isintr_morpheus", 2);
5646
5647 Isr = readl(ha->mem_ptr + IPS_REG_I2O_HIR);
5648
5649 if (Isr & IPS_BIT_I2O_OPQI)
5650 return (1);
5651 else
5652 return (0);
5653}
5654
5655/****************************************************************************/
5656/* */
5657/* Routine Name: ips_wait */
5658/* */
5659/* Routine Description: */
5660/* */
5661/* Wait for a command to complete */
5662/* */
5663/****************************************************************************/
5664static int
5665ips_wait(ips_ha_t * ha, int time, int intr)
5666{
5667 int ret;
5668 int done;
5669
5670 METHOD_TRACE("ips_wait", 1);
5671
5672 ret = IPS_FAILURE;
5673 done = FALSE;
5674
5675 time *= IPS_ONE_SEC; /* convert seconds */
5676
5677 while ((time > 0) && (!done)) {
5678 if (intr == IPS_INTR_ON) {
5679 if (ha->waitflag == FALSE) {
5680 ret = IPS_SUCCESS;
5681 done = TRUE;
5682 break;
5683 }
5684 } else if (intr == IPS_INTR_IORL) {
5685 if (ha->waitflag == FALSE) {
5686 /*
5687 * controller generated an interrupt to
5688 * acknowledge completion of the command
5689 * and ips_intr() has serviced the interrupt.
5690 */
5691 ret = IPS_SUCCESS;
5692 done = TRUE;
5693 break;
5694 }
5695
5696 /*
5697 * NOTE: we already have the io_request_lock so
5698 * even if we get an interrupt it won't get serviced
5699 * until after we finish.
5700 */
5701
5702 (*ha->func.intr) (ha);
5703 }
5704
5705 /* This looks like a very evil loop, but it only does this during start-up */
5706 udelay(1000);
5707 time--;
5708 }
5709
5710 return (ret);
5711}
5712
5713/****************************************************************************/
5714/* */
5715/* Routine Name: ips_write_driver_status */
5716/* */
5717/* Routine Description: */
5718/* */
5719/* Write OS/Driver version to Page 5 of the nvram on the controller */
5720/* */
5721/****************************************************************************/
5722static int
5723ips_write_driver_status(ips_ha_t * ha, int intr)
5724{
5725 METHOD_TRACE("ips_write_driver_status", 1);
5726
5727 if (!ips_readwrite_page5(ha, FALSE, intr)) {
5728 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5729 "unable to read NVRAM page 5.\n");
5730
5731 return (0);
5732 }
5733
5734 /* check to make sure the page has a valid */
5735 /* signature */
5736 if (le32_to_cpu(ha->nvram->signature) != IPS_NVRAM_P5_SIG) {
5737 DEBUG_VAR(1,
5738 "(%s%d) NVRAM page 5 has an invalid signature: %X.",
5739 ips_name, ha->host_num, ha->nvram->signature);
5740 ha->nvram->signature = IPS_NVRAM_P5_SIG;
5741 }
5742
5743 DEBUG_VAR(2,
5744 "(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.",
5745 ips_name, ha->host_num, le16_to_cpu(ha->nvram->adapter_type),
5746 ha->nvram->adapter_slot, ha->nvram->bios_high[0],
5747 ha->nvram->bios_high[1], ha->nvram->bios_high[2],
5748 ha->nvram->bios_high[3], ha->nvram->bios_low[0],
5749 ha->nvram->bios_low[1], ha->nvram->bios_low[2],
5750 ha->nvram->bios_low[3]);
5751
5752 ips_get_bios_version(ha, intr);
5753
5754 /* change values (as needed) */
5755 ha->nvram->operating_system = IPS_OS_LINUX;
5756 ha->nvram->adapter_type = ha->ad_type;
5757 strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
5758 strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
5759 strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
5760 strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
5761
Jack Hammera60768e2005-11-03 09:46:00 -05005762 ha->nvram->versioning = 0; /* Indicate the Driver Does Not Support Versioning */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763
5764 /* now update the page */
5765 if (!ips_readwrite_page5(ha, TRUE, intr)) {
5766 IPS_PRINTK(KERN_WARNING, ha->pcidev,
5767 "unable to write NVRAM page 5.\n");
5768
5769 return (0);
5770 }
5771
5772 /* IF NVRAM Page 5 is OK, Use it for Slot Number Info Because Linux Doesn't Do Slots */
5773 ha->slot_num = ha->nvram->adapter_slot;
5774
5775 return (1);
5776}
5777
5778/****************************************************************************/
5779/* */
5780/* Routine Name: ips_read_adapter_status */
5781/* */
5782/* Routine Description: */
5783/* */
5784/* Do an Inquiry command to the adapter */
5785/* */
5786/****************************************************************************/
5787static int
5788ips_read_adapter_status(ips_ha_t * ha, int intr)
5789{
5790 ips_scb_t *scb;
5791 int ret;
5792
5793 METHOD_TRACE("ips_read_adapter_status", 1);
5794
5795 scb = &ha->scbs[ha->max_cmds - 1];
5796
5797 ips_init_scb(ha, scb);
5798
5799 scb->timeout = ips_cmd_timeout;
5800 scb->cdb[0] = IPS_CMD_ENQUIRY;
5801
5802 scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
5803 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5804 scb->cmd.basic_io.sg_count = 0;
5805 scb->cmd.basic_io.lba = 0;
5806 scb->cmd.basic_io.sector_count = 0;
5807 scb->cmd.basic_io.log_drv = 0;
5808 scb->data_len = sizeof (*ha->enq);
5809 scb->cmd.basic_io.sg_addr = ha->enq_busaddr;
5810
5811 /* send command */
5812 if (((ret =
5813 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5814 || (ret == IPS_SUCCESS_IMM)
5815 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5816 return (0);
5817
5818 return (1);
5819}
5820
5821/****************************************************************************/
5822/* */
5823/* Routine Name: ips_read_subsystem_parameters */
5824/* */
5825/* Routine Description: */
5826/* */
5827/* Read subsystem parameters from the adapter */
5828/* */
5829/****************************************************************************/
5830static int
5831ips_read_subsystem_parameters(ips_ha_t * ha, int intr)
5832{
5833 ips_scb_t *scb;
5834 int ret;
5835
5836 METHOD_TRACE("ips_read_subsystem_parameters", 1);
5837
5838 scb = &ha->scbs[ha->max_cmds - 1];
5839
5840 ips_init_scb(ha, scb);
5841
5842 scb->timeout = ips_cmd_timeout;
5843 scb->cdb[0] = IPS_CMD_GET_SUBSYS;
5844
5845 scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS;
5846 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5847 scb->cmd.basic_io.sg_count = 0;
5848 scb->cmd.basic_io.lba = 0;
5849 scb->cmd.basic_io.sector_count = 0;
5850 scb->cmd.basic_io.log_drv = 0;
5851 scb->data_len = sizeof (*ha->subsys);
5852 scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
5853
5854 /* send command */
5855 if (((ret =
5856 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5857 || (ret == IPS_SUCCESS_IMM)
5858 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
5859 return (0);
5860
5861 memcpy(ha->subsys, ha->ioctl_data, sizeof(*ha->subsys));
5862 return (1);
5863}
5864
5865/****************************************************************************/
5866/* */
5867/* Routine Name: ips_read_config */
5868/* */
5869/* Routine Description: */
5870/* */
5871/* Read the configuration on the adapter */
5872/* */
5873/****************************************************************************/
5874static int
5875ips_read_config(ips_ha_t * ha, int intr)
5876{
5877 ips_scb_t *scb;
5878 int i;
5879 int ret;
5880
5881 METHOD_TRACE("ips_read_config", 1);
5882
5883 /* set defaults for initiator IDs */
5884 for (i = 0; i < 4; i++)
5885 ha->conf->init_id[i] = 7;
5886
5887 scb = &ha->scbs[ha->max_cmds - 1];
5888
5889 ips_init_scb(ha, scb);
5890
5891 scb->timeout = ips_cmd_timeout;
5892 scb->cdb[0] = IPS_CMD_READ_CONF;
5893
5894 scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF;
5895 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
5896 scb->data_len = sizeof (*ha->conf);
5897 scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
5898
5899 /* send command */
5900 if (((ret =
5901 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5902 || (ret == IPS_SUCCESS_IMM)
5903 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5904
5905 memset(ha->conf, 0, sizeof (IPS_CONF));
5906
5907 /* reset initiator IDs */
5908 for (i = 0; i < 4; i++)
5909 ha->conf->init_id[i] = 7;
5910
5911 /* Allow Completed with Errors, so JCRM can access the Adapter to fix the problems */
5912 if ((scb->basic_status & IPS_GSC_STATUS_MASK) ==
5913 IPS_CMD_CMPLT_WERROR)
5914 return (1);
5915
5916 return (0);
5917 }
Jeff Garzik2f277d62007-12-13 16:14:08 -08005918
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919 memcpy(ha->conf, ha->ioctl_data, sizeof(*ha->conf));
5920 return (1);
5921}
5922
5923/****************************************************************************/
5924/* */
5925/* Routine Name: ips_readwrite_page5 */
5926/* */
5927/* Routine Description: */
5928/* */
5929/* Read nvram page 5 from the adapter */
5930/* */
5931/****************************************************************************/
5932static int
5933ips_readwrite_page5(ips_ha_t * ha, int write, int intr)
5934{
5935 ips_scb_t *scb;
5936 int ret;
5937
5938 METHOD_TRACE("ips_readwrite_page5", 1);
5939
5940 scb = &ha->scbs[ha->max_cmds - 1];
5941
5942 ips_init_scb(ha, scb);
5943
5944 scb->timeout = ips_cmd_timeout;
5945 scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE;
5946
5947 scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE;
5948 scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
5949 scb->cmd.nvram.page = 5;
5950 scb->cmd.nvram.write = write;
5951 scb->cmd.nvram.reserved = 0;
5952 scb->cmd.nvram.reserved2 = 0;
5953 scb->data_len = sizeof (*ha->nvram);
5954 scb->cmd.nvram.buffer_addr = ha->ioctl_busaddr;
5955 if (write)
5956 memcpy(ha->ioctl_data, ha->nvram, sizeof(*ha->nvram));
Jeff Garzik2f277d62007-12-13 16:14:08 -08005957
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958 /* issue the command */
5959 if (((ret =
5960 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
5961 || (ret == IPS_SUCCESS_IMM)
5962 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
5963
5964 memset(ha->nvram, 0, sizeof (IPS_NVRAM_P5));
5965
5966 return (0);
5967 }
5968 if (!write)
5969 memcpy(ha->nvram, ha->ioctl_data, sizeof(*ha->nvram));
5970 return (1);
5971}
5972
5973/****************************************************************************/
5974/* */
5975/* Routine Name: ips_clear_adapter */
5976/* */
5977/* Routine Description: */
5978/* */
5979/* Clear the stripe lock tables */
5980/* */
5981/****************************************************************************/
5982static int
5983ips_clear_adapter(ips_ha_t * ha, int intr)
5984{
5985 ips_scb_t *scb;
5986 int ret;
5987
5988 METHOD_TRACE("ips_clear_adapter", 1);
5989
5990 scb = &ha->scbs[ha->max_cmds - 1];
5991
5992 ips_init_scb(ha, scb);
5993
5994 scb->timeout = ips_reset_timeout;
5995 scb->cdb[0] = IPS_CMD_CONFIG_SYNC;
5996
5997 scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC;
5998 scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
5999 scb->cmd.config_sync.channel = 0;
6000 scb->cmd.config_sync.source_target = IPS_POCL;
6001 scb->cmd.config_sync.reserved = 0;
6002 scb->cmd.config_sync.reserved2 = 0;
6003 scb->cmd.config_sync.reserved3 = 0;
6004
6005 /* issue command */
6006 if (((ret =
6007 ips_send_wait(ha, scb, ips_reset_timeout, intr)) == IPS_FAILURE)
6008 || (ret == IPS_SUCCESS_IMM)
6009 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
6010 return (0);
6011
6012 /* send unlock stripe command */
6013 ips_init_scb(ha, scb);
6014
6015 scb->cdb[0] = IPS_CMD_ERROR_TABLE;
6016 scb->timeout = ips_reset_timeout;
6017
6018 scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE;
6019 scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
6020 scb->cmd.unlock_stripe.log_drv = 0;
6021 scb->cmd.unlock_stripe.control = IPS_CSL;
6022 scb->cmd.unlock_stripe.reserved = 0;
6023 scb->cmd.unlock_stripe.reserved2 = 0;
6024 scb->cmd.unlock_stripe.reserved3 = 0;
6025
6026 /* issue command */
6027 if (((ret =
6028 ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
6029 || (ret == IPS_SUCCESS_IMM)
6030 || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
6031 return (0);
6032
6033 return (1);
6034}
6035
6036/****************************************************************************/
6037/* */
6038/* Routine Name: ips_ffdc_reset */
6039/* */
6040/* Routine Description: */
6041/* */
6042/* FFDC: write reset info */
6043/* */
6044/****************************************************************************/
6045static void
6046ips_ffdc_reset(ips_ha_t * ha, int intr)
6047{
6048 ips_scb_t *scb;
6049
6050 METHOD_TRACE("ips_ffdc_reset", 1);
6051
6052 scb = &ha->scbs[ha->max_cmds - 1];
6053
6054 ips_init_scb(ha, scb);
6055
6056 scb->timeout = ips_cmd_timeout;
6057 scb->cdb[0] = IPS_CMD_FFDC;
6058 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6059 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6060 scb->cmd.ffdc.reset_count = ha->reset_count;
6061 scb->cmd.ffdc.reset_type = 0x80;
6062
6063 /* convert time to what the card wants */
6064 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6065
6066 /* issue command */
6067 ips_send_wait(ha, scb, ips_cmd_timeout, intr);
6068}
6069
6070/****************************************************************************/
6071/* */
6072/* Routine Name: ips_ffdc_time */
6073/* */
6074/* Routine Description: */
6075/* */
6076/* FFDC: write time info */
6077/* */
6078/****************************************************************************/
6079static void
6080ips_ffdc_time(ips_ha_t * ha)
6081{
6082 ips_scb_t *scb;
6083
6084 METHOD_TRACE("ips_ffdc_time", 1);
6085
6086 DEBUG_VAR(1, "(%s%d) Sending time update.", ips_name, ha->host_num);
6087
6088 scb = &ha->scbs[ha->max_cmds - 1];
6089
6090 ips_init_scb(ha, scb);
6091
6092 scb->timeout = ips_cmd_timeout;
6093 scb->cdb[0] = IPS_CMD_FFDC;
6094 scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
6095 scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
6096 scb->cmd.ffdc.reset_count = 0;
6097 scb->cmd.ffdc.reset_type = 0;
6098
6099 /* convert time to what the card wants */
6100 ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
6101
6102 /* issue command */
6103 ips_send_wait(ha, scb, ips_cmd_timeout, IPS_FFDC);
6104}
6105
6106/****************************************************************************/
6107/* */
6108/* Routine Name: ips_fix_ffdc_time */
6109/* */
6110/* Routine Description: */
6111/* Adjust time_t to what the card wants */
6112/* */
6113/****************************************************************************/
6114static void
6115ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time_t current_time)
6116{
6117 long days;
6118 long rem;
6119 int i;
6120 int year;
6121 int yleap;
6122 int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
6123 int month_lengths[12][2] = { {31, 31},
6124 {28, 29},
6125 {31, 31},
6126 {30, 30},
6127 {31, 31},
6128 {30, 30},
6129 {31, 31},
6130 {31, 31},
6131 {30, 30},
6132 {31, 31},
6133 {30, 30},
6134 {31, 31}
6135 };
6136
6137 METHOD_TRACE("ips_fix_ffdc_time", 1);
6138
6139 days = current_time / IPS_SECS_DAY;
6140 rem = current_time % IPS_SECS_DAY;
6141
6142 scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
6143 rem = rem % IPS_SECS_HOUR;
6144 scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
6145 scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
6146
6147 year = IPS_EPOCH_YEAR;
6148 while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
6149 int newy;
6150
6151 newy = year + (days / IPS_DAYS_NORMAL_YEAR);
6152 if (days < 0)
6153 --newy;
6154 days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
6155 IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
6156 IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
6157 year = newy;
6158 }
6159
6160 scb->cmd.ffdc.yearH = year / 100;
6161 scb->cmd.ffdc.yearL = year % 100;
6162
6163 for (i = 0; days >= month_lengths[i][yleap]; ++i)
6164 days -= month_lengths[i][yleap];
6165
6166 scb->cmd.ffdc.month = i + 1;
6167 scb->cmd.ffdc.day = days + 1;
6168}
6169
6170/****************************************************************************
6171 * BIOS Flash Routines *
6172 ****************************************************************************/
6173
6174/****************************************************************************/
6175/* */
6176/* Routine Name: ips_erase_bios */
6177/* */
6178/* Routine Description: */
6179/* Erase the BIOS on the adapter */
6180/* */
6181/****************************************************************************/
6182static int
6183ips_erase_bios(ips_ha_t * ha)
6184{
6185 int timeout;
6186 uint8_t status = 0;
6187
6188 METHOD_TRACE("ips_erase_bios", 1);
6189
6190 status = 0;
6191
6192 /* Clear the status register */
6193 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006194 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195 udelay(25); /* 25 us */
6196
6197 outb(0x50, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006198 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199 udelay(25); /* 25 us */
6200
6201 /* Erase Setup */
6202 outb(0x20, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006203 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204 udelay(25); /* 25 us */
6205
6206 /* Erase Confirm */
6207 outb(0xD0, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006208 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209 udelay(25); /* 25 us */
6210
6211 /* Erase Status */
6212 outb(0x70, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006213 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214 udelay(25); /* 25 us */
6215
6216 timeout = 80000; /* 80 seconds */
6217
6218 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006219 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220 outl(0, ha->io_addr + IPS_REG_FLAP);
6221 udelay(25); /* 25 us */
6222 }
6223
6224 status = inb(ha->io_addr + IPS_REG_FLDP);
6225
6226 if (status & 0x80)
6227 break;
6228
6229 MDELAY(1);
6230 timeout--;
6231 }
6232
6233 /* check for timeout */
6234 if (timeout <= 0) {
6235 /* timeout */
6236
6237 /* try to suspend the erase */
6238 outb(0xB0, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006239 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006240 udelay(25); /* 25 us */
6241
6242 /* wait for 10 seconds */
6243 timeout = 10000;
6244 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006245 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246 outl(0, ha->io_addr + IPS_REG_FLAP);
6247 udelay(25); /* 25 us */
6248 }
6249
6250 status = inb(ha->io_addr + IPS_REG_FLDP);
6251
6252 if (status & 0xC0)
6253 break;
6254
6255 MDELAY(1);
6256 timeout--;
6257 }
6258
6259 return (1);
6260 }
6261
6262 /* check for valid VPP */
6263 if (status & 0x08)
6264 /* VPP failure */
6265 return (1);
6266
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02006267 /* check for successful flash */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006268 if (status & 0x30)
6269 /* sequence error */
6270 return (1);
6271
6272 /* Otherwise, we were successful */
6273 /* clear status */
6274 outb(0x50, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006275 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276 udelay(25); /* 25 us */
6277
6278 /* enable reads */
6279 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006280 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281 udelay(25); /* 25 us */
6282
6283 return (0);
6284}
6285
6286/****************************************************************************/
6287/* */
6288/* Routine Name: ips_erase_bios_memio */
6289/* */
6290/* Routine Description: */
6291/* Erase the BIOS on the adapter */
6292/* */
6293/****************************************************************************/
6294static int
6295ips_erase_bios_memio(ips_ha_t * ha)
6296{
6297 int timeout;
6298 uint8_t status;
6299
6300 METHOD_TRACE("ips_erase_bios_memio", 1);
6301
6302 status = 0;
6303
6304 /* Clear the status register */
6305 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006306 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307 udelay(25); /* 25 us */
6308
6309 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006310 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 udelay(25); /* 25 us */
6312
6313 /* Erase Setup */
6314 writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006315 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316 udelay(25); /* 25 us */
6317
6318 /* Erase Confirm */
6319 writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006320 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321 udelay(25); /* 25 us */
6322
6323 /* Erase Status */
6324 writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006325 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006326 udelay(25); /* 25 us */
6327
6328 timeout = 80000; /* 80 seconds */
6329
6330 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006331 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6333 udelay(25); /* 25 us */
6334 }
6335
6336 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6337
6338 if (status & 0x80)
6339 break;
6340
6341 MDELAY(1);
6342 timeout--;
6343 }
6344
6345 /* check for timeout */
6346 if (timeout <= 0) {
6347 /* timeout */
6348
6349 /* try to suspend the erase */
6350 writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006351 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006352 udelay(25); /* 25 us */
6353
6354 /* wait for 10 seconds */
6355 timeout = 10000;
6356 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006357 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006358 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6359 udelay(25); /* 25 us */
6360 }
6361
6362 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6363
6364 if (status & 0xC0)
6365 break;
6366
6367 MDELAY(1);
6368 timeout--;
6369 }
6370
6371 return (1);
6372 }
6373
6374 /* check for valid VPP */
6375 if (status & 0x08)
6376 /* VPP failure */
6377 return (1);
6378
Andreas Mohrd6e05ed2006-06-26 18:35:02 +02006379 /* check for successful flash */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380 if (status & 0x30)
6381 /* sequence error */
6382 return (1);
6383
6384 /* Otherwise, we were successful */
6385 /* clear status */
6386 writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006387 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006388 udelay(25); /* 25 us */
6389
6390 /* enable reads */
6391 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006392 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393 udelay(25); /* 25 us */
6394
6395 return (0);
6396}
6397
6398/****************************************************************************/
6399/* */
6400/* Routine Name: ips_program_bios */
6401/* */
6402/* Routine Description: */
6403/* Program the BIOS on the adapter */
6404/* */
6405/****************************************************************************/
6406static int
6407ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6408 uint32_t offset)
6409{
6410 int i;
6411 int timeout;
6412 uint8_t status = 0;
6413
6414 METHOD_TRACE("ips_program_bios", 1);
6415
6416 status = 0;
6417
6418 for (i = 0; i < buffersize; i++) {
6419 /* write a byte */
6420 outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006421 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006422 udelay(25); /* 25 us */
6423
6424 outb(0x40, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006425 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426 udelay(25); /* 25 us */
6427
6428 outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006429 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006430 udelay(25); /* 25 us */
6431
6432 /* wait up to one second */
6433 timeout = 1000;
6434 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006435 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436 outl(0, ha->io_addr + IPS_REG_FLAP);
6437 udelay(25); /* 25 us */
6438 }
6439
6440 status = inb(ha->io_addr + IPS_REG_FLDP);
6441
6442 if (status & 0x80)
6443 break;
6444
6445 MDELAY(1);
6446 timeout--;
6447 }
6448
6449 if (timeout == 0) {
6450 /* timeout error */
6451 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006452 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006453 udelay(25); /* 25 us */
6454
6455 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006456 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457 udelay(25); /* 25 us */
6458
6459 return (1);
6460 }
6461
6462 /* check the status */
6463 if (status & 0x18) {
6464 /* programming error */
6465 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006466 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006467 udelay(25); /* 25 us */
6468
6469 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006470 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006471 udelay(25); /* 25 us */
6472
6473 return (1);
6474 }
6475 } /* end for */
6476
6477 /* Enable reading */
6478 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006479 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006480 udelay(25); /* 25 us */
6481
6482 outb(0xFF, ha->io_addr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006483 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484 udelay(25); /* 25 us */
6485
6486 return (0);
6487}
6488
6489/****************************************************************************/
6490/* */
6491/* Routine Name: ips_program_bios_memio */
6492/* */
6493/* Routine Description: */
6494/* Program the BIOS on the adapter */
6495/* */
6496/****************************************************************************/
6497static int
6498ips_program_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6499 uint32_t offset)
6500{
6501 int i;
6502 int timeout;
6503 uint8_t status = 0;
6504
6505 METHOD_TRACE("ips_program_bios_memio", 1);
6506
6507 status = 0;
6508
6509 for (i = 0; i < buffersize; i++) {
6510 /* write a byte */
6511 writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006512 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513 udelay(25); /* 25 us */
6514
6515 writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006516 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006517 udelay(25); /* 25 us */
6518
6519 writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006520 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006521 udelay(25); /* 25 us */
6522
6523 /* wait up to one second */
6524 timeout = 1000;
6525 while (timeout > 0) {
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006526 if (ha->pcidev->revision == IPS_REVID_TROMBONE64) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527 writel(0, ha->mem_ptr + IPS_REG_FLAP);
6528 udelay(25); /* 25 us */
6529 }
6530
6531 status = readb(ha->mem_ptr + IPS_REG_FLDP);
6532
6533 if (status & 0x80)
6534 break;
6535
6536 MDELAY(1);
6537 timeout--;
6538 }
6539
6540 if (timeout == 0) {
6541 /* timeout error */
6542 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006543 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006544 udelay(25); /* 25 us */
6545
6546 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006547 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006548 udelay(25); /* 25 us */
6549
6550 return (1);
6551 }
6552
6553 /* check the status */
6554 if (status & 0x18) {
6555 /* programming error */
6556 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006557 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006558 udelay(25); /* 25 us */
6559
6560 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006561 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006562 udelay(25); /* 25 us */
6563
6564 return (1);
6565 }
6566 } /* end for */
6567
6568 /* Enable reading */
6569 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006570 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006571 udelay(25); /* 25 us */
6572
6573 writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006574 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006575 udelay(25); /* 25 us */
6576
6577 return (0);
6578}
6579
6580/****************************************************************************/
6581/* */
6582/* Routine Name: ips_verify_bios */
6583/* */
6584/* Routine Description: */
6585/* Verify the BIOS on the adapter */
6586/* */
6587/****************************************************************************/
6588static int
6589ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6590 uint32_t offset)
6591{
6592 uint8_t checksum;
6593 int i;
6594
6595 METHOD_TRACE("ips_verify_bios", 1);
6596
6597 /* test 1st byte */
6598 outl(0, ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006599 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006600 udelay(25); /* 25 us */
6601
6602 if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
6603 return (1);
6604
6605 outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006606 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006607 udelay(25); /* 25 us */
6608 if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
6609 return (1);
6610
6611 checksum = 0xff;
6612 for (i = 2; i < buffersize; i++) {
6613
6614 outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006615 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006616 udelay(25); /* 25 us */
6617
6618 checksum = (uint8_t) checksum + inb(ha->io_addr + IPS_REG_FLDP);
6619 }
6620
6621 if (checksum != 0)
6622 /* failure */
6623 return (1);
6624 else
6625 /* success */
6626 return (0);
6627}
6628
6629/****************************************************************************/
6630/* */
6631/* Routine Name: ips_verify_bios_memio */
6632/* */
6633/* Routine Description: */
6634/* Verify the BIOS on the adapter */
6635/* */
6636/****************************************************************************/
6637static int
6638ips_verify_bios_memio(ips_ha_t * ha, char *buffer, uint32_t buffersize,
6639 uint32_t offset)
6640{
6641 uint8_t checksum;
6642 int i;
6643
6644 METHOD_TRACE("ips_verify_bios_memio", 1);
6645
6646 /* test 1st byte */
6647 writel(0, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006648 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006649 udelay(25); /* 25 us */
6650
6651 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
6652 return (1);
6653
6654 writel(1, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006655 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656 udelay(25); /* 25 us */
6657 if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
6658 return (1);
6659
6660 checksum = 0xff;
6661 for (i = 2; i < buffersize; i++) {
6662
6663 writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006664 if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006665 udelay(25); /* 25 us */
6666
6667 checksum =
6668 (uint8_t) checksum + readb(ha->mem_ptr + IPS_REG_FLDP);
6669 }
6670
6671 if (checksum != 0)
6672 /* failure */
6673 return (1);
6674 else
6675 /* success */
6676 return (0);
6677}
6678
Linus Torvalds1da177e2005-04-16 15:20:36 -07006679/****************************************************************************/
6680/* */
6681/* Routine Name: ips_abort_init */
6682/* */
6683/* Routine Description: */
6684/* cleanup routine for a failed adapter initialization */
6685/****************************************************************************/
6686static int
6687ips_abort_init(ips_ha_t * ha, int index)
6688{
6689 ha->active = 0;
6690 ips_free(ha);
6691 ips_ha[index] = NULL;
6692 ips_sh[index] = NULL;
6693 return -1;
6694}
6695
6696/****************************************************************************/
6697/* */
6698/* Routine Name: ips_shift_controllers */
6699/* */
6700/* Routine Description: */
6701/* helper function for ordering adapters */
6702/****************************************************************************/
6703static void
6704ips_shift_controllers(int lowindex, int highindex)
6705{
6706 ips_ha_t *ha_sav = ips_ha[highindex];
6707 struct Scsi_Host *sh_sav = ips_sh[highindex];
6708 int i;
6709
6710 for (i = highindex; i > lowindex; i--) {
6711 ips_ha[i] = ips_ha[i - 1];
6712 ips_sh[i] = ips_sh[i - 1];
6713 ips_ha[i]->host_num = i;
6714 }
6715 ha_sav->host_num = lowindex;
6716 ips_ha[lowindex] = ha_sav;
6717 ips_sh[lowindex] = sh_sav;
6718}
6719
6720/****************************************************************************/
6721/* */
6722/* Routine Name: ips_order_controllers */
6723/* */
6724/* Routine Description: */
6725/* place controllers is the "proper" boot order */
6726/****************************************************************************/
6727static void
6728ips_order_controllers(void)
6729{
6730 int i, j, tmp, position = 0;
6731 IPS_NVRAM_P5 *nvram;
6732 if (!ips_ha[0])
6733 return;
6734 nvram = ips_ha[0]->nvram;
6735
6736 if (nvram->adapter_order[0]) {
6737 for (i = 1; i <= nvram->adapter_order[0]; i++) {
6738 for (j = position; j < ips_num_controllers; j++) {
6739 switch (ips_ha[j]->ad_type) {
6740 case IPS_ADTYPE_SERVERAID6M:
6741 case IPS_ADTYPE_SERVERAID7M:
6742 if (nvram->adapter_order[i] == 'M') {
6743 ips_shift_controllers(position,
6744 j);
6745 position++;
6746 }
6747 break;
6748 case IPS_ADTYPE_SERVERAID4L:
6749 case IPS_ADTYPE_SERVERAID4M:
6750 case IPS_ADTYPE_SERVERAID4MX:
6751 case IPS_ADTYPE_SERVERAID4LX:
6752 if (nvram->adapter_order[i] == 'N') {
6753 ips_shift_controllers(position,
6754 j);
6755 position++;
6756 }
6757 break;
6758 case IPS_ADTYPE_SERVERAID6I:
6759 case IPS_ADTYPE_SERVERAID5I2:
6760 case IPS_ADTYPE_SERVERAID5I1:
6761 case IPS_ADTYPE_SERVERAID7k:
6762 if (nvram->adapter_order[i] == 'S') {
6763 ips_shift_controllers(position,
6764 j);
6765 position++;
6766 }
6767 break;
6768 case IPS_ADTYPE_SERVERAID:
6769 case IPS_ADTYPE_SERVERAID2:
6770 case IPS_ADTYPE_NAVAJO:
6771 case IPS_ADTYPE_KIOWA:
6772 case IPS_ADTYPE_SERVERAID3L:
6773 case IPS_ADTYPE_SERVERAID3:
6774 case IPS_ADTYPE_SERVERAID4H:
6775 if (nvram->adapter_order[i] == 'A') {
6776 ips_shift_controllers(position,
6777 j);
6778 position++;
6779 }
6780 break;
6781 default:
6782 break;
6783 }
6784 }
6785 }
6786 /* if adapter_order[0], then ordering is complete */
6787 return;
6788 }
6789 /* old bios, use older ordering */
6790 tmp = 0;
6791 for (i = position; i < ips_num_controllers; i++) {
6792 if (ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID5I2 ||
6793 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID5I1) {
6794 ips_shift_controllers(position, i);
6795 position++;
6796 tmp = 1;
6797 }
6798 }
6799 /* if there were no 5I cards, then don't do any extra ordering */
6800 if (!tmp)
6801 return;
6802 for (i = position; i < ips_num_controllers; i++) {
6803 if (ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4L ||
6804 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4M ||
6805 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4LX ||
6806 ips_ha[i]->ad_type == IPS_ADTYPE_SERVERAID4MX) {
6807 ips_shift_controllers(position, i);
6808 position++;
6809 }
6810 }
6811
6812 return;
6813}
6814
6815/****************************************************************************/
6816/* */
6817/* Routine Name: ips_register_scsi */
6818/* */
6819/* Routine Description: */
6820/* perform any registration and setup with the scsi layer */
6821/****************************************************************************/
6822static int
6823ips_register_scsi(int index)
6824{
6825 struct Scsi_Host *sh;
6826 ips_ha_t *ha, *oldha = ips_ha[index];
6827 sh = scsi_host_alloc(&ips_driver_template, sizeof (ips_ha_t));
6828 if (!sh) {
6829 IPS_PRINTK(KERN_WARNING, oldha->pcidev,
6830 "Unable to register controller with SCSI subsystem\n");
6831 return -1;
6832 }
6833 ha = IPS_HA(sh);
6834 memcpy(ha, oldha, sizeof (ips_ha_t));
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006835 free_irq(oldha->pcidev->irq, oldha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836 /* Install the interrupt handler with the new ha */
Jeff Garzik8a694cc2007-12-13 16:14:07 -08006837 if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838 IPS_PRINTK(KERN_WARNING, ha->pcidev,
6839 "Unable to install interrupt handler\n");
6840 scsi_host_put(sh);
6841 return -1;
6842 }
6843
6844 kfree(oldha);
6845 ips_sh[index] = sh;
6846 ips_ha[index] = ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006847
6848 /* Store away needed values for later use */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006849 sh->unique_id = (ha->io_addr) ? ha->io_addr : ha->mem_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006850 sh->sg_tablesize = sh->hostt->sg_tablesize;
6851 sh->can_queue = sh->hostt->can_queue;
6852 sh->cmd_per_lun = sh->hostt->cmd_per_lun;
6853 sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
6854 sh->use_clustering = sh->hostt->use_clustering;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006855 sh->max_sectors = 128;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006856
6857 sh->max_id = ha->ntargets;
6858 sh->max_lun = ha->nlun;
6859 sh->max_channel = ha->nbus - 1;
6860 sh->can_queue = ha->max_cmds - 1;
6861
Adrian Bunkc6a6c812007-05-23 14:41:46 -07006862 scsi_add_host(sh, NULL);
6863 scsi_scan_host(sh);
6864
Linus Torvalds1da177e2005-04-16 15:20:36 -07006865 return 0;
6866}
6867
6868/*---------------------------------------------------------------------------*/
6869/* Routine Name: ips_remove_device */
6870/* */
6871/* Routine Description: */
6872/* Remove one Adapter ( Hot Plugging ) */
6873/*---------------------------------------------------------------------------*/
6874static void __devexit
6875ips_remove_device(struct pci_dev *pci_dev)
6876{
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08006877 struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006878
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08006879 pci_set_drvdata(pci_dev, NULL);
6880
6881 ips_release(sh);
6882
6883 pci_release_regions(pci_dev);
6884 pci_disable_device(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006885}
6886
6887/****************************************************************************/
6888/* */
6889/* Routine Name: ips_module_init */
6890/* */
6891/* Routine Description: */
6892/* function called on module load */
6893/****************************************************************************/
6894static int __init
6895ips_module_init(void)
6896{
Alan Cox02a0fa62006-09-25 23:45:51 +01006897 if (pci_register_driver(&ips_pci_driver) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006898 return -ENODEV;
6899 ips_driver_template.module = THIS_MODULE;
6900 ips_order_controllers();
Adrian Bunkc6a6c812007-05-23 14:41:46 -07006901 if (!ips_detect(&ips_driver_template)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006902 pci_unregister_driver(&ips_pci_driver);
6903 return -ENODEV;
6904 }
6905 register_reboot_notifier(&ips_notifier);
6906 return 0;
6907}
6908
6909/****************************************************************************/
6910/* */
6911/* Routine Name: ips_module_exit */
6912/* */
6913/* Routine Description: */
6914/* function called on module unload */
6915/****************************************************************************/
6916static void __exit
6917ips_module_exit(void)
6918{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919 pci_unregister_driver(&ips_pci_driver);
6920 unregister_reboot_notifier(&ips_notifier);
6921}
6922
6923module_init(ips_module_init);
6924module_exit(ips_module_exit);
6925
6926/*---------------------------------------------------------------------------*/
6927/* Routine Name: ips_insert_device */
6928/* */
6929/* Routine Description: */
6930/* Add One Adapter ( Hot Plug ) */
6931/* */
6932/* Return Value: */
6933/* 0 if Successful, else non-zero */
6934/*---------------------------------------------------------------------------*/
6935static int __devinit
6936ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
6937{
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08006938 int index = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006939 int rc;
6940
6941 METHOD_TRACE("ips_insert_device", 1);
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08006942 rc = pci_enable_device(pci_dev);
6943 if (rc)
6944 return rc;
6945
6946 rc = pci_request_regions(pci_dev, "ips");
6947 if (rc)
6948 goto err_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006949
6950 rc = ips_init_phase1(pci_dev, &index);
6951 if (rc == SUCCESS)
6952 rc = ips_init_phase2(index);
6953
6954 if (ips_hotplug)
6955 if (ips_register_scsi(index)) {
6956 ips_free(ips_ha[index]);
6957 rc = -1;
6958 }
6959
6960 if (rc == SUCCESS)
6961 ips_num_controllers++;
6962
6963 ips_next_controller = ips_num_controllers;
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08006964
6965 if (rc < 0) {
6966 rc = -ENODEV;
6967 goto err_out_regions;
6968 }
6969
6970 pci_set_drvdata(pci_dev, ips_sh[index]);
6971 return 0;
6972
6973err_out_regions:
6974 pci_release_regions(pci_dev);
6975err_out:
6976 pci_disable_device(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977 return rc;
6978}
6979
6980/*---------------------------------------------------------------------------*/
6981/* Routine Name: ips_init_phase1 */
6982/* */
6983/* Routine Description: */
6984/* Adapter Initialization */
6985/* */
6986/* Return Value: */
6987/* 0 if Successful, else non-zero */
6988/*---------------------------------------------------------------------------*/
6989static int
6990ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
6991{
6992 ips_ha_t *ha;
6993 uint32_t io_addr;
6994 uint32_t mem_addr;
6995 uint32_t io_len;
6996 uint32_t mem_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006997 uint8_t bus;
6998 uint8_t func;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006999 int j;
7000 int index;
7001 dma_addr_t dma_address;
7002 char __iomem *ioremap_ptr;
7003 char __iomem *mem_ptr;
7004 uint32_t IsDead;
7005
7006 METHOD_TRACE("ips_init_phase1", 1);
7007 index = IPS_MAX_ADAPTERS;
7008 for (j = 0; j < IPS_MAX_ADAPTERS; j++) {
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08007009 if (ips_ha[j] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010 index = j;
7011 break;
7012 }
7013 }
7014
7015 if (index >= IPS_MAX_ADAPTERS)
7016 return -1;
7017
7018 /* stuff that we get in dev */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007019 bus = pci_dev->bus->number;
7020 func = pci_dev->devfn;
7021
7022 /* Init MEM/IO addresses to 0 */
7023 mem_addr = 0;
7024 io_addr = 0;
7025 mem_len = 0;
7026 io_len = 0;
7027
7028 for (j = 0; j < 2; j++) {
7029 if (!pci_resource_start(pci_dev, j))
7030 break;
7031
7032 if (pci_resource_flags(pci_dev, j) & IORESOURCE_IO) {
7033 io_addr = pci_resource_start(pci_dev, j);
7034 io_len = pci_resource_len(pci_dev, j);
7035 } else {
7036 mem_addr = pci_resource_start(pci_dev, j);
7037 mem_len = pci_resource_len(pci_dev, j);
7038 }
7039 }
7040
7041 /* setup memory mapped area (if applicable) */
7042 if (mem_addr) {
7043 uint32_t base;
7044 uint32_t offs;
7045
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046 base = mem_addr & PAGE_MASK;
7047 offs = mem_addr - base;
7048 ioremap_ptr = ioremap(base, PAGE_SIZE);
Jeff Garzik21e1a5f2007-12-13 16:14:09 -08007049 if (!ioremap_ptr)
7050 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007051 mem_ptr = ioremap_ptr + offs;
7052 } else {
7053 ioremap_ptr = NULL;
7054 mem_ptr = NULL;
7055 }
7056
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057 /* found a controller */
Yoann Padioleaudd00cc42007-07-19 01:49:03 -07007058 ha = kzalloc(sizeof (ips_ha_t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059 if (ha == NULL) {
7060 IPS_PRINTK(KERN_WARNING, pci_dev,
7061 "Unable to allocate temporary ha struct\n");
7062 return -1;
7063 }
7064
Linus Torvalds1da177e2005-04-16 15:20:36 -07007065 ips_sh[index] = NULL;
7066 ips_ha[index] = ha;
7067 ha->active = 1;
7068
7069 /* Store info in HA structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070 ha->io_addr = io_addr;
7071 ha->io_len = io_len;
7072 ha->mem_addr = mem_addr;
7073 ha->mem_len = mem_len;
7074 ha->mem_ptr = mem_ptr;
7075 ha->ioremap_ptr = ioremap_ptr;
7076 ha->host_num = (uint32_t) index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007077 ha->slot_num = PCI_SLOT(pci_dev->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007078 ha->pcidev = pci_dev;
7079
7080 /*
7081 * Set the pci_dev's dma_mask. Not all adapters support 64bit
7082 * addressing so don't enable it if the adapter can't support
7083 * it! Also, don't use 64bit addressing if dma addresses
7084 * are guaranteed to be < 4G.
7085 */
7086 if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
Matthias Gehre910638a2006-03-28 01:56:48 -08007087 !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007088 (ha)->flags |= IPS_HA_ENH_SG;
7089 } else {
Matthias Gehre910638a2006-03-28 01:56:48 -08007090 if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091 printk(KERN_WARNING "Unable to set DMA Mask\n");
7092 return ips_abort_init(ha, index);
7093 }
7094 }
7095 if(ips_cd_boot && !ips_FlashData){
7096 ips_FlashData = pci_alloc_consistent(pci_dev, PAGE_SIZE << 7,
7097 &ips_flashbusaddr);
7098 }
7099
7100 ha->enq = pci_alloc_consistent(pci_dev, sizeof (IPS_ENQ),
7101 &ha->enq_busaddr);
7102 if (!ha->enq) {
7103 IPS_PRINTK(KERN_WARNING, pci_dev,
7104 "Unable to allocate host inquiry structure\n");
7105 return ips_abort_init(ha, index);
7106 }
7107
7108 ha->adapt = pci_alloc_consistent(pci_dev, sizeof (IPS_ADAPTER) +
7109 sizeof (IPS_IO_CMD), &dma_address);
7110 if (!ha->adapt) {
7111 IPS_PRINTK(KERN_WARNING, pci_dev,
7112 "Unable to allocate host adapt & dummy structures\n");
7113 return ips_abort_init(ha, index);
7114 }
7115 ha->adapt->hw_status_start = dma_address;
7116 ha->dummy = (void *) (ha->adapt + 1);
7117
7118
7119
7120 ha->logical_drive_info = pci_alloc_consistent(pci_dev, sizeof (IPS_LD_INFO), &dma_address);
7121 if (!ha->logical_drive_info) {
7122 IPS_PRINTK(KERN_WARNING, pci_dev,
7123 "Unable to allocate logical drive info structure\n");
7124 return ips_abort_init(ha, index);
7125 }
7126 ha->logical_drive_info_dma_addr = dma_address;
7127
7128
7129 ha->conf = kmalloc(sizeof (IPS_CONF), GFP_KERNEL);
7130
7131 if (!ha->conf) {
7132 IPS_PRINTK(KERN_WARNING, pci_dev,
7133 "Unable to allocate host conf structure\n");
7134 return ips_abort_init(ha, index);
7135 }
7136
7137 ha->nvram = kmalloc(sizeof (IPS_NVRAM_P5), GFP_KERNEL);
7138
7139 if (!ha->nvram) {
7140 IPS_PRINTK(KERN_WARNING, pci_dev,
7141 "Unable to allocate host NVRAM structure\n");
7142 return ips_abort_init(ha, index);
7143 }
7144
7145 ha->subsys = kmalloc(sizeof (IPS_SUBSYS), GFP_KERNEL);
7146
7147 if (!ha->subsys) {
7148 IPS_PRINTK(KERN_WARNING, pci_dev,
7149 "Unable to allocate host subsystem structure\n");
7150 return ips_abort_init(ha, index);
7151 }
7152
7153 /* the ioctl buffer is now used during adapter initialization, so its
7154 * successful allocation is now required */
7155 if (ips_ioctlsize < PAGE_SIZE)
7156 ips_ioctlsize = PAGE_SIZE;
7157
7158 ha->ioctl_data = pci_alloc_consistent(pci_dev, ips_ioctlsize,
7159 &ha->ioctl_busaddr);
7160 ha->ioctl_len = ips_ioctlsize;
7161 if (!ha->ioctl_data) {
7162 IPS_PRINTK(KERN_WARNING, pci_dev,
7163 "Unable to allocate IOCTL data\n");
7164 return ips_abort_init(ha, index);
7165 }
7166
7167 /*
7168 * Setup Functions
7169 */
7170 ips_setup_funclist(ha);
7171
7172 if ((IPS_IS_MORPHEUS(ha)) || (IPS_IS_MARCO(ha))) {
7173 /* If Morpheus appears dead, reset it */
7174 IsDead = readl(ha->mem_ptr + IPS_REG_I960_MSG1);
7175 if (IsDead == 0xDEADBEEF) {
7176 ips_reset_morpheus(ha);
7177 }
7178 }
7179
7180 /*
7181 * Initialize the card if it isn't already
7182 */
7183
7184 if (!(*ha->func.isinit) (ha)) {
7185 if (!(*ha->func.init) (ha)) {
7186 /*
7187 * Initialization failed
7188 */
7189 IPS_PRINTK(KERN_WARNING, pci_dev,
7190 "Unable to initialize controller\n");
7191 return ips_abort_init(ha, index);
7192 }
7193 }
7194
7195 *indexPtr = index;
7196 return SUCCESS;
7197}
7198
7199/*---------------------------------------------------------------------------*/
7200/* Routine Name: ips_init_phase2 */
7201/* */
7202/* Routine Description: */
7203/* Adapter Initialization Phase 2 */
7204/* */
7205/* Return Value: */
7206/* 0 if Successful, else non-zero */
7207/*---------------------------------------------------------------------------*/
7208static int
7209ips_init_phase2(int index)
7210{
7211 ips_ha_t *ha;
7212
7213 ha = ips_ha[index];
7214
7215 METHOD_TRACE("ips_init_phase2", 1);
7216 if (!ha->active) {
7217 ips_ha[index] = NULL;
7218 return -1;
7219 }
7220
7221 /* Install the interrupt handler */
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007222 if (request_irq(ha->pcidev->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7224 "Unable to install interrupt handler\n");
7225 return ips_abort_init(ha, index);
7226 }
7227
7228 /*
7229 * Allocate a temporary SCB for initialization
7230 */
7231 ha->max_cmds = 1;
7232 if (!ips_allocatescbs(ha)) {
7233 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7234 "Unable to allocate a CCB\n");
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007235 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236 return ips_abort_init(ha, index);
7237 }
7238
7239 if (!ips_hainit(ha)) {
7240 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7241 "Unable to initialize controller\n");
Jeff Garzik8a694cc2007-12-13 16:14:07 -08007242 free_irq(ha->pcidev->irq, ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007243 return ips_abort_init(ha, index);
7244 }
7245 /* Free the temporary SCB */
7246 ips_deallocatescbs(ha, 1);
7247
7248 /* allocate CCBs */
7249 if (!ips_allocatescbs(ha)) {
7250 IPS_PRINTK(KERN_WARNING, ha->pcidev,
7251 "Unable to allocate CCBs\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
7256 return SUCCESS;
7257}
7258
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259MODULE_LICENSE("GPL");
Linus Torvalds1da177e2005-04-16 15:20:36 -07007260MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261MODULE_VERSION(IPS_VER_STRING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262
7263
7264/*
7265 * Overrides for Emacs so that we almost follow Linus's tabbing style.
7266 * Emacs will notice this stuff at the end of the file and automatically
7267 * adjust the settings for this buffer only. This must remain at the end
7268 * of the file.
7269 * ---------------------------------------------------------------------------
7270 * Local variables:
7271 * c-indent-level: 2
7272 * c-brace-imaginary-offset: 0
7273 * c-brace-offset: -2
7274 * c-argdecl-indent: 2
7275 * c-label-offset: -2
7276 * c-continued-statement-offset: 2
7277 * c-continued-brace-offset: 0
7278 * indent-tabs-mode: nil
7279 * tab-width: 8
7280 * End:
7281 */