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