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