Import 2.3.18pre1
[davej-history.git] / drivers / scsi / ips.c
blobe3d2ea4b971b958b28e93a7e2489bb245dc6a84b
1 /*****************************************************************************/
2 /* ips.c -- driver for the IBM ServeRAID controller */
3 /* */
4 /* Written By: Keith Mitchell, IBM Corporation */
5 /* */
6 /* Copyright (C) 1999 IBM Corporation */
7 /* */
8 /* This program is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation; either version 2 of the License, or */
11 /* (at your option) any later version. */
12 /* */
13 /* This program is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
17 /* */
18 /* NO WARRANTY */
19 /* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR */
20 /* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT */
21 /* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, */
22 /* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is */
23 /* solely responsible for determining the appropriateness of using and */
24 /* distributing the Program and assumes all risks associated with its */
25 /* exercise of rights under this Agreement, including but not limited to */
26 /* the risks and costs of program errors, damage to or loss of data, */
27 /* programs or equipment, and unavailability or interruption of operations. */
28 /* */
29 /* DISCLAIMER OF LIABILITY */
30 /* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY */
31 /* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
32 /* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND */
33 /* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR */
34 /* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE */
35 /* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED */
36 /* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES */
37 /* */
38 /* You should have received a copy of the GNU General Public License */
39 /* along with this program; if not, write to the Free Software */
40 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
41 /* */
42 /* Bugs/Comments/Suggestions should be mailed to: */
43 /* ipslinux@us.ibm.com */
44 /* */
45 /*****************************************************************************/
47 /*****************************************************************************/
48 /* Change Log */
49 /* */
50 /* 0.99.02 - Breakup commands that are bigger than 8 * the stripe size */
51 /* 0.99.03 - Make interrupt routine handle all completed request on the */
52 /* adapter not just the first one */
53 /* - Make sure passthru commands get woken up if we run out of */
54 /* SCBs */
55 /* - Send all of the commands on the queue at once rather than */
56 /* one at a time since the card will support it. */
57 /* 0.99.04 - Fix race condition in the passthru mechanism -- this required */
58 /* the interface to the utilities to change */
59 /* - Fix error recovery code */
60 /* 0.99.05 - Fix an oops when we get certain passthru commands */
61 /* 1.00.00 - Initial Public Release */
62 /* Functionally equivalent to 0.99.05 */
63 /* */
64 /*****************************************************************************/
67 * Conditional Compilation directives for this driver:
69 * NO_IPS_RESET - Don't reset the controller (no matter what)
70 * IPS_DEBUG - More verbose error messages
71 * IPS_PCI_PROBE_DEBUG - Print out more detail on the PCI probe
75 #if defined (MODULE)
76 #include <linux/module.h>
77 #endif /* MODULE */
79 #include <asm/io.h>
80 #include <asm/byteorder.h>
81 #include <linux/stddef.h>
82 #include <linux/version.h>
83 #include <linux/string.h>
84 #include <linux/errno.h>
85 #include <linux/kernel.h>
86 #include <linux/ioport.h>
87 #include <linux/malloc.h>
88 #include <linux/delay.h>
89 #include <linux/sched.h>
90 #include <linux/pci.h>
91 #include <linux/proc_fs.h>
93 #include <linux/blk.h>
94 #include <linux/types.h>
96 #ifndef NO_IPS_CMDLINE
97 #include <scsi/sg.h>
98 #endif
100 #include "sd.h"
101 #include "scsi.h"
102 #include "hosts.h"
103 #include "ips.h"
105 #include <linux/stat.h>
106 #include <linux/config.h>
107 #include <linux/spinlock.h>
108 #include <linux/smp.h>
111 * DRIVER_VER
113 #define IPS_VERSION_HIGH "1.00" /* MUST be 4 chars */
114 #define IPS_VERSION_LOW ".00 " /* MUST be 4 chars */
116 struct proc_dir_entry proc_scsi_ips = {
117 #if !defined(PROC_SCSI_IPS)
118 0, /* Use dynamic inode allocation */
119 #else
120 PROC_SCSI_IPS,
121 #endif
122 3, "ips",
123 S_IFDIR | S_IRUGO | S_IXUGO, 2
126 #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)
127 #include <linux/bios32.h>
128 #endif
130 #if !defined(__i386__)
131 #error "This driver has only been tested on the x86 platform"
132 #endif
134 #if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
135 #error "This driver only works with kernel 2.2.0 and later"
136 #endif
138 #if !defined(NO_IPS_CMDLINE) && ((SG_BIG_BUFF < 8192) || !defined(SG_BIG_BUFF))
139 #error "To use the command-line interface you need to define SG_BIG_BUFF"
140 #endif
142 #if IPS_DEBUG >= 12
143 #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*ONE_SEC)
144 #elif IPS_DEBUG >= 11
145 #define DBG(s) printk(KERN_NOTICE s "\n")
146 #else
147 #define DBG(s)
148 #endif
151 * global variables
153 static const char * ips_name = "ips";
154 static struct Scsi_Host * ips_sh[IPS_MAX_ADAPTERS]; /* Array of host controller structures */
155 static ips_ha_t * ips_ha[IPS_MAX_ADAPTERS]; /* Array of HA structures */
156 static unsigned int ips_num_controllers = 0;
157 static int ips_cmd_timeout = 60;
158 static int ips_reset_timeout = 60 * 5;
160 #define MAX_ADAPTER_NAME 6
162 static char ips_adapter_name[][30] = {
163 "ServeRAID",
164 "ServeRAID II",
165 "ServeRAID on motherboard",
166 "ServeRAID on motherboard",
167 "ServeRAID 3H",
168 "ServeRAID 3L"
172 * Function prototypes
174 int ips_detect(Scsi_Host_Template *);
175 int ips_release(struct Scsi_Host *);
176 int ips_abort(Scsi_Cmnd *);
177 int ips_reset(Scsi_Cmnd *, unsigned int);
178 int ips_eh_abort(Scsi_Cmnd *);
179 int ips_eh_reset(Scsi_Cmnd *);
180 int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
181 int ips_biosparam(Disk *, kdev_t, int *);
182 const char * ips_info(struct Scsi_Host *);
183 void do_ipsintr(int, void *, struct pt_regs *);
184 static int ips_hainit(ips_ha_t *);
185 static int ips_map_status(ips_scb_t *, ips_stat_t *);
186 static int ips_send(ips_ha_t *, ips_scb_t *, scb_callback);
187 static int ips_send_wait(ips_ha_t *, ips_scb_t *, int);
188 static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
189 static int ips_chkstatus(ips_ha_t *);
190 static int ips_online(ips_ha_t *, ips_scb_t *);
191 static int ips_inquiry(ips_ha_t *, ips_scb_t *);
192 static int ips_rdcap(ips_ha_t *, ips_scb_t *);
193 static int ips_msense(ips_ha_t *, ips_scb_t *);
194 static int ips_reqsen(ips_ha_t *, ips_scb_t *);
195 static int ips_allocatescbs(ips_ha_t *);
196 static int ips_reset_adapter(ips_ha_t *);
197 static int ips_statupd(ips_ha_t *);
198 static int ips_issue(ips_ha_t *, ips_scb_t *);
199 static int ips_isintr(ips_ha_t *);
200 static int ips_wait(ips_ha_t *, int, int);
201 static int ips_write_driver_status(ips_ha_t *);
202 static int ips_read_adapter_status(ips_ha_t *);
203 static int ips_read_subsystem_parameters(ips_ha_t *);
204 static int ips_read_config(ips_ha_t *);
205 static int ips_clear_adapter(ips_ha_t *);
206 static int ips_readwrite_page5(ips_ha_t *, int);
207 static void ips_intr(ips_ha_t *);
208 static void ips_next(ips_ha_t *);
209 static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
210 static void ipsintr_done(ips_ha_t *, struct ips_scb *);
211 static void ips_done(ips_ha_t *, ips_scb_t *);
212 static void ips_free(ips_ha_t *);
213 static void ips_init_scb(ips_ha_t *, ips_scb_t *);
214 static void ips_freescb(ips_ha_t *, ips_scb_t *);
215 static void ips_statinit(ips_ha_t *);
216 static ips_scb_t * ips_getscb(ips_ha_t *);
217 static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
218 static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
219 static inline ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t *);
220 static inline ips_scb_t * ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
221 static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
222 static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
223 static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *);
224 static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
226 #ifndef NO_IPS_CMDLINE
227 static int ips_is_passthru(Scsi_Cmnd *);
228 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);
229 static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
230 #endif
232 int ips_proc_info(char *, char **, off_t, int, int, int);
233 static int ips_host_info(ips_ha_t *, char *, off_t, int);
234 static void copy_mem_info(INFOSTR *, char *, int);
235 static int copy_info(INFOSTR *, char *, ...);
237 /*--------------------------------------------------------------------------*/
238 /* Exported Functions */
239 /*--------------------------------------------------------------------------*/
241 /****************************************************************************/
242 /* */
243 /* Routine Name: ips_detect */
244 /* */
245 /* Routine Description: */
246 /* */
247 /* Detect and initialize the driver */
248 /* */
249 /****************************************************************************/
251 ips_detect(Scsi_Host_Template *SHT) {
252 struct Scsi_Host *sh;
253 ips_ha_t *ha;
254 u32 io_addr;
255 u16 planer;
256 u8 bus;
257 u8 func;
258 u8 irq;
259 int index;
260 struct pci_dev *dev = NULL;
262 DBG("ips_detect");
264 SHT->proc_info = ips_proc_info;
265 SHT->proc_dir = &proc_scsi_ips;
267 #if defined(CONFIG_PCI)
269 /* initalize number of controllers */
270 ips_num_controllers = 0;
272 if (!pci_present())
273 return (0);
275 for (index = 0; index < IPS_MAX_ADAPTERS; index++) {
277 if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev)))
278 break;
280 /* stuff that we get in dev */
281 irq = dev->irq;
282 bus = dev->bus->number;
283 func = dev->devfn;
284 io_addr = dev->resource[0].start;
286 /* get planer status */
287 if (pci_read_config_word(dev, 0x04, &planer)) {
288 printk(KERN_WARNING "(%s%d) can't get planer status.\n",
289 ips_name, index);
291 continue;
294 /* check I/O address */
295 if ((dev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
296 continue;
298 /* check to see if an onboard planer controller is disabled */
299 if (!(planer & 0x000C)) {
301 #ifdef IPS_PCI_PROBE_DEBUG
302 printk(KERN_NOTICE "(%s%d) detect, Onboard ServeRAID disabled by BIOS\n",
303 ips_name, index);
304 #endif
306 continue;
309 #ifdef IPS_PCI_PROBE_DEBUG
310 printk(KERN_NOTICE "(%s%d) detect bus %d, func %x, irq %d, io %x\n",
311 ips_name, index, bus, func, irq, io_addr);
312 #endif
314 /* found a controller */
315 sh = scsi_register(SHT, sizeof(ips_ha_t));
317 if (sh == NULL) {
318 printk(KERN_WARNING "(%s%d) Unable to register controller with SCSI subsystem - skipping controller\n",
319 ips_name, index);
321 continue;
324 ha = HA(sh);
325 memset(ha, 0, sizeof(ips_ha_t));
327 /* Initialize spin lock */
328 spin_lock_init(&ha->scb_lock);
329 spin_lock_init(&ha->copp_lock);
331 ips_sh[ips_num_controllers] = sh;
332 ips_ha[ips_num_controllers] = ha;
333 ips_num_controllers++;
334 ha->active = 1;
336 ha->enq = kmalloc(sizeof(ENQCMD), GFP_KERNEL|GFP_DMA);
338 if (!ha->enq) {
339 printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
340 ips_name, index);
342 ha->active = 0;
344 continue;
347 ha->adapt = kmalloc(sizeof(ADAPTER_AREA), GFP_KERNEL|GFP_DMA);
349 if (!ha->adapt) {
350 printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
351 ips_name, index);
353 ha->active = 0;
355 continue;
358 ha->conf = kmalloc(sizeof(CONFCMD), GFP_KERNEL|GFP_DMA);
360 if (!ha->conf) {
361 printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
362 ips_name, index);
364 ha->active = 0;
366 continue;
369 ha->nvram = kmalloc(sizeof(NVRAM_PAGE5), GFP_KERNEL|GFP_DMA);
371 if (!ha->nvram) {
372 printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
373 ips_name, index);
375 ha->active = 0;
377 continue;
380 ha->subsys = kmalloc(sizeof(SUBSYS_PARAM), GFP_KERNEL|GFP_DMA);
382 if (!ha->subsys) {
383 printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
384 ips_name, index);
386 ha->active = 0;
388 continue;
391 ha->dummy = kmalloc(sizeof(BASIC_IO_CMD), GFP_KERNEL|GFP_DMA);
393 if (!ha->dummy) {
394 printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
395 ips_name, index);
397 ha->active = 0;
399 continue;
402 /* Store away needed values for later use */
403 sh->io_port = io_addr;
404 sh->n_io_port = 255;
405 sh->unique_id = io_addr;
406 sh->irq = irq;
407 sh->select_queue_depths = NULL;
408 sh->sg_tablesize = sh->hostt->sg_tablesize;
409 sh->can_queue = sh->hostt->can_queue;
410 sh->cmd_per_lun = sh->hostt->cmd_per_lun;
411 sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
412 sh->use_clustering = sh->hostt->use_clustering;
413 sh->wish_block = FALSE;
415 /* Store info in HA structure */
416 ha->io_addr = io_addr;
417 ha->irq = irq;
418 ha->host_num = index;
420 /* install the interrupt handler */
421 if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
422 printk(KERN_WARNING "(%s%d) unable to install interrupt handler - skipping controller\n",
423 ips_name, index);
425 ha->active = 0;
427 continue;
431 * Allocate a temporary SCB for initialization
433 ha->scbs = (ips_scb_t *) kmalloc(sizeof(ips_scb_t), GFP_KERNEL|GFP_DMA);
434 if (!ha->scbs) {
435 /* couldn't allocate a temp SCB */
436 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
437 ips_name, index);
439 ha->active = 0;
441 continue;
444 memset(ha->scbs, 0, sizeof(ips_scb_t));
445 ha->scbs->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
446 if (!ha->scbs->sg_list) {
447 /* couldn't allocate a temp SCB S/G list */
448 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
449 ips_name, index);
451 ha->active = 0;
453 continue;
456 ha->max_cmds = 1;
458 if (!ips_hainit(ha)) {
459 printk(KERN_WARNING "(%s%d) unable to initialize controller - skipping\n",
460 ips_name, index);
462 ha->active = 0;
464 continue;
468 * Free the temporary SCB
470 kfree(ha->scbs->sg_list);
471 kfree(ha->scbs);
472 ha->scbs = NULL;
474 /* allocate CCBs */
475 if (!ips_allocatescbs(ha)) {
476 printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
477 ips_name, index);
479 ha->active = 0;
481 continue;
484 /* finish setting values */
485 sh->max_id = ha->ntargets;
486 sh->max_lun = ha->nlun;
487 sh->max_channel = ha->nbus;
488 sh->can_queue = ha->max_cmds-1;
489 } /* end for */
491 return (ips_num_controllers);
493 #else
495 /* No PCI -- No ServeRAID */
496 return (0);
497 #endif /* CONFIG_PCI */
500 /****************************************************************************/
501 /* */
502 /* Routine Name: ips_release */
503 /* */
504 /* Routine Description: */
505 /* */
506 /* Remove a driver */
507 /* */
508 /****************************************************************************/
510 ips_release(struct Scsi_Host *sh) {
511 ips_scb_t *scb;
512 ips_ha_t *ha;
513 int i;
515 DBG("ips_release");
517 for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++);
519 if (i == IPS_MAX_ADAPTERS)
520 panic("(%s) release, invalid Scsi_Host pointer.\n",
521 ips_name);
523 ha = HA(sh);
525 if (!ha)
526 return (FALSE);
528 /* flush the cache on the controller */
529 scb = &ha->scbs[ha->max_cmds-1];
531 ips_init_scb(ha, scb);
533 scb->timeout = ips_cmd_timeout;
534 scb->cdb[0] = FLUSH_CACHE;
536 scb->cmd.flush_cache.op_code = FLUSH_CACHE;
537 scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
538 scb->cmd.flush_cache.state = NORM_STATE;
539 scb->cmd.flush_cache.reserved = 0;
540 scb->cmd.flush_cache.reserved2 = 0;
541 scb->cmd.flush_cache.reserved3 = 0;
542 scb->cmd.flush_cache.reserved4 = 0;
544 printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
546 /* send command */
547 if (ips_send_wait(ha, scb, ips_cmd_timeout) == IPS_FAILURE)
548 printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num);
550 printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num);
552 ips_sh[i] = NULL;
553 ips_ha[i] = NULL;
555 /* free extra memory */
556 ips_free(ha);
558 /* free IRQ */
559 free_irq(ha->irq, ha);
561 /* unregister with SCSI sub system */
562 scsi_unregister(sh);
564 return (FALSE);
567 /****************************************************************************/
568 /* */
569 /* Routine Name: ips_eh_abort */
570 /* */
571 /* Routine Description: */
572 /* */
573 /* Abort a command (using the new error code stuff) */
574 /* */
575 /****************************************************************************/
577 ips_eh_abort(Scsi_Cmnd *SC) {
578 ips_ha_t *ha;
580 DBG("ips_eh_abort");
582 if (!SC)
583 return (FAILED);
585 ha = (ips_ha_t *) SC->host->hostdata;
587 if (!ha)
588 return (FAILED);
590 if (!ha->active)
591 return (FAILED);
593 if (SC->serial_number != SC->serial_number_at_timeout) {
594 /* HMM, looks like a bogus command */
595 #if IPS_DEBUG >= 1
596 printk(KERN_NOTICE "Abort called with bogus scsi command\n");
597 #endif
599 return (FAILED);
602 if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
603 return (FAILED);
605 /* See if the command is on the wait queue */
606 if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
607 ips_removeq_wait(&ha->copp_waitlist, SC)) {
608 /* command not sent yet */
609 clear_bit(IPS_IN_ABORT, &ha->flags);
611 return (SUCCESS);
612 } else {
613 /* command must have already been sent */
614 clear_bit(IPS_IN_ABORT, &ha->flags);
616 return (FAILED);
620 /****************************************************************************/
621 /* */
622 /* Routine Name: ips_abort */
623 /* */
624 /* Routine Description: */
625 /* */
626 /* Abort a command */
627 /* */
628 /****************************************************************************/
630 ips_abort(Scsi_Cmnd *SC) {
631 ips_ha_t *ha;
633 DBG("ips_abort");
635 if (!SC)
636 return (SCSI_ABORT_SNOOZE);
638 ha = (ips_ha_t *) SC->host->hostdata;
640 if (!ha)
641 return (SCSI_ABORT_SNOOZE);
643 if (!ha->active)
644 return (SCSI_ABORT_SNOOZE);
646 if (SC->serial_number != SC->serial_number_at_timeout) {
647 /* HMM, looks like a bogus command */
648 #if IPS_DEBUG >= 1
649 printk(KERN_NOTICE "Abort called with bogus scsi command\n");
650 #endif
652 return (SCSI_ABORT_NOT_RUNNING);
655 if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
656 return (SCSI_ABORT_SNOOZE);
658 /* See if the command is on the wait queue */
659 if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
660 ips_removeq_wait(&ha->copp_waitlist, SC)) {
661 /* command not sent yet */
662 clear_bit(IPS_IN_ABORT, &ha->flags);
664 return (SCSI_ABORT_PENDING);
665 } else {
666 /* command must have already been sent */
667 clear_bit(IPS_IN_ABORT, &ha->flags);
669 return (SCSI_ABORT_SNOOZE);
673 /****************************************************************************/
674 /* */
675 /* Routine Name: ips_eh_reset */
676 /* */
677 /* Routine Description: */
678 /* */
679 /* Reset the controller (with new eh error code) */
680 /* */
681 /****************************************************************************/
683 ips_eh_reset(Scsi_Cmnd *SC) {
684 ips_ha_t *ha;
685 ips_scb_t *scb;
687 DBG("ips_eh_reset");
689 #ifdef NO_IPS_RESET
690 return (FAILED);
691 #else
693 if (!SC) {
695 #if IPS_DEBUG >= 1
696 printk(KERN_NOTICE "Reset called with NULL scsi command\n");
697 #endif
699 return (FAILED);
702 ha = (ips_ha_t *) SC->host->hostdata;
704 if (!ha) {
706 #if IPS_DEBUG >= 1
707 printk(KERN_NOTICE "Reset called with NULL ha struct\n");
708 #endif
710 return (FAILED);
713 if (!ha->active)
714 return (FAILED);
716 if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
717 return (FAILED);
719 /* See if the command is on the waiting queue */
720 if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
721 ips_removeq_wait(&ha->copp_waitlist, SC)) {
722 /* command not sent yet */
723 clear_bit(IPS_IN_ABORT, &ha->flags);
725 return (SUCCESS);
729 * command must have already been sent
730 * reset the controller
732 if (!ips_reset_adapter(ha)) {
733 clear_bit(IPS_IN_RESET, &ha->flags);
735 return (FAILED);
738 if (!ips_clear_adapter(ha)) {
739 clear_bit(IPS_IN_RESET, &ha->flags);
741 return (FAILED);
744 /* Now fail all of the active commands */
745 #if IPS_DEBUG >= 1
746 printk(KERN_WARNING "(%s%d) Failing active commands\n",
747 ips_name, ha->host_num);
748 #endif
749 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
750 scb->scsi_cmd->result = DID_RESET << 16;
751 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
752 ips_freescb(ha, scb);
755 /* Reset the number of active IOCTLs */
756 ha->num_ioctl = 0;
758 clear_bit(IPS_IN_RESET, &ha->flags);
760 if (!test_bit(IPS_IN_INTR, &ha->flags)) {
762 * Only execute the next command when
763 * we are not being called from the
764 * interrupt handler. The interrupt
765 * handler wants to do this and since
766 * interrupts are turned off here....
768 ips_next(ha);
771 return (SUCCESS);
773 #endif /* NO_IPS_RESET */
777 /****************************************************************************/
778 /* */
779 /* Routine Name: ips_reset */
780 /* */
781 /* Routine Description: */
782 /* */
783 /* Reset the controller */
784 /* */
785 /****************************************************************************/
787 ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
788 ips_ha_t *ha;
789 ips_scb_t *scb;
791 DBG("ips_reset");
793 #ifdef NO_IPS_RESET
794 return (SCSI_RESET_SNOOZE);
795 #else
797 if (!SC) {
799 #if IPS_DEBUG >= 1
800 printk(KERN_NOTICE "Reset called with NULL scsi command\n");
801 #endif
803 return (SCSI_RESET_SNOOZE);
806 ha = (ips_ha_t *) SC->host->hostdata;
808 if (!ha) {
810 #if IPS_DEBUG >= 1
811 printk(KERN_NOTICE "Reset called with NULL ha struct\n");
812 #endif
814 return (SCSI_RESET_SNOOZE);
817 if (!ha->active)
818 return (SCSI_RESET_SNOOZE);
820 if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
821 return (SCSI_RESET_SNOOZE);
823 /* See if the command is on the waiting queue */
824 if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
825 ips_removeq_wait(&ha->copp_waitlist, SC)) {
826 /* command not sent yet */
827 clear_bit(IPS_IN_ABORT, &ha->flags);
829 return (SCSI_RESET_SNOOZE);
832 /* reset the controller */
833 if (!ips_reset_adapter(ha)) {
834 clear_bit(IPS_IN_RESET, &ha->flags);
836 return (SCSI_RESET_ERROR);
839 if (!ips_clear_adapter(ha)) {
840 clear_bit(IPS_IN_RESET, &ha->flags);
842 return (SCSI_RESET_ERROR);
845 /* Now fail all of the active commands */
846 #if IPS_DEBUG >= 1
847 printk(KERN_WARNING "(%s%d) Failing active commands\n",
848 ips_name, ha->host_num);
849 #endif
850 while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
851 scb->scsi_cmd->result = DID_RESET << 16;
852 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
853 ips_freescb(ha, scb);
856 /* Reset the number of active IOCTLs */
857 ha->num_ioctl = 0;
859 clear_bit(IPS_IN_RESET, &ha->flags);
861 if (!test_bit(IPS_IN_INTR, &ha->flags)) {
863 * Only execute the next command when
864 * we are not being called from the
865 * interrupt handler. The interrupt
866 * handler wants to do this and since
867 * interrupts are turned off here....
869 ips_next(ha);
872 return (SCSI_RESET_SUCCESS);
874 #endif /* NO_IPS_RESET */
878 /****************************************************************************/
879 /* */
880 /* Routine Name: ips_queue */
881 /* */
882 /* Routine Description: */
883 /* */
884 /* Send a command to the controller */
885 /* */
886 /****************************************************************************/
888 ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
889 ips_ha_t *ha;
891 DBG("ips_queue");
893 ha = (ips_ha_t *) SC->host->hostdata;
895 if (!ha)
896 return (1);
898 if (!ha->active)
899 return (1);
901 #ifndef NO_IPS_CMDLINE
902 if (ips_is_passthru(SC)) {
903 if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
904 SC->result = DID_BUS_BUSY << 16;
905 done(SC);
907 return (0);
909 } else {
910 #endif
911 if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
912 SC->result = DID_BUS_BUSY << 16;
913 done(SC);
915 return (0);
918 #ifndef NO_IPS_CMDLINE
920 #endif
922 SC->scsi_done = done;
924 #if IPS_DEBUG >= 10
925 printk(KERN_NOTICE "%s: ips_queue: cmd 0x%X (%d %d %d)\n",
926 ips_name,
927 SC->cmnd[0],
928 SC->channel,
929 SC->target,
930 SC->lun);
931 #if IPS_DEBUG >= 11
932 MDELAY(2*ONE_SEC);
933 #endif
934 #endif
936 #ifndef NO_IPS_CMDLINE
937 if (ips_is_passthru(SC))
938 ips_putq_wait_tail(&ha->copp_waitlist, SC);
939 else
940 #endif
941 ips_putq_wait_tail(&ha->scb_waitlist, SC);
943 if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&
944 (!test_bit(IPS_IN_ABORT, &ha->flags)) &&
945 (!test_bit(IPS_IN_RESET, &ha->flags)))
946 ips_next(ha);
948 return (0);
951 /****************************************************************************/
952 /* */
953 /* Routine Name: ips_biosparam */
954 /* */
955 /* Routine Description: */
956 /* */
957 /* Set bios geometry for the controller */
958 /* */
959 /****************************************************************************/
961 ips_biosparam(Disk *disk, kdev_t dev, int geom[]) {
962 ips_ha_t *ha;
963 int heads;
964 int sectors;
965 int cylinders;
967 DBG("ips_biosparam");
969 ha = (ips_ha_t *) disk->device->host->hostdata;
971 if (!ha)
972 /* ?!?! host adater info invalid */
973 return (0);
975 if (!ha->active)
976 return (0);
978 if (!ips_read_adapter_status(ha))
979 /* ?!?! Enquiry command failed */
980 return (0);
982 if ((disk->capacity > 0x400000) &&
983 ((ha->enq->ucMiscFlag & 0x8) == 0)) {
984 heads = NORM_MODE_HEADS;
985 sectors = NORM_MODE_SECTORS;
986 } else {
987 heads = COMP_MODE_HEADS;
988 sectors = COMP_MODE_SECTORS;
991 cylinders = disk->capacity / (heads * sectors);
993 #if IPS_DEBUG >= 2
994 printk(KERN_NOTICE "Geometry: heads: %d, sectors: %d, cylinders: %d\n",
995 heads, sectors, cylinders);
996 #endif
998 geom[0] = heads;
999 geom[1] = sectors;
1000 geom[2] = cylinders;
1002 return (0);
1005 /****************************************************************************/
1006 /* */
1007 /* Routine Name: do_ipsintr */
1008 /* */
1009 /* Routine Description: */
1010 /* */
1011 /* Wrapper for the interrupt handler */
1012 /* */
1013 /****************************************************************************/
1014 void
1015 do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
1016 ips_ha_t *ha;
1017 unsigned int cpu_flags;
1019 DBG("do_ipsintr");
1021 ha = (ips_ha_t *) dev_id;
1023 spin_lock_irqsave(&io_request_lock, cpu_flags);
1025 if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
1026 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1028 return ;
1031 if (!ha) {
1032 clear_bit(IPS_IN_INTR, &ha->flags);
1033 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1035 return;
1038 if (!ha->active) {
1039 clear_bit(IPS_IN_INTR, &ha->flags);
1040 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1042 return;
1045 ips_intr(ha);
1047 clear_bit(IPS_IN_INTR, &ha->flags);
1049 spin_unlock_irqrestore(&io_request_lock, cpu_flags);
1052 /****************************************************************************/
1053 /* */
1054 /* Routine Name: ips_intr */
1055 /* */
1056 /* Routine Description: */
1057 /* */
1058 /* Polling interrupt handler */
1059 /* */
1060 /* ASSUMES interrupts are disabled */
1061 /* */
1062 /****************************************************************************/
1063 void
1064 ips_intr(ips_ha_t *ha) {
1065 ips_stat_t *sp;
1066 ips_scb_t *scb;
1067 int status;
1069 DBG("ips_intr");
1071 if (!ha)
1072 return;
1074 if (!ha->active)
1075 return;
1077 while (ips_isintr(ha)) {
1078 sp = &ha->sp;
1080 if ((status = ips_chkstatus(ha)) < 0) {
1081 /* unexpected interrupt - no ccb */
1082 printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n",
1083 ips_name, ha->host_num);
1084 continue ;
1087 scb = (ips_scb_t *) sp->scb_addr;
1090 * use the callback function to finish things up
1091 * NOTE: interrupts are OFF for this
1093 (*scb->callback) (ha, scb);
1096 clear_bit(IPS_IN_INTR, &ha->flags);
1099 /****************************************************************************/
1100 /* */
1101 /* Routine Name: ips_info */
1102 /* */
1103 /* Routine Description: */
1104 /* */
1105 /* Return info about the driver */
1106 /* */
1107 /****************************************************************************/
1108 const char *
1109 ips_info(struct Scsi_Host *SH) {
1110 static char buffer[256];
1111 char *bp;
1112 ips_ha_t *ha;
1114 DBG("ips_info");
1116 ha = HA(SH);
1118 if (!ha)
1119 return (NULL);
1121 bp = &buffer[0];
1122 memset(bp, 0, sizeof(buffer));
1124 strcpy(bp, "IBM PCI ServeRAID ");
1125 strcat(bp, IPS_VERSION_HIGH);
1126 strcat(bp, IPS_VERSION_LOW);
1128 if (ha->ad_type > 0 &&
1129 ha->ad_type <= MAX_ADAPTER_NAME) {
1130 strcat(bp, " <");
1131 strcat(bp, ips_adapter_name[ha->ad_type-1]);
1132 strcat(bp, ">");
1135 return (bp);
1138 /****************************************************************************/
1139 /* */
1140 /* Routine Name: ips_proc_info */
1141 /* */
1142 /* Routine Description: */
1143 /* */
1144 /* The passthru interface for the driver */
1145 /* */
1146 /****************************************************************************/
1148 ips_proc_info(char *buffer, char **start, off_t offset,
1149 int length, int hostno, int func) {
1150 int i;
1151 int ret;
1152 ips_ha_t *ha = NULL;
1154 DBG("ips_proc_info");
1156 /* Find our host structure */
1157 for (i = 0; i < ips_num_controllers; i++) {
1158 if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
1159 ha = (ips_ha_t *) ips_sh[i]->hostdata;
1161 break;
1165 if (!ha)
1166 return (-EINVAL);
1168 if (func) {
1169 /* write */
1170 return (0);
1171 } else {
1172 /* read */
1173 if (start)
1174 *start = buffer;
1176 ret = ips_host_info(ha, buffer, offset, length);
1178 return (ret);
1182 /*--------------------------------------------------------------------------*/
1183 /* Helper Functions */
1184 /*--------------------------------------------------------------------------*/
1186 #ifndef NO_IPS_CMDLINE
1188 /****************************************************************************/
1189 /* */
1190 /* Routine Name: ips_is_passthru */
1191 /* */
1192 /* Routine Description: */
1193 /* */
1194 /* Determine if the specified SCSI command is really a passthru command */
1195 /* */
1196 /****************************************************************************/
1197 static int
1198 ips_is_passthru(Scsi_Cmnd *SC) {
1199 DBG("ips_is_passthru");
1201 if (!SC)
1202 return (0);
1204 if ((SC->channel == 0) &&
1205 (SC->target == IPS_ADAPTER_ID) &&
1206 (SC->lun == 0) &&
1207 (SC->cmnd[0] == 0x0d) &&
1208 (SC->request_bufflen) &&
1209 (!SC->use_sg) &&
1210 (((char *) SC->request_buffer)[0] == 'C') &&
1211 (((char *) SC->request_buffer)[1] == 'O') &&
1212 (((char *) SC->request_buffer)[2] == 'P') &&
1213 (((char *) SC->request_buffer)[3] == 'P')) {
1214 return (1);
1215 } else {
1216 return (0);
1220 /****************************************************************************/
1221 /* */
1222 /* Routine Name: ips_is_passthru */
1223 /* */
1224 /* Routine Description: */
1225 /* */
1226 /* Make a passthru command out of the info in the Scsi block */
1227 /* */
1228 /****************************************************************************/
1229 static int
1230 ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
1231 ips_passthru_t *pt;
1233 DBG("ips_make_passthru");
1235 if (!SC->request_bufflen || !SC->request_buffer) {
1236 /* no data */
1237 #if IPS_DEBUG_PT >= 1
1238 printk(KERN_NOTICE "(%s%d) No passthru structure\n",
1239 ips_name, ha->host_num);
1240 #endif
1242 return (IPS_FAILURE);
1245 if (SC->request_bufflen < sizeof(ips_passthru_t)) {
1246 /* wrong size */
1247 #if IPS_DEBUG_PT >= 1
1248 printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
1249 ips_name, ha->host_num);
1250 #endif
1252 return (IPS_FAILURE);
1255 if ((((char *) SC->request_buffer)[0] != 'C') ||
1256 (((char *) SC->request_buffer)[1] != 'O') ||
1257 (((char *) SC->request_buffer)[2] != 'P') ||
1258 (((char *) SC->request_buffer)[3] != 'P')) {
1259 /* signature doesn't match */
1260 #if IPS_DEBUG_PT >= 1
1261 printk(KERN_NOTICE "(%s%d) Wrong signature on passthru structure.\n",
1262 ips_name, ha->host_num);
1263 #endif
1265 return (IPS_FAILURE);
1268 pt = (ips_passthru_t *) SC->request_buffer;
1269 scb->scsi_cmd = SC;
1271 if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
1272 /* wrong size */
1273 #if IPS_DEBUG_PT >= 1
1274 printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
1275 ips_name, ha->host_num);
1276 #endif
1278 return (IPS_FAILURE);
1281 switch (pt->CoppCmd) {
1282 case IPS_NUMCTRLS:
1283 memcpy(SC->request_buffer + sizeof(ips_passthru_t),
1284 &ips_num_controllers, sizeof(int));
1285 SC->result = DID_OK << 16;
1287 return (IPS_SUCCESS_IMM);
1288 case IPS_CTRLINFO:
1289 memcpy(SC->request_buffer + sizeof(ips_passthru_t),
1290 ha, sizeof(ips_ha_t));
1291 SC->result = DID_OK << 16;
1293 return (IPS_SUCCESS_IMM);
1294 case COPPUSRCMD:
1295 if (ips_usrcmd(ha, pt, scb))
1296 return (IPS_SUCCESS);
1297 else
1298 return (IPS_FAILURE);
1299 break;
1302 return (IPS_FAILURE);
1305 /****************************************************************************/
1306 /* */
1307 /* Routine Name: ips_usrcmd */
1308 /* */
1309 /* Routine Description: */
1310 /* */
1311 /* Process a user command and make it ready to send */
1312 /* */
1313 /****************************************************************************/
1314 static int
1315 ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
1316 SG_LIST *sg_list;
1318 DBG("ips_usrcmd");
1320 if ((!scb) || (!pt) || (!ha))
1321 return (0);
1323 /* Save the S/G list pointer so it doesn't get clobbered */
1324 sg_list = scb->sg_list;
1326 /* copy in the CP */
1327 memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IOCTL_INFO));
1328 memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(DCDB_TABLE));
1330 /* FIX stuff that might be wrong */
1331 scb->sg_list = sg_list;
1332 scb->scb_busaddr = VIRT_TO_BUS(scb);
1333 scb->bus = 0;
1334 scb->target_id = 0;
1335 scb->lun = 0;
1336 scb->sg_len = 0;
1337 scb->data_len = 0;
1338 scb->flags = 0;
1339 scb->op_code = 0;
1340 scb->callback = ipsintr_done;
1341 scb->timeout = ips_cmd_timeout;
1342 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
1344 /* we don't support DCDB/READ/WRITE Scatter Gather */
1345 if ((scb->cmd.basic_io.op_code == READ_SCATTER_GATHER) ||
1346 (scb->cmd.basic_io.op_code == WRITE_SCATTER_GATHER) ||
1347 (scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER))
1348 return (0);
1350 if (pt->CmdBSize && pt->CmdBuffer) {
1351 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + sizeof(ips_passthru_t));
1352 } else {
1353 scb->data_busaddr = 0L;
1356 if (pt->CmdBSize) {
1357 if (scb->cmd.dcdb.op_code == DIRECT_CDB) {
1358 scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
1359 scb->dcdb.buffer_pointer = scb->data_busaddr;
1360 } else {
1361 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
1365 /* set timeouts */
1366 if (pt->TimeOut) {
1367 scb->timeout = pt->TimeOut;
1369 if (pt->TimeOut <= 10)
1370 scb->dcdb.cmd_attribute |= TIMEOUT_10;
1371 else if (pt->TimeOut <= 60)
1372 scb->dcdb.cmd_attribute |= TIMEOUT_60;
1373 else
1374 scb->dcdb.cmd_attribute |= TIMEOUT_20M;
1377 /* assume error */
1378 scb->scsi_cmd->result = DID_ERROR << 16;
1380 /* success */
1381 return (1);
1384 /****************************************************************************/
1385 /* */
1386 /* Routine Name: ips_cleanup_passthru */
1387 /* */
1388 /* Routine Description: */
1389 /* */
1390 /* Cleanup after a passthru command */
1391 /* */
1392 /****************************************************************************/
1393 static void
1394 ips_cleanup_passthru(ips_scb_t *scb) {
1395 ips_passthru_t *pt;
1397 DBG("ips_cleanup_passthru");
1399 if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
1400 #if IPS_DEBUG_PT >= 1
1401 printk(KERN_NOTICE "IPS couldn't cleanup\n");
1402 #endif
1404 return ;
1407 pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer;
1409 /* Copy data back to the user */
1410 pt->BasicStatus = scb->basic_status;
1411 pt->ExtendedStatus = scb->extended_status;
1413 scb->scsi_cmd->result = DID_OK << 16;
1416 #endif
1418 /****************************************************************************/
1419 /* */
1420 /* Routine Name: ips_host_info */
1421 /* */
1422 /* Routine Description: */
1423 /* */
1424 /* The passthru interface for the driver */
1425 /* */
1426 /****************************************************************************/
1427 static int
1428 ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
1429 INFOSTR info;
1431 DBG("ips_host_info");
1433 info.buffer = ptr;
1434 info.length = len;
1435 info.offset = offset;
1436 info.pos = 0;
1438 copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
1440 if ((ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) &&
1441 (ha->nvram->adapter_type != 0))
1442 copy_info(&info, "\tController Type : %s\n", ips_adapter_name[ha->ad_type-1]);
1443 else
1444 copy_info(&info, "\tController Type : Unknown\n");
1446 copy_info(&info, "\tIO port address : 0x%lx\n", ha->io_addr);
1447 copy_info(&info, "\tIRQ number : %d\n", ha->irq);
1449 if (ha->nvram->signature == NVRAM_PAGE5_SIGNATURE)
1450 copy_info(&info, "\tBIOS Version : %c%c%c%c%c%c%c%c\n",
1451 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
1452 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
1453 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
1454 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
1456 copy_info(&info, "\tFirmware Version : %c%c%c%c%c%c%c%c\n",
1457 ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
1458 ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
1459 ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
1460 ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
1462 copy_info(&info, "\tBoot Block Version : %c%c%c%c%c%c%c%c\n",
1463 ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
1464 ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
1465 ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
1466 ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
1468 copy_info(&info, "\tDriver Version : %s%s\n",
1469 IPS_VERSION_HIGH, IPS_VERSION_LOW);
1471 copy_info(&info, "\tMax Physical Devices : %d\n",
1472 ha->enq->ucMaxPhysicalDevices);
1473 copy_info(&info, "\tMax Active Commands : %d\n",
1474 ha->max_cmds);
1475 copy_info(&info, "\tCurrent Queued Commands : %d\n",
1476 ha->scb_waitlist.count);
1477 copy_info(&info, "\tCurrent Active Commands : %d\n",
1478 ha->scb_activelist.count - ha->num_ioctl);
1479 copy_info(&info, "\tCurrent Queued PT Commands : %d\n",
1480 ha->copp_waitlist.count);
1481 copy_info(&info, "\tCurrent Active PT Commands : %d\n",
1482 ha->num_ioctl);
1484 copy_info(&info, "\n");
1486 return (info.pos > info.offset ? info.pos - info.offset : 0);
1489 /****************************************************************************/
1490 /* */
1491 /* Routine Name: copy_mem_info */
1492 /* */
1493 /* Routine Description: */
1494 /* */
1495 /* Copy data into an INFOSTR structure */
1496 /* */
1497 /****************************************************************************/
1498 static void
1499 copy_mem_info(INFOSTR *info, char *data, int len) {
1500 DBG("copy_mem_info");
1502 if (info->pos + len > info->length)
1503 len = info->length - info->pos;
1505 if (info->pos + len < info->offset) {
1506 info->pos += len;
1507 return;
1510 if (info->pos < info->offset) {
1511 data += (info->offset - info->pos);
1512 len -= (info->offset - info->pos);
1515 if (len > 0) {
1516 memcpy(info->buffer + info->pos, data, len);
1517 info->pos += len;
1521 /****************************************************************************/
1522 /* */
1523 /* Routine Name: copy_info */
1524 /* */
1525 /* Routine Description: */
1526 /* */
1527 /* printf style wrapper for an info structure */
1528 /* */
1529 /****************************************************************************/
1530 static int
1531 copy_info(INFOSTR *info, char *fmt, ...) {
1532 va_list args;
1533 char buf[81];
1534 int len;
1536 DBG("copy_info");
1538 va_start(args, fmt);
1539 len = vsprintf(buf, fmt, args);
1540 va_end(args);
1542 copy_mem_info(info, buf, len);
1544 return (len);
1547 /****************************************************************************/
1548 /* */
1549 /* Routine Name: ips_hainit */
1550 /* */
1551 /* Routine Description: */
1552 /* */
1553 /* Initialize the controller */
1554 /* */
1555 /* NOTE: Assumes to be called from with a lock */
1556 /* */
1557 /****************************************************************************/
1558 static int
1559 ips_hainit(ips_ha_t *ha) {
1560 int i;
1562 DBG("ips_hainit");
1564 if (!ha)
1565 return (0);
1567 /* initialize status queue */
1568 ips_statinit(ha);
1570 /* Setup HBA ID's */
1571 if (!ips_read_config(ha)) {
1573 #ifndef NO_IPS_RESET
1575 /* Try to reset the controller and try again */
1576 if (!ips_reset_adapter(ha)) {
1577 printk(KERN_WARNING "(%s%d) unable to reset controller.\n",
1578 ips_name, ha->host_num);
1580 return (0);
1583 if (!ips_clear_adapter(ha)) {
1584 printk(KERN_WARNING "(%s%d) unable to initialize controller.\n",
1585 ips_name, ha->host_num);
1587 return (0);
1590 #endif
1592 if (!ips_read_config(ha)) {
1593 printk(KERN_WARNING "(%s%d) unable to read config from controller.\n",
1594 ips_name, ha->host_num);
1596 return (0);
1598 } /* end if */
1600 /* write driver version */
1601 if (!ips_write_driver_status(ha)) {
1602 printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n",
1603 ips_name, ha->host_num);
1605 return (0);
1608 if (!ips_read_adapter_status(ha)) {
1609 printk(KERN_WARNING "(%s%d) unable to read controller status.\n",
1610 ips_name, ha->host_num);
1612 return (0);
1615 if (!ips_read_subsystem_parameters(ha)) {
1616 printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n",
1617 ips_name, ha->host_num);
1619 return (0);
1622 /* set limits on SID, LUN, BUS */
1623 ha->ntargets = MAX_TARGETS + 1;
1624 ha->nlun = 1;
1625 ha->nbus = (ha->enq->ucMaxPhysicalDevices / MAX_TARGETS);
1627 switch (ha->conf->logical_drive[0].ucStripeSize) {
1628 case 4:
1629 ha->max_xfer = 0x10000;
1630 break;
1632 case 5:
1633 ha->max_xfer = 0x20000;
1634 break;
1636 case 6:
1637 ha->max_xfer = 0x40000;
1638 break;
1640 case 7:
1641 default:
1642 ha->max_xfer = 0x80000;
1643 break;
1646 /* setup max concurrent commands */
1647 if (ha->subsys->param[4] & 0x1) {
1648 /* Use the new method */
1649 ha->max_cmds = ha->enq->ucConcurrentCmdCount;
1650 } else {
1651 /* use the old method */
1652 switch (ha->conf->logical_drive[0].ucStripeSize) {
1653 case 4:
1654 ha->max_cmds = 32;
1655 break;
1657 case 5:
1658 ha->max_cmds = 16;
1659 break;
1661 case 6:
1662 ha->max_cmds = 8;
1663 break;
1665 case 7:
1666 default:
1667 ha->max_cmds = 4;
1668 break;
1672 /* set controller IDs */
1673 ha->ha_id[0] = IPS_ADAPTER_ID;
1674 for (i = 1; i < ha->nbus; i++)
1675 ha->ha_id[i] = ha->conf->init_id[i-1] & 0x1f;
1677 return (1);
1680 /****************************************************************************/
1681 /* */
1682 /* Routine Name: ips_next */
1683 /* */
1684 /* Routine Description: */
1685 /* */
1686 /* Take the next command off the queue and send it to the controller */
1687 /* */
1688 /* ASSUMED to be called from within a lock */
1689 /* */
1690 /****************************************************************************/
1691 static void
1692 ips_next(ips_ha_t *ha) {
1693 ips_scb_t *scb;
1694 Scsi_Cmnd *SC;
1695 int ret;
1697 DBG("ips_next");
1699 if (!ha)
1700 return ;
1702 #ifndef NO_IPS_CMDLINE
1704 * Send passthru commands
1705 * These have priority over normal I/O
1706 * but shouldn't affect performance too much
1707 * since we limit the number that can be active
1708 * on the card at any one time
1710 while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
1711 (ha->copp_waitlist.head) &&
1712 (scb = ips_getscb(ha))) {
1713 SC = ips_removeq_wait_head(&ha->copp_waitlist);
1715 ret = ips_make_passthru(ha, SC, scb);
1717 switch (ret) {
1718 case IPS_FAILURE:
1719 if (scb->scsi_cmd) {
1720 scb->scsi_cmd->result = DID_ERROR << 16;
1721 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1723 ips_freescb(ha, scb);
1724 break;
1725 case IPS_SUCCESS_IMM:
1726 if (scb->scsi_cmd)
1727 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1728 ips_freescb(ha, scb);
1729 break;
1730 default:
1731 break;
1732 } /* end case */
1734 if (ret != IPS_SUCCESS)
1735 continue;
1737 ret = ips_send_cmd(ha, scb);
1739 if (ret == IPS_SUCCESS) {
1740 ips_putq_scb_head(&ha->scb_activelist, scb);
1741 ha->num_ioctl++;
1744 switch(ret) {
1745 case IPS_FAILURE:
1746 if (scb->scsi_cmd) {
1747 scb->scsi_cmd->result = DID_ERROR << 16;
1748 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1751 ips_freescb(ha, scb);
1752 break;
1753 case IPS_SUCCESS_IMM:
1754 if (scb->scsi_cmd)
1755 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1756 ips_freescb(ha, scb);
1757 break;
1758 default:
1759 break;
1760 } /* end case */
1762 #endif
1765 * Send "Normal" I/O commands
1767 while ((ha->scb_waitlist.head) &&
1768 (scb = ips_getscb(ha))) {
1769 SC = ips_removeq_wait_head(&ha->scb_waitlist);
1771 SC->result = DID_OK;
1772 SC->host_scribble = NULL;
1774 memset(SC->sense_buffer, 0, sizeof(SC->sense_buffer));
1776 scb->target_id = SC->target;
1777 scb->lun = SC->lun;
1778 scb->bus = SC->channel;
1779 scb->scsi_cmd = SC;
1780 scb->breakup = 0;
1781 scb->data_len = 0;
1782 scb->callback = ipsintr_done;
1783 scb->timeout = ips_cmd_timeout;
1784 memset(&scb->cmd, 0, 4);
1786 /* copy in the CDB */
1787 memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
1789 /* Now handle the data buffer */
1790 if (SC->use_sg) {
1791 struct scatterlist *sg;
1792 int i;
1794 sg = SC->request_buffer;
1796 for (i = 0; i < SC->use_sg; i++) {
1797 scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
1798 scb->sg_list[i].length = sg[i].length;
1800 if (scb->data_len + sg[i].length > ha->max_xfer) {
1802 * Data Breakup required
1804 scb->breakup = i;
1805 break;
1808 scb->data_len += sg[i].length;
1811 if (!scb->breakup)
1812 scb->sg_len = SC->use_sg;
1813 else
1814 scb->sg_len = scb->breakup;
1816 scb->dcdb.transfer_length = scb->data_len;
1817 scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
1818 } else {
1819 if (SC->request_bufflen) {
1820 if (SC->request_bufflen > ha->max_xfer) {
1822 * Data breakup required
1824 scb->breakup = 1;
1825 scb->data_len = ha->max_xfer;
1826 } else {
1827 scb->data_len = SC->request_bufflen;
1830 scb->dcdb.transfer_length = scb->data_len;
1831 scb->data_busaddr = VIRT_TO_BUS(SC->request_buffer);
1832 scb->sg_len = 0;
1833 } else {
1834 scb->data_busaddr = 0L;
1835 scb->sg_len = 0;
1836 scb->data_len = 0;
1837 scb->dcdb.transfer_length = 0;
1842 if ((scb->scsi_cmd->request.cmd == READ) && (SC->request_bufflen))
1843 scb->dcdb.cmd_attribute |= DATA_IN;
1845 if ((scb->scsi_cmd->request.cmd == WRITE) && (SC->request_bufflen))
1846 scb->dcdb.cmd_attribute |= DATA_OUT;
1848 if (scb->data_len >= IPS_MAX_XFER) {
1849 scb->dcdb.cmd_attribute |= TRANSFER_64K;
1850 scb->dcdb.transfer_length = 0;
1853 ret = ips_send_cmd(ha, scb);
1855 if (ret == IPS_SUCCESS)
1856 ips_putq_scb_head(&ha->scb_activelist, scb);
1858 switch(ret) {
1859 case IPS_FAILURE:
1860 if (scb->scsi_cmd) {
1861 scb->scsi_cmd->result = DID_ERROR << 16;
1862 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1865 ips_freescb(ha, scb);
1866 break;
1867 case IPS_SUCCESS_IMM:
1868 if (scb->scsi_cmd)
1869 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
1870 ips_freescb(ha, scb);
1871 break;
1872 default:
1873 break;
1874 } /* end case */
1875 } /* end while */
1878 /****************************************************************************/
1879 /* */
1880 /* Routine Name: ips_putq_scb_head */
1881 /* */
1882 /* Routine Description: */
1883 /* */
1884 /* Add an item to the head of the queue */
1885 /* */
1886 /* ASSUMED to be called from within a lock */
1887 /* */
1888 /****************************************************************************/
1889 static inline void
1890 ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
1891 DBG("ips_putq_scb_head");
1893 if (!item)
1894 return ;
1896 item->q_next = queue->head;
1897 queue->head = item;
1899 if (!queue->tail)
1900 queue->tail = item;
1902 queue->count++;
1905 /****************************************************************************/
1906 /* */
1907 /* Routine Name: ips_putq_scb_tail */
1908 /* */
1909 /* Routine Description: */
1910 /* */
1911 /* Add an item to the tail of the queue */
1912 /* */
1913 /* ASSUMED to be called from within a lock */
1914 /* */
1915 /****************************************************************************/
1916 static inline void
1917 ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
1918 DBG("ips_putq_scb_tail");
1920 if (!item)
1921 return ;
1923 item->q_next = NULL;
1925 if (queue->tail)
1926 queue->tail->q_next = item;
1928 queue->tail = item;
1930 if (!queue->head)
1931 queue->head = item;
1933 queue->count++;
1936 /****************************************************************************/
1937 /* */
1938 /* Routine Name: ips_removeq_scb_head */
1939 /* */
1940 /* Routine Description: */
1941 /* */
1942 /* Remove the head of the queue */
1943 /* */
1944 /* ASSUMED to be called from within a lock */
1945 /* */
1946 /****************************************************************************/
1947 static inline ips_scb_t *
1948 ips_removeq_scb_head(ips_scb_queue_t *queue) {
1949 ips_scb_t *item;
1951 DBG("ips_removeq_scb_head");
1953 item = queue->head;
1955 if (!item)
1956 return (NULL);
1958 queue->head = item->q_next;
1959 item->q_next = NULL;
1961 if (queue->tail == item)
1962 queue->tail = NULL;
1964 queue->count--;
1966 return (item);
1969 /****************************************************************************/
1970 /* */
1971 /* Routine Name: ips_removeq_scb */
1972 /* */
1973 /* Routine Description: */
1974 /* */
1975 /* Remove an item from a queue */
1976 /* */
1977 /* ASSUMED to be called from within a lock */
1978 /* */
1979 /****************************************************************************/
1980 static inline ips_scb_t *
1981 ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
1982 ips_scb_t *p;
1984 DBG("ips_removeq_scb");
1986 if (!item)
1987 return (NULL);
1989 if (item == queue->head)
1990 return (ips_removeq_scb_head(queue));
1992 p = queue->head;
1994 while ((p) && (item != p->q_next))
1995 p = p->q_next;
1997 if (p) {
1998 /* found a match */
1999 p->q_next = item->q_next;
2001 if (!item->q_next)
2002 queue->tail = p;
2004 item->q_next = NULL;
2005 queue->count--;
2007 return (item);
2010 return (NULL);
2013 /****************************************************************************/
2014 /* */
2015 /* Routine Name: ips_putq_wait_head */
2016 /* */
2017 /* Routine Description: */
2018 /* */
2019 /* Add an item to the head of the queue */
2020 /* */
2021 /* ASSUMED to be called from within a lock */
2022 /* */
2023 /****************************************************************************/
2024 static inline void
2025 ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
2026 DBG("ips_putq_wait_head");
2028 if (!item)
2029 return ;
2031 item->host_scribble = (char *) queue->head;
2032 queue->head = item;
2034 if (!queue->tail)
2035 queue->tail = item;
2037 queue->count++;
2040 /****************************************************************************/
2041 /* */
2042 /* Routine Name: ips_putq_wait_tail */
2043 /* */
2044 /* Routine Description: */
2045 /* */
2046 /* Add an item to the tail of the queue */
2047 /* */
2048 /* ASSUMED to be called from within a lock */
2049 /* */
2050 /****************************************************************************/
2051 static inline void
2052 ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
2053 DBG("ips_putq_wait_tail");
2055 if (!item)
2056 return ;
2058 item->host_scribble = NULL;
2060 if (queue->tail)
2061 queue->tail->host_scribble = (char *)item;
2063 queue->tail = item;
2065 if (!queue->head)
2066 queue->head = item;
2068 queue->count++;
2071 /****************************************************************************/
2072 /* */
2073 /* Routine Name: ips_removeq_wait_head */
2074 /* */
2075 /* Routine Description: */
2076 /* */
2077 /* Remove the head of the queue */
2078 /* */
2079 /* ASSUMED to be called from within a lock */
2080 /* */
2081 /****************************************************************************/
2082 static inline Scsi_Cmnd *
2083 ips_removeq_wait_head(ips_wait_queue_t *queue) {
2084 Scsi_Cmnd *item;
2086 DBG("ips_removeq_wait_head");
2088 item = queue->head;
2090 if (!item)
2091 return (NULL);
2093 queue->head = (Scsi_Cmnd *) item->host_scribble;
2094 item->host_scribble = NULL;
2096 if (queue->tail == item)
2097 queue->tail = NULL;
2099 queue->count--;
2101 return (item);
2104 /****************************************************************************/
2105 /* */
2106 /* Routine Name: ips_removeq_wait */
2107 /* */
2108 /* Routine Description: */
2109 /* */
2110 /* Remove an item from a queue */
2111 /* */
2112 /* ASSUMED to be called from within a lock */
2113 /* */
2114 /****************************************************************************/
2115 static inline Scsi_Cmnd *
2116 ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
2117 Scsi_Cmnd *p;
2119 DBG("ips_removeq_wait");
2121 if (!item)
2122 return (NULL);
2124 if (item == queue->head)
2125 return (ips_removeq_wait_head(queue));
2127 p = queue->head;
2129 while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
2130 p = (Scsi_Cmnd *) p->host_scribble;
2132 if (p) {
2133 /* found a match */
2134 p->host_scribble = item->host_scribble;
2136 if (!item->host_scribble)
2137 queue->tail = p;
2139 item->host_scribble = NULL;
2140 queue->count--;
2142 return (item);
2145 return (NULL);
2148 /****************************************************************************/
2149 /* */
2150 /* Routine Name: ipsintr_blocking */
2151 /* */
2152 /* Routine Description: */
2153 /* */
2154 /* Finalize an interrupt for internal commands */
2155 /* */
2156 /****************************************************************************/
2157 static void
2158 ipsintr_blocking(ips_ha_t *ha, ips_scb_t *scb) {
2159 DBG("ipsintr_blocking");
2161 if ((ha->waitflag == TRUE) &&
2162 (ha->cmd_in_progress == scb->cdb[0])) {
2163 ha->waitflag = FALSE;
2165 return ;
2169 /****************************************************************************/
2170 /* */
2171 /* Routine Name: ipsintr_done */
2172 /* */
2173 /* Routine Description: */
2174 /* */
2175 /* Finalize an interrupt for non-internal commands */
2176 /* */
2177 /****************************************************************************/
2178 static void
2179 ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) {
2180 DBG("ipsintr_done");
2182 if (scb->scsi_cmd == NULL) {
2183 /* unexpected interrupt */
2184 printk(KERN_WARNING "(%s%d) Spurious interrupt; scsi_cmd not set.\n",
2185 ips_name, ha->host_num);
2187 return;
2190 ips_done(ha, scb);
2193 /****************************************************************************/
2194 /* */
2195 /* Routine Name: ips_done */
2196 /* */
2197 /* Routine Description: */
2198 /* */
2199 /* Do housekeeping on completed commands */
2200 /* */
2201 /****************************************************************************/
2202 static void
2203 ips_done(ips_ha_t *ha, ips_scb_t *scb) {
2204 int ret;
2206 DBG("ips_done");
2208 if (!scb)
2209 return ;
2211 #ifndef NO_IPS_CMDLINE
2212 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
2213 ips_cleanup_passthru(scb);
2214 ha->num_ioctl--;
2215 } else {
2216 #endif
2218 * Check to see if this command had too much
2219 * data and had to be broke up. If so, queue
2220 * the rest of the data and continue.
2222 if (scb->breakup) {
2223 /* we had a data breakup */
2224 u16 bk_save;
2226 bk_save = scb->breakup;
2227 scb->breakup = 0;
2229 if (scb->scsi_cmd->use_sg) {
2230 /* S/G request */
2231 struct scatterlist *sg;
2232 int i;
2234 sg = scb->scsi_cmd->request_buffer;
2236 scb->data_len = 0;
2238 for (i = bk_save; i < scb->scsi_cmd->use_sg; i++) {
2239 scb->sg_list[i - bk_save].address = VIRT_TO_BUS(sg[i].address);
2240 scb->sg_list[i - bk_save].length = sg[i].length;
2242 if (scb->data_len + sg[i].length > ha->max_xfer) {
2244 * Data Breakup required
2246 scb->breakup = i;
2247 break;
2250 scb->data_len += sg[i].length;
2253 if (!scb->breakup)
2254 scb->sg_len = scb->scsi_cmd->use_sg - bk_save;
2255 else
2256 scb->sg_len = scb->breakup - bk_save;
2258 scb->dcdb.transfer_length = scb->data_len;
2259 scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
2260 } else {
2261 /* Non S/G Request */
2262 if (scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer)) {
2263 /* Further breakup required */
2264 scb->data_len = ha->max_xfer;
2265 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
2266 scb->breakup = bk_save + 1;
2267 } else {
2268 scb->data_len = scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer);
2269 scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
2272 scb->dcdb.transfer_length = scb->data_len;
2273 scb->sg_len = 0;
2276 if ((scb->scsi_cmd->request.cmd == READ) && (scb->data_len))
2277 scb->dcdb.cmd_attribute |= DATA_IN;
2279 if ((scb->scsi_cmd->request.cmd == WRITE) && (scb->data_len))
2280 scb->dcdb.cmd_attribute |= DATA_OUT;
2282 if (scb->data_len >= IPS_MAX_XFER) {
2283 scb->dcdb.cmd_attribute |= TRANSFER_64K;
2284 scb->dcdb.transfer_length = 0;
2287 ret = ips_send_cmd(ha, scb);
2289 switch(ret) {
2290 case IPS_FAILURE:
2291 if (scb->scsi_cmd) {
2292 scb->scsi_cmd->result = DID_ERROR << 16;
2293 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2296 ips_freescb(ha, scb);
2297 break;
2298 case IPS_SUCCESS_IMM:
2299 if (scb->scsi_cmd) {
2300 scb->scsi_cmd->result = DID_ERROR << 16;
2301 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2304 ips_freescb(ha, scb);
2305 break;
2306 default:
2307 break;
2308 } /* end case */
2310 return ;
2312 #ifndef NO_IPS_CMDLINE
2313 } /* end if passthru */
2314 #endif
2316 /* call back to SCSI layer */
2317 scb->scsi_cmd->scsi_done(scb->scsi_cmd);
2318 ips_freescb(ha, scb);
2320 /* do the next command */
2321 ips_next(ha);
2324 /****************************************************************************/
2325 /* */
2326 /* Routine Name: ips_map_status */
2327 /* */
2328 /* Routine Description: */
2329 /* */
2330 /* Map ServeRAID error codes to Linux Error Codes */
2331 /* */
2332 /****************************************************************************/
2333 static int
2334 ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
2335 int errcode;
2337 DBG("ips_map_status");
2339 if (scb->bus) {
2340 /* copy SCSI status and sense data for DCDB commands */
2341 memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info,
2342 sizeof(scb->scsi_cmd->sense_buffer));
2343 scb->scsi_cmd->result = scb->dcdb.scsi_status;
2344 } else
2345 scb->scsi_cmd->result = 0;
2347 /* default driver error */
2348 errcode = DID_ERROR;
2350 switch (scb->basic_status & GSC_STATUS_MASK) {
2351 case CMD_TIMEOUT:
2352 errcode = DID_TIME_OUT;
2353 break;
2355 case INVAL_OPCO:
2356 case INVAL_CMD_BLK:
2357 case INVAL_PARM_BLK:
2358 case LOG_DRV_ERROR:
2359 case CMD_CMPLT_WERROR:
2360 break;
2362 case PHYS_DRV_ERROR:
2364 * For physical drive errors that
2365 * are not on a logical drive should
2366 * be DID_OK. The SCSI errcode will
2367 * show what the real error is.
2369 if (scb->bus)
2370 errcode = DID_OK;
2372 switch (scb->extended_status) {
2373 case SELECTION_TIMEOUT:
2374 if (scb->bus) {
2375 scb->scsi_cmd->result |= DID_TIME_OUT << 16;
2377 return (0);
2379 break;
2380 case DATA_OVER_UNDER_RUN:
2381 if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) {
2382 if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
2383 ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
2384 /* underflow -- no error */
2385 /* restrict access to physical DASD */
2386 errcode = DID_TIME_OUT;
2387 break;
2390 /* normal underflow Occured */
2391 if (scb->dcdb.transfer_length >= scb->scsi_cmd->underflow) {
2392 scb->scsi_cmd->result |= DID_OK << 16;
2394 return (0);
2398 break;
2399 case EXT_RECOVERY:
2400 /* don't fail recovered errors */
2401 if (scb->bus) {
2402 scb->scsi_cmd->result |= DID_OK << 16;
2404 return (0);
2406 break;
2408 case EXT_HOST_RESET:
2409 case EXT_DEVICE_RESET:
2410 errcode = DID_RESET;
2411 break;
2413 case EXT_CHECK_CONDITION:
2414 break;
2415 } /* end switch */
2416 } /* end switch */
2418 scb->scsi_cmd->result |= (errcode << 16);
2420 return (1);
2423 /****************************************************************************/
2424 /* */
2425 /* Routine Name: ips_send */
2426 /* */
2427 /* Routine Description: */
2428 /* */
2429 /* Wrapper for ips_send_cmd */
2430 /* */
2431 /****************************************************************************/
2432 static int
2433 ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) {
2434 int ret;
2436 DBG("ips_send");
2438 scb->callback = callback;
2440 ret = ips_send_cmd(ha, scb);
2442 return (ret);
2445 /****************************************************************************/
2446 /* */
2447 /* Routine Name: ips_send_wait */
2448 /* */
2449 /* Routine Description: */
2450 /* */
2451 /* Send a command to the controller and wait for it to return */
2452 /* */
2453 /****************************************************************************/
2454 static int
2455 ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) {
2456 int ret;
2458 DBG("ips_send_wait");
2460 ha->waitflag = TRUE;
2461 ha->cmd_in_progress = scb->cdb[0];
2463 ret = ips_send(ha, scb, ipsintr_blocking);
2465 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
2466 return (ret);
2468 ret = ips_wait(ha, timeout, IPS_INTR_OFF);
2470 return (ret);
2473 /****************************************************************************/
2474 /* */
2475 /* Routine Name: ips_send_cmd */
2476 /* */
2477 /* Routine Description: */
2478 /* */
2479 /* Map SCSI commands to ServeRAID commands for logical drives */
2480 /* */
2481 /****************************************************************************/
2482 static int
2483 ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
2484 int ret;
2486 DBG("ips_send_cmd");
2488 ret = IPS_SUCCESS;
2490 if (!scb->scsi_cmd) {
2491 /* internal command */
2493 if (scb->bus > 0) {
2494 /* ServeRAID commands can't be issued */
2495 /* to real devices -- fail them */
2496 if ((ha->waitflag == TRUE) &&
2497 (ha->cmd_in_progress == scb->cdb[0])) {
2498 ha->waitflag = FALSE;
2501 return (1);
2503 #ifndef NO_IPS_CMDLINE
2504 } else if ((scb->bus == 0) && (!ips_is_passthru(scb->scsi_cmd))) {
2505 #else
2506 } else if (scb->bus == 0) {
2507 #endif
2508 /* command to logical bus -- interpret */
2509 ret = IPS_SUCCESS_IMM;
2511 switch (scb->scsi_cmd->cmnd[0]) {
2512 case ALLOW_MEDIUM_REMOVAL:
2513 case REZERO_UNIT:
2514 case ERASE:
2515 case WRITE_FILEMARKS:
2516 case SPACE:
2517 scb->scsi_cmd->result = DID_ERROR << 16;
2518 break;
2520 case START_STOP:
2521 scb->scsi_cmd->result = DID_OK << 16;
2523 case TEST_UNIT_READY:
2524 case INQUIRY:
2525 if (scb->target_id == IPS_ADAPTER_ID) {
2527 * Either we have a TUR
2528 * or we have a SCSI inquiry
2530 if (scb->scsi_cmd->cmnd[0] == TEST_UNIT_READY)
2531 scb->scsi_cmd->result = DID_OK << 16;
2533 if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
2534 INQUIRYDATA inq;
2536 memset(&inq, 0, sizeof(INQUIRYDATA));
2538 inq.DeviceType = TYPE_PROCESSOR;
2539 inq.DeviceTypeQualifier = 0;
2540 inq.RemoveableMedia = 0;
2541 inq.Versions = 0x1; /* SCSI I */
2542 inq.AdditionalLength = 31;
2543 strncpy(inq.VendorId, "IBM ", 8);
2544 strncpy(inq.ProductId, "SERVERAID ", 16);
2545 strncpy(inq.ProductRevisionLevel, "1.00", 4);
2547 memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
2549 scb->scsi_cmd->result = DID_OK << 16;
2551 } else {
2552 scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
2553 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
2554 scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
2555 scb->cmd.logical_info.reserved = 0;
2556 scb->cmd.logical_info.reserved2 = 0;
2557 ret = IPS_SUCCESS;
2560 break;
2562 case REQUEST_SENSE:
2563 ips_reqsen(ha, scb);
2564 scb->scsi_cmd->result = DID_OK << 16;
2565 break;
2567 case READ_6:
2568 case WRITE_6:
2569 if (!scb->sg_len) {
2570 scb->cmd.basic_io.op_code =
2571 (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_READ : IPS_WRITE;
2572 } else {
2573 scb->cmd.basic_io.op_code =
2574 (scb->scsi_cmd->cmnd[0] == READ_6) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
2577 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
2578 scb->cmd.basic_io.log_drv = scb->target_id;
2579 scb->cmd.basic_io.sg_count = scb->sg_len;
2580 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
2582 if (scb->cmd.basic_io.lba)
2583 scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
2584 else
2585 scb->cmd.basic_io.lba = (((scb->scsi_cmd->cmnd[1] & 0x1f) << 16) |
2586 (scb->scsi_cmd->cmnd[2] << 8) |
2587 (scb->scsi_cmd->cmnd[3]));
2589 scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
2591 if (scb->cmd.basic_io.sector_count == 0)
2592 scb->cmd.basic_io.sector_count = 256;
2594 scb->cmd.basic_io.reserved = 0;
2595 ret = IPS_SUCCESS;
2596 break;
2598 case READ_10:
2599 case WRITE_10:
2600 if (!scb->sg_len) {
2601 scb->cmd.basic_io.op_code =
2602 (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_READ : IPS_WRITE;
2603 } else {
2604 scb->cmd.basic_io.op_code =
2605 (scb->scsi_cmd->cmnd[0] == READ_10) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
2608 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
2609 scb->cmd.basic_io.log_drv = scb->target_id;
2610 scb->cmd.basic_io.sg_count = scb->sg_len;
2611 scb->cmd.basic_io.sg_addr = scb->data_busaddr;
2613 if (scb->cmd.basic_io.lba)
2614 scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
2615 else
2616 scb->cmd.basic_io.lba = ((scb->scsi_cmd->cmnd[2] << 24) |
2617 (scb->scsi_cmd->cmnd[3] << 16) |
2618 (scb->scsi_cmd->cmnd[4] << 8) |
2619 scb->scsi_cmd->cmnd[5]);
2621 scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
2623 scb->cmd.basic_io.reserved = 0;
2625 if (scb->cmd.basic_io.sector_count == 0) {
2627 * This is a null condition
2628 * we don't have to do anything
2629 * so just return
2631 scb->scsi_cmd->result = DID_OK << 16;
2632 } else
2633 ret = IPS_SUCCESS;
2635 break;
2637 case RESERVE:
2638 case RELEASE:
2639 scb->scsi_cmd->result = DID_OK << 16;
2640 break;
2642 case MODE_SENSE:
2643 scb->cmd.basic_io.op_code = ENQUIRY;
2644 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
2645 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
2646 ret = IPS_SUCCESS;
2647 break;
2649 case READ_CAPACITY:
2650 scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
2651 scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
2652 scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
2653 scb->cmd.logical_info.reserved = 0;
2654 scb->cmd.logical_info.reserved2 = 0;
2655 scb->cmd.logical_info.reserved3 = 0;
2656 ret = IPS_SUCCESS;
2657 break;
2659 case SEND_DIAGNOSTIC:
2660 case REASSIGN_BLOCKS:
2661 case FORMAT_UNIT:
2662 case SEEK_10:
2663 case VERIFY:
2664 case READ_DEFECT_DATA:
2665 case READ_BUFFER:
2666 case WRITE_BUFFER:
2667 scb->scsi_cmd->result = DID_OK << 16;
2668 break;
2670 default:
2671 scb->scsi_cmd->result = DID_ERROR << 16;
2672 break;
2673 } /* end switch */
2674 } /* end if */
2676 if (ret == IPS_SUCCESS_IMM)
2677 return (ret);
2679 /* setup DCDB */
2680 if (scb->bus > 0) {
2681 if (!scb->sg_len)
2682 scb->cmd.dcdb.op_code = DIRECT_CDB;
2683 else
2684 scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER;
2686 scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
2687 scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
2688 scb->cmd.dcdb.reserved = 0;
2689 scb->cmd.dcdb.reserved2 = 0;
2690 scb->cmd.dcdb.reserved3 = 0;
2692 scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id;
2693 scb->dcdb.cmd_attribute |= DISCONNECT_ALLOWED;
2695 if (scb->timeout) {
2696 if (scb->timeout <= 10)
2697 scb->dcdb.cmd_attribute |= TIMEOUT_10;
2698 else if (scb->timeout <= 60)
2699 scb->dcdb.cmd_attribute |= TIMEOUT_60;
2700 else
2701 scb->dcdb.cmd_attribute |= TIMEOUT_20M;
2704 if (!(scb->dcdb.cmd_attribute & TIMEOUT_20M))
2705 scb->dcdb.cmd_attribute |= TIMEOUT_20M;
2707 scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer);
2708 scb->dcdb.buffer_pointer = scb->data_busaddr;
2709 scb->dcdb.sg_count = scb->sg_len;
2710 scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
2711 memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len);
2714 return (ips_issue(ha, scb));
2717 /****************************************************************************/
2718 /* */
2719 /* Routine Name: ips_chk_status */
2720 /* */
2721 /* Routine Description: */
2722 /* */
2723 /* Check the status of commands to logical drives */
2724 /* */
2725 /****************************************************************************/
2726 static int
2727 ips_chkstatus(ips_ha_t *ha) {
2728 ips_scb_t *scb;
2729 ips_stat_t *sp = &ha->sp;
2730 u8 basic_status;
2731 u8 ext_status;
2732 int command_id;
2733 int errcode;
2734 int ret;
2736 DBG("ips_chkstatus");
2738 command_id = ips_statupd(ha);
2740 if (command_id > (MAX_CMDS-1)) {
2741 printk(KERN_NOTICE "(%s%d) invalid command id received: %d\n",
2742 ips_name, ha->host_num, command_id);
2744 return (-1);
2747 scb = &ha->scbs[command_id];
2748 sp->scb_addr = (u32) scb;
2749 sp->residue_len = 0;
2750 scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & BASIC_STATUS_MASK;
2751 scb->extended_status = ext_status = ha->adapt->p_status_tail->extended_status;
2753 /* Remove the item from the active queue */
2754 ips_removeq_scb(&ha->scb_activelist, scb);
2756 if (!scb->scsi_cmd)
2757 /* internal commands are handled in do_ipsintr */
2758 return (0);
2760 #ifndef NO_IPS_CMDLINE
2761 if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
2762 /* passthru - just returns the raw result */
2763 return (0);
2764 #endif
2766 errcode = DID_OK;
2767 ret = 0;
2769 if (((basic_status & GSC_STATUS_MASK) == SSUCCESS) ||
2770 ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR)) {
2772 if (scb->bus == 0) {
2773 #if IPS_DEBUG >= 1
2774 if ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR) {
2775 printk(KERN_NOTICE "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n",
2776 ips_name, ha->host_num,
2777 scb->cmd.basic_io.op_code, basic_status, ext_status);
2779 #endif
2781 switch (scb->scsi_cmd->cmnd[0]) {
2782 case ALLOW_MEDIUM_REMOVAL:
2783 case REZERO_UNIT:
2784 case ERASE:
2785 case WRITE_FILEMARKS:
2786 case SPACE:
2787 errcode = DID_ERROR;
2788 ret = 1;
2789 break;
2791 case START_STOP:
2792 break;
2794 case TEST_UNIT_READY:
2795 if (!ips_online(ha, scb)) {
2796 errcode = DID_TIME_OUT;
2797 ret = 1;
2799 break;
2801 case INQUIRY:
2802 if (ips_online(ha, scb)) {
2803 ips_inquiry(ha, scb);
2804 } else {
2805 errcode = DID_TIME_OUT;
2806 ret = 1;
2808 break;
2810 case REQUEST_SENSE:
2811 ips_reqsen(ha, scb);
2812 break;
2814 case READ_6:
2815 case WRITE_6:
2816 case READ_10:
2817 case WRITE_10:
2818 case RESERVE:
2819 case RELEASE:
2820 break;
2822 case MODE_SENSE:
2823 if (!ips_online(ha, scb) || !ips_msense(ha, scb)) {
2824 errcode = DID_ERROR;
2825 ret = 1;
2827 break;
2829 case READ_CAPACITY:
2830 if (ips_online(ha, scb))
2831 ips_rdcap(ha, scb);
2832 else {
2833 errcode = DID_TIME_OUT;
2834 ret = 1;
2836 break;
2838 case SEND_DIAGNOSTIC:
2839 case REASSIGN_BLOCKS:
2840 break;
2842 case FORMAT_UNIT:
2843 errcode = DID_ERROR;
2844 ret = 1;
2845 break;
2847 case SEEK_10:
2848 case VERIFY:
2849 case READ_DEFECT_DATA:
2850 case READ_BUFFER:
2851 case WRITE_BUFFER:
2852 break;
2854 default:
2855 errcode = DID_ERROR;
2856 ret = 1;
2857 } /* end switch */
2859 scb->scsi_cmd->result = errcode << 16;
2860 } else { /* bus == 0 */
2861 /* restrict access to physical drives */
2862 if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
2863 ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
2865 scb->scsi_cmd->result = DID_TIME_OUT << 16;
2867 ret = 1;
2869 } /* else */
2870 } else { /* recovered error / success */
2871 #if IPS_DEBUG >= 1
2872 if (scb->bus == 0) {
2873 printk(KERN_NOTICE "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n",
2874 ips_name, ha->host_num,
2875 scb->cmd.basic_io.op_code, basic_status, ext_status);
2877 #endif
2879 ret = ips_map_status(scb, sp);
2880 } /* else */
2882 return (ret);
2885 /****************************************************************************/
2886 /* */
2887 /* Routine Name: ips_online */
2888 /* */
2889 /* Routine Description: */
2890 /* */
2891 /* Determine if a logical drive is online */
2892 /* */
2893 /****************************************************************************/
2894 static int
2895 ips_online(ips_ha_t *ha, ips_scb_t *scb) {
2896 DBG("ips_online");
2898 if (scb->target_id >= MAX_LOGICAL_DRIVES)
2899 return (0);
2901 if ((scb->basic_status & GSC_STATUS_MASK) > 1) {
2902 memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info));
2904 return (0);
2907 if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive &&
2908 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != OFF_LINE &&
2909 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != FREE &&
2910 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != CRS &&
2911 ha->adapt->logical_drive_info.drive_info[scb->target_id].state != SYS)
2912 return (1);
2913 else
2914 return (0);
2917 /****************************************************************************/
2918 /* */
2919 /* Routine Name: ips_inquiry */
2920 /* */
2921 /* Routine Description: */
2922 /* */
2923 /* Simulate an inquiry command to a logical drive */
2924 /* */
2925 /****************************************************************************/
2926 static int
2927 ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
2928 INQUIRYDATA inq;
2930 DBG("ips_inquiry");
2932 memset(&inq, 0, sizeof(INQUIRYDATA));
2934 inq.DeviceType = TYPE_DISK;
2935 inq.DeviceTypeQualifier = 0;
2936 inq.RemoveableMedia = 0;
2937 inq.Versions = 0x1; /* SCSI I */
2938 inq.AdditionalLength = 31;
2939 strncpy(inq.VendorId, "IBM ", 8);
2940 strncpy(inq.ProductId, "SERVERAID ", 16);
2941 strncpy(inq.ProductRevisionLevel, "1.00", 4);
2943 memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
2945 return (1);
2948 /****************************************************************************/
2949 /* */
2950 /* Routine Name: ips_rdcap */
2951 /* */
2952 /* Routine Description: */
2953 /* */
2954 /* Simulate a read capacity command to a logical drive */
2955 /* */
2956 /****************************************************************************/
2957 static int
2958 ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) {
2959 CAPACITY_T *cap;
2961 DBG("ips_rdcap");
2963 if (scb->scsi_cmd->bufflen < 8)
2964 return (0);
2966 cap = (CAPACITY_T *) scb->scsi_cmd->request_buffer;
2968 cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1);
2969 cap->len = htonl((u32) IPS_BLKSIZE);
2971 return (1);
2974 /****************************************************************************/
2975 /* */
2976 /* Routine Name: ips_msense */
2977 /* */
2978 /* Routine Description: */
2979 /* */
2980 /* Simulate a mode sense command to a logical drive */
2981 /* */
2982 /****************************************************************************/
2983 static int
2984 ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
2985 u16 heads;
2986 u16 sectors;
2987 u32 cylinders;
2988 ips_mdata_t mdata;
2990 DBG("ips_msense");
2992 if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 &&
2993 (ha->enq->ucMiscFlag & 0x8) == 0) {
2994 heads = NORM_MODE_HEADS;
2995 sectors = NORM_MODE_SECTORS;
2996 } else {
2997 heads = COMP_MODE_HEADS;
2998 sectors = COMP_MODE_SECTORS;
3001 cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors);
3003 mdata.plh.plh_type = 0;
3004 mdata.plh.plh_wp = 0;
3005 mdata.plh.plh_bdl = 8;
3007 switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
3008 case 0x03: /* page 3 */
3009 mdata.pdata.pg3.pg_pc = 0x3;
3010 mdata.pdata.pg3.pg_res1 = 0;
3011 mdata.pdata.pg3.pg_len = sizeof(DADF_T);
3012 mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len;
3013 mdata.pdata.pg3.pg_trk_z = 0;
3014 mdata.pdata.pg3.pg_asec_z = 0;
3015 mdata.pdata.pg3.pg_atrk_z = 0;
3016 mdata.pdata.pg3.pg_atrk_v = 0;
3017 mdata.pdata.pg3.pg_sec_t = htons(sectors);
3018 mdata.pdata.pg3.pg_bytes_s = htons(IPS_BLKSIZE);
3019 mdata.pdata.pg3.pg_intl = htons(1);
3020 mdata.pdata.pg3.pg_trkskew = 0;
3021 mdata.pdata.pg3.pg_cylskew = 0;
3022 mdata.pdata.pg3.pg_res2 = 0;
3023 mdata.pdata.pg3.pg_ins = 0;
3024 mdata.pdata.pg3.pg_surf = 0;
3025 mdata.pdata.pg3.pg_rmb = 0;
3026 mdata.pdata.pg3.pg_hsec = 0;
3027 mdata.pdata.pg3.pg_ssec = 1;
3028 break;
3030 case 0x4:
3031 mdata.pdata.pg4.pg_pc = 0x4;
3032 mdata.pdata.pg4.pg_res1 = 0;
3033 mdata.pdata.pg4.pg_len = sizeof(RDDG_T);
3034 mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len;
3035 mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff;
3036 mdata.pdata.pg4.pg_cyll = cylinders & 0xff;
3037 mdata.pdata.pg4.pg_head = heads;
3038 mdata.pdata.pg4.pg_wrpcompu = 0;
3039 mdata.pdata.pg4.pg_wrpcompl = 0;
3040 mdata.pdata.pg4.pg_redwrcur = 0;
3041 mdata.pdata.pg4.pg_drstep = htons(1);
3042 mdata.pdata.pg4.pg_landu = 0;
3043 mdata.pdata.pg4.pg_landl = 0;
3044 mdata.pdata.pg4.pg_res2 = 0;
3045 break;
3046 default:
3047 return (0);
3048 } /* end switch */
3050 memcpy(scb->scsi_cmd->request_buffer, &mdata, scb->scsi_cmd->request_bufflen);
3052 return (1);
3055 /****************************************************************************/
3056 /* */
3057 /* Routine Name: ips_reqsen */
3058 /* */
3059 /* Routine Description: */
3060 /* */
3061 /* Simulate a request sense command to a logical drive */
3062 /* */
3063 /****************************************************************************/
3064 static int
3065 ips_reqsen(ips_ha_t *ha, ips_scb_t *scb) {
3066 char *sp;
3068 DBG("ips_reqsen");
3070 sp = (char *) scb->scsi_cmd->sense_buffer;
3071 memset(sp, 0, sizeof(scb->scsi_cmd->sense_buffer));
3073 sp[0] = 0x70;
3074 sp[3] = NO_SENSE;
3075 sp[7] = 0xe;
3076 sp[12] = NO_SENSE;
3078 return (0);
3081 /****************************************************************************/
3082 /* */
3083 /* Routine Name: ips_free */
3084 /* */
3085 /* Routine Description: */
3086 /* */
3087 /* Free any allocated space for this controller */
3088 /* */
3089 /****************************************************************************/
3090 static void
3091 ips_free(ips_ha_t *ha) {
3092 int i;
3094 DBG("ips_free");
3096 if (ha) {
3097 if (ha->enq) {
3098 kfree(ha->enq);
3099 ha->enq = NULL;
3102 if (ha->conf) {
3103 kfree(ha->conf);
3104 ha->conf = NULL;
3107 if (ha->adapt) {
3108 kfree(ha->adapt);
3109 ha->adapt = NULL;
3112 if (ha->nvram) {
3113 kfree(ha->nvram);
3114 ha->nvram = NULL;
3117 if (ha->subsys) {
3118 kfree(ha->subsys);
3119 ha->subsys = NULL;
3122 if (ha->dummy) {
3123 kfree(ha->dummy);
3124 ha->dummy = NULL;
3127 if (ha->scbs) {
3128 for (i = 0; i < ha->max_cmds; i++) {
3129 if (ha->scbs[i].sg_list)
3130 kfree(ha->scbs[i].sg_list);
3133 kfree(ha->scbs);
3134 ha->scbs = NULL;
3135 } /* end if */
3139 /****************************************************************************/
3140 /* */
3141 /* Routine Name: ips_allocatescbs */
3142 /* */
3143 /* Routine Description: */
3144 /* */
3145 /* Allocate the command blocks */
3146 /* */
3147 /****************************************************************************/
3148 static int
3149 ips_allocatescbs(ips_ha_t *ha) {
3150 ips_scb_t *scb_p;
3151 int i;
3153 DBG("ips_allocatescbs");
3155 /* Allocate memory for the CCBs */
3156 ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_KERNEL|GFP_DMA);
3158 memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
3160 for (i = 0; i < ha->max_cmds; i++) {
3161 scb_p = &ha->scbs[i];
3163 /* allocate S/G list */
3164 scb_p->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
3166 if (! scb_p->sg_list)
3167 return (0);
3169 /* add to the free list */
3170 if (i < ha->max_cmds - 1) {
3171 scb_p->q_next = ha->scb_freelist;
3172 ha->scb_freelist = scb_p;
3176 /* success */
3177 return (1);
3180 /****************************************************************************/
3181 /* */
3182 /* Routine Name: ips_init_scb */
3183 /* */
3184 /* Routine Description: */
3185 /* */
3186 /* Initialize a CCB to default values */
3187 /* */
3188 /****************************************************************************/
3189 static void
3190 ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
3191 SG_LIST *sg_list;
3193 DBG("ips_init_scb");
3195 if (scb == NULL)
3196 return ;
3198 sg_list = scb->sg_list;
3200 /* zero fill */
3201 memset(scb, 0, sizeof(ips_scb_t));
3202 memset(ha->dummy, 0, sizeof(BASIC_IO_CMD));
3204 /* Initialize dummy command bucket */
3205 ha->dummy->op_code = 0xFF;
3206 ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy);
3207 ha->dummy->command_id = MAX_CMDS;
3209 /* set bus address of scb */
3210 scb->scb_busaddr = VIRT_TO_BUS(scb);
3211 scb->sg_list = sg_list;
3213 /* Neptune Fix */
3214 scb->cmd.basic_io.cccr = ILE;
3215 scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy);
3218 /****************************************************************************/
3219 /* */
3220 /* Routine Name: ips_get_scb */
3221 /* */
3222 /* Routine Description: */
3223 /* */
3224 /* Initialize a CCB to default values */
3225 /* */
3226 /* ASSUMED to be callled from within a lock */
3227 /* */
3228 /****************************************************************************/
3229 static ips_scb_t *
3230 ips_getscb(ips_ha_t *ha) {
3231 ips_scb_t *scb;
3232 unsigned int cpu_flags;
3234 DBG("ips_getscb");
3236 spin_lock_irqsave(&ha->scb_lock, cpu_flags);
3237 if ((scb = ha->scb_freelist) == NULL) {
3238 spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
3240 return (NULL);
3243 ha->scb_freelist = scb->q_next;
3244 scb->q_next = NULL;
3246 spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
3248 ips_init_scb(ha, scb);
3250 return (scb);
3253 /****************************************************************************/
3254 /* */
3255 /* Routine Name: ips_free_scb */
3256 /* */
3257 /* Routine Description: */
3258 /* */
3259 /* Return an unused CCB back to the free list */
3260 /* */
3261 /* ASSUMED to be called from within a lock */
3262 /* */
3263 /****************************************************************************/
3264 static void
3265 ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
3266 unsigned int cpu_flags;
3268 DBG("ips_freescb");
3270 /* check to make sure this is not our "special" scb */
3271 if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
3272 spin_lock_irqsave(&ha->scb_lock, cpu_flags);
3273 scb->q_next = ha->scb_freelist;
3274 ha->scb_freelist = scb;
3275 spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
3279 /****************************************************************************/
3280 /* */
3281 /* Routine Name: ips_reset_adapter */
3282 /* */
3283 /* Routine Description: */
3284 /* */
3285 /* Reset the controller */
3286 /* */
3287 /****************************************************************************/
3288 static int
3289 ips_reset_adapter(ips_ha_t *ha) {
3290 u8 Isr;
3291 u8 Cbsp;
3292 u8 PostByte[MAX_POST_BYTES];
3293 u8 ConfigByte[MAX_CONFIG_BYTES];
3294 int i, j;
3295 int reset_counter;
3297 DBG("ips_reset_adapter");
3299 #if IPS_DEBUG >= 1
3300 printk(KERN_WARNING "ips_reset_adapter: io addr: %x, irq: %d\n",
3301 ha->io_addr, ha->irq);
3302 #endif
3304 reset_counter = 0;
3306 while (reset_counter < 2) {
3307 reset_counter++;
3309 outb(RST, ha->io_addr + SCPR);
3310 MDELAY(ONE_SEC);
3311 outb(0, ha->io_addr + SCPR);
3312 MDELAY(ONE_SEC);
3314 for (i = 0; i < MAX_POST_BYTES; i++) {
3315 for (j = 0; j < 45; j++) {
3316 Isr = inb(ha->io_addr + HISR);
3317 if (Isr & GHI)
3318 break;
3320 MDELAY(ONE_SEC);
3323 if (j >= 45) {
3324 /* error occured */
3325 if (reset_counter < 2)
3326 continue;
3327 else
3328 /* reset failed */
3329 return (0);
3332 PostByte[i] = inb(ha->io_addr + ISPR);
3333 outb(Isr, ha->io_addr + HISR);
3336 if (PostByte[0] < GOOD_POST_BASIC_STATUS) {
3337 printk("(%s%d) reset controller fails (post status %x %x).\n",
3338 ips_name, ha->host_num, PostByte[0], PostByte[1]);
3340 return (0);
3343 for (i = 0; i < MAX_CONFIG_BYTES; i++) {
3344 for (j = 0; j < 240; j++) {
3345 Isr = inb(ha->io_addr + HISR);
3346 if (Isr & GHI)
3347 break;
3349 MDELAY(ONE_SEC); /* 100 msec */
3352 if (j >= 240) {
3353 /* error occured */
3354 if (reset_counter < 2)
3355 continue;
3356 else
3357 /* reset failed */
3358 return (0);
3361 ConfigByte[i] = inb(ha->io_addr + ISPR);
3362 outb(Isr, ha->io_addr + HISR);
3365 if (ConfigByte[0] == 0 && ConfigByte[1] == 2) {
3366 printk("(%s%d) reset controller fails (status %x %x).\n",
3367 ips_name, ha->host_num, ConfigByte[0], ConfigByte[1]);
3369 return (0);
3372 for (i = 0; i < 240; i++) {
3373 Cbsp = inb(ha->io_addr + CBSP);
3375 if ((Cbsp & OP) == 0)
3376 break;
3378 MDELAY(ONE_SEC);
3381 if (i >= 240) {
3382 /* error occured */
3383 if (reset_counter < 2)
3384 continue;
3385 else
3386 /* reset failed */
3387 return (0);
3390 /* setup CCCR */
3391 outw(0x1010, ha->io_addr + CCCR);
3393 /* Enable busmastering */
3394 outb(EBM, ha->io_addr + SCPR);
3396 /* setup status queues */
3397 ips_statinit(ha);
3399 /* Enable interrupts */
3400 outb(EI, ha->io_addr + HISR);
3402 /* if we get here then everything went OK */
3403 break;
3406 return (1);
3409 /****************************************************************************/
3410 /* */
3411 /* Routine Name: ips_statinit */
3412 /* */
3413 /* Routine Description: */
3414 /* */
3415 /* Initialize the status queues on the controller */
3416 /* */
3417 /****************************************************************************/
3418 static void
3419 ips_statinit(ips_ha_t *ha) {
3420 u32 phys_status_start;
3422 DBG("ips_statinit");
3424 ha->adapt->p_status_start = ha->adapt->status;
3425 ha->adapt->p_status_end = ha->adapt->status + MAX_CMDS;
3426 ha->adapt->p_status_tail = ha->adapt->status;
3428 phys_status_start = VIRT_TO_BUS(ha->adapt->status);
3429 outl(phys_status_start, ha->io_addr + SQSR);
3430 outl(phys_status_start + STATUS_Q_SIZE, ha->io_addr + SQER);
3431 outl(phys_status_start + STATUS_SIZE, ha->io_addr + SQHR);
3432 outl(phys_status_start, ha->io_addr + SQTR);
3434 ha->adapt->hw_status_start = phys_status_start;
3435 ha->adapt->hw_status_tail = phys_status_start;
3438 /****************************************************************************/
3439 /* */
3440 /* Routine Name: ips_statupd */
3441 /* */
3442 /* Routine Description: */
3443 /* */
3444 /* Remove an element from the status queue */
3445 /* */
3446 /****************************************************************************/
3447 static int
3448 ips_statupd(ips_ha_t *ha) {
3449 int command_id;
3451 DBG("ips_statupd");
3453 if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
3454 ha->adapt->p_status_tail++;
3455 ha->adapt->hw_status_tail += sizeof(STATUS);
3456 } else {
3457 ha->adapt->p_status_tail = ha->adapt->p_status_start;
3458 ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
3461 outl(ha->adapt->hw_status_tail, ha->io_addr + SQTR);
3463 command_id = ha->adapt->p_status_tail->command_id;
3465 return (command_id);
3468 /****************************************************************************/
3469 /* */
3470 /* Routine Name: ips_issue */
3471 /* */
3472 /* Routine Description: */
3473 /* */
3474 /* Send a command down to the controller */
3475 /* */
3476 /* ASSUMED to be called from within a lock */
3477 /* */
3478 /****************************************************************************/
3479 static int
3480 ips_issue(ips_ha_t *ha, ips_scb_t *scb) {
3481 u32 TimeOut;
3482 u16 val;
3484 DBG("ips_issue");
3486 #if IPS_DEBUG >= 10
3487 if (scb->scsi_cmd)
3488 printk(KERN_NOTICE "%s: ips_issue: cmd 0x%X id %d (%d %d %d)\n",
3489 ips_name,
3490 scb->cdb[0],
3491 scb->cmd.basic_io.command_id,
3492 scb->bus,
3493 scb->target_id,
3494 scb->lun);
3495 else
3496 printk(KERN_NOTICE "%s: ips_issue: logical cmd id %d\n",
3497 ips_name,
3498 scb->cmd.basic_io.command_id);
3499 #if IPS_DEBUG >= 11
3500 MDELAY(ONE_SEC);
3501 #endif
3502 #endif
3504 TimeOut = 0;
3506 while ((val = inw(ha->io_addr + CCCR)) & SEMAPHORE) {
3507 UDELAY(1000);
3509 if (++TimeOut >= SEMAPHORE_TIMEOUT) {
3510 if (!(val & START_STOP_BIT))
3511 break;
3513 printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
3514 ips_name, ha->host_num, val);
3515 printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
3516 ips_name, ha->host_num);
3518 return (IPS_FAILURE);
3519 } /* end if */
3520 } /* end while */
3522 outl(scb->scb_busaddr, ha->io_addr + CCSAR);
3523 outw(START_COMMAND, ha->io_addr + CCCR);
3525 return (IPS_SUCCESS);
3528 /****************************************************************************/
3529 /* */
3530 /* Routine Name: ips_isintr */
3531 /* */
3532 /* Routine Description: */
3533 /* */
3534 /* Test to see if an interrupt is for us */
3535 /* */
3536 /****************************************************************************/
3537 static int
3538 ips_isintr(ips_ha_t *ha) {
3539 u8 Isr;
3541 DBG("ips_isintr");
3543 Isr = inb(ha->io_addr + HISR);
3545 if (Isr == 0xFF)
3546 /* ?!?! Nothing really there */
3547 return (0);
3549 if (Isr & SCE)
3550 return (1);
3551 else if (Isr & (SQO | GHI)) {
3552 /* status queue overflow or GHI */
3553 /* just clear the interrupt */
3554 outb(Isr, ha->io_addr + HISR);
3557 return (0);
3560 /****************************************************************************/
3561 /* */
3562 /* Routine Name: ips_wait */
3563 /* */
3564 /* Routine Description: */
3565 /* */
3566 /* Wait for a command to complete */
3567 /* */
3568 /****************************************************************************/
3569 static int
3570 ips_wait(ips_ha_t *ha, int time, int intr) {
3571 int ret;
3573 DBG("ips_wait");
3575 ret = IPS_FAILURE;
3577 time *= ONE_SEC; /* convert seconds to milliseconds */
3579 while (time > 0) {
3580 if (intr == IPS_INTR_OFF) {
3581 if (ha->waitflag == FALSE) {
3583 * controller generated an interupt to
3584 * acknowledge completion of the command
3585 * and ips_intr() has serviced the interrupt.
3587 ret = IPS_SUCCESS;
3588 break;
3592 * NOTE: Interrupts are disabled here
3593 * On an SMP system interrupts will only
3594 * be disabled on one processor.
3595 * So, ultimately we still need to set the
3596 * "I'm in the interrupt handler flag"
3598 while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
3599 UDELAY(1000);
3601 ips_intr(ha);
3603 clear_bit(IPS_IN_INTR, &ha->flags);
3605 } else {
3606 if (ha->waitflag == FALSE) {
3607 ret = IPS_SUCCESS;
3608 break;
3612 UDELAY(1000); /* 1 milisecond */
3613 time--;
3616 return (ret);
3619 /****************************************************************************/
3620 /* */
3621 /* Routine Name: ips_write_driver_status */
3622 /* */
3623 /* Routine Description: */
3624 /* */
3625 /* Write OS/Driver version to Page 5 of the nvram on the controller */
3626 /* */
3627 /****************************************************************************/
3628 static int
3629 ips_write_driver_status(ips_ha_t *ha) {
3630 DBG("ips_write_driver_status");
3632 if (!ips_readwrite_page5(ha, FALSE)) {
3633 printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n",
3634 ips_name, ha->host_num);
3636 return (0);
3639 /* check to make sure the page has a valid */
3640 /* signature */
3641 if (ha->nvram->signature != NVRAM_PAGE5_SIGNATURE) {
3642 #if IPS_DEBUG >= 1
3643 printk("(%s%d) NVRAM page 5 has an invalid signature: %X.\n",
3644 ips_name, ha->host_num, ha->nvram->signature);
3645 #endif
3646 return (1);
3649 #if IPS_DEBUG >= 2
3650 printk("(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.\n",
3651 ips_name, ha->host_num, ha->nvram->adapter_type, ha->nvram->adapter_slot,
3652 ha->nvram->bios_high[0], ha->nvram->bios_high[1],
3653 ha->nvram->bios_high[2], ha->nvram->bios_high[3],
3654 ha->nvram->bios_low[0], ha->nvram->bios_low[1],
3655 ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
3656 #endif
3658 /* save controller type */
3659 ha->ad_type = ha->nvram->adapter_type;
3661 /* change values (as needed) */
3662 ha->nvram->operating_system = OS_LINUX;
3663 strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
3664 strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
3666 /* now update the page */
3667 if (!ips_readwrite_page5(ha, TRUE)) {
3668 printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n",
3669 ips_name, ha->host_num);
3671 return (0);
3674 return (1);
3677 /****************************************************************************/
3678 /* */
3679 /* Routine Name: ips_read_adapter_status */
3680 /* */
3681 /* Routine Description: */
3682 /* */
3683 /* Do an Inquiry command to the adapter */
3684 /* */
3685 /****************************************************************************/
3686 static int
3687 ips_read_adapter_status(ips_ha_t *ha) {
3688 ips_scb_t *scb;
3689 int ret;
3691 DBG("ips_read_adapter_status");
3693 scb = &ha->scbs[ha->max_cmds-1];
3695 ips_init_scb(ha, scb);
3697 scb->timeout = ips_cmd_timeout;
3698 scb->cdb[0] = ENQUIRY;
3700 scb->cmd.basic_io.op_code = ENQUIRY;
3701 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3702 scb->cmd.basic_io.sg_count = 0;
3703 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
3704 scb->cmd.basic_io.lba = 0;
3705 scb->cmd.basic_io.sector_count = 0;
3706 scb->cmd.basic_io.log_drv = 0;
3707 scb->cmd.basic_io.reserved = 0;
3709 /* send command */
3710 ret = ips_send_wait(ha, scb, ips_cmd_timeout);
3711 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3712 return (0);
3714 return (1);
3717 /****************************************************************************/
3718 /* */
3719 /* Routine Name: ips_read_subsystem_parameters */
3720 /* */
3721 /* Routine Description: */
3722 /* */
3723 /* Read subsystem parameters from the adapter */
3724 /* */
3725 /****************************************************************************/
3726 static int
3727 ips_read_subsystem_parameters(ips_ha_t *ha) {
3728 ips_scb_t *scb;
3729 int ret;
3731 DBG("ips_read_subsystem_parameters");
3733 scb = &ha->scbs[ha->max_cmds-1];
3735 ips_init_scb(ha, scb);
3737 scb->timeout = ips_cmd_timeout;
3738 scb->cdb[0] = GET_SUBSYS_PARAM;
3740 scb->cmd.basic_io.op_code = GET_SUBSYS_PARAM;
3741 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3742 scb->cmd.basic_io.sg_count = 0;
3743 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys);
3744 scb->cmd.basic_io.lba = 0;
3745 scb->cmd.basic_io.sector_count = 0;
3746 scb->cmd.basic_io.log_drv = 0;
3747 scb->cmd.basic_io.reserved = 0;
3749 /* send command */
3750 ret = ips_send_wait(ha, scb, ips_cmd_timeout);
3751 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3752 return (0);
3754 return (1);
3757 /****************************************************************************/
3758 /* */
3759 /* Routine Name: ips_read_config */
3760 /* */
3761 /* Routine Description: */
3762 /* */
3763 /* Read the configuration on the adapter */
3764 /* */
3765 /****************************************************************************/
3766 static int
3767 ips_read_config(ips_ha_t *ha) {
3768 ips_scb_t *scb;
3769 int i;
3770 int ret;
3772 DBG("ips_read_config");
3774 /* set defaults for initiator IDs */
3775 ha->conf->init_id[0] = IPS_ADAPTER_ID;
3776 for (i = 1; i < 4; i++)
3777 ha->conf->init_id[i] = 7;
3779 scb = &ha->scbs[ha->max_cmds-1];
3781 ips_init_scb(ha, scb);
3783 scb->timeout = ips_cmd_timeout;
3784 scb->cdb[0] = READ_NVRAM_CONFIGURATION;
3786 scb->cmd.basic_io.op_code = READ_NVRAM_CONFIGURATION;
3787 scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
3788 scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf);
3790 /* send command */
3791 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
3792 (ret == IPS_SUCCESS_IMM) ||
3793 ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
3795 memset(ha->conf, 0, sizeof(CONFCMD));
3797 /* reset initiator IDs */
3798 ha->conf->init_id[0] = IPS_ADAPTER_ID;
3799 for (i = 1; i < 4; i++)
3800 ha->conf->init_id[i] = 7;
3802 return (0);
3805 return (1);
3808 /****************************************************************************/
3809 /* */
3810 /* Routine Name: ips_readwrite_page5 */
3811 /* */
3812 /* Routine Description: */
3813 /* */
3814 /* Read the configuration on the adapter */
3815 /* */
3816 /****************************************************************************/
3817 static int
3818 ips_readwrite_page5(ips_ha_t *ha, int write) {
3819 ips_scb_t *scb;
3820 int ret;
3822 DBG("ips_readwrite_page5");
3824 scb = &ha->scbs[ha->max_cmds-1];
3826 ips_init_scb(ha, scb);
3828 scb->timeout = ips_cmd_timeout;
3829 scb->cdb[0] = RW_NVRAM_PAGE;
3831 scb->cmd.nvram.op_code = RW_NVRAM_PAGE;
3832 scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
3833 scb->cmd.nvram.page = 5;
3834 scb->cmd.nvram.write = write;
3835 scb->cmd.nvram.buffer_addr = VIRT_TO_BUS(ha->nvram);
3836 scb->cmd.nvram.reserved = 0;
3837 scb->cmd.nvram.reserved2 = 0;
3839 /* issue the command */
3840 if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
3841 (ret == IPS_SUCCESS_IMM) ||
3842 ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
3844 memset(ha->nvram, 0, sizeof(NVRAM_PAGE5));
3846 return (0);
3849 return (1);
3852 /****************************************************************************/
3853 /* */
3854 /* Routine Name: ips_clear_adapter */
3855 /* */
3856 /* Routine Description: */
3857 /* */
3858 /* Clear the stripe lock tables */
3859 /* */
3860 /****************************************************************************/
3861 static int
3862 ips_clear_adapter(ips_ha_t *ha) {
3863 ips_scb_t *scb;
3864 int ret;
3866 DBG("ips_clear_adapter");
3868 scb = &ha->scbs[ha->max_cmds-1];
3870 ips_init_scb(ha, scb);
3872 scb->timeout = ips_reset_timeout;
3873 scb->cdb[0] = CONFIG_SYNC;
3875 scb->cmd.config_sync.op_code = CONFIG_SYNC;
3876 scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
3877 scb->cmd.config_sync.channel = 0;
3878 scb->cmd.config_sync.source_target = POCL;
3879 scb->cmd.config_sync.reserved = 0;
3880 scb->cmd.config_sync.reserved2 = 0;
3881 scb->cmd.config_sync.reserved3 = 0;
3883 /* issue command */
3884 ret = ips_send_wait(ha, scb, ips_reset_timeout);
3885 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3886 return (0);
3888 /* send unlock stripe command */
3889 ips_init_scb(ha, scb);
3891 scb->cdb[0] = GET_ERASE_ERROR_TABLE;
3892 scb->timeout = ips_reset_timeout;
3894 scb->cmd.unlock_stripe.op_code = GET_ERASE_ERROR_TABLE;
3895 scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
3896 scb->cmd.unlock_stripe.log_drv = 0;
3897 scb->cmd.unlock_stripe.control = CSL;
3898 scb->cmd.unlock_stripe.reserved = 0;
3899 scb->cmd.unlock_stripe.reserved2 = 0;
3900 scb->cmd.unlock_stripe.reserved3 = 0;
3902 /* issue command */
3903 ret = ips_send_wait(ha, scb, ips_reset_timeout);
3904 if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
3905 return (0);
3907 return (1);
3910 #if defined (MODULE)
3912 Scsi_Host_Template driver_template = IPS;
3914 #include "scsi_module.c"
3916 #endif
3920 * Overrides for Emacs so that we almost follow Linus's tabbing style.
3921 * Emacs will notice this stuff at the end of the file and automatically
3922 * adjust the settings for this buffer only. This must remain at the end
3923 * of the file.
3924 * ---------------------------------------------------------------------------
3925 * Local variables:
3926 * c-indent-level: 2
3927 * c-brace-imaginary-offset: 0
3928 * c-brace-offset: -2
3929 * c-argdecl-indent: 2
3930 * c-label-offset: -2
3931 * c-continued-statement-offset: 2
3932 * c-continued-brace-offset: 0
3933 * indent-tabs-mode: nil
3934 * tab-width: 8
3935 * End: