patch-2.1.93 linux/drivers/scsi/u14-34f.c

Next file: linux/drivers/scsi/u14-34f.h
Previous file: linux/drivers/scsi/tmscsim.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.92/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
+ *          io_port is now unsigned long.
+ *
+ *      17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88
+ *          Use new scsi error handling code (if linux version >= 2.1.88).
+ *          Use new interrupt code.
+ *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
@@ -113,7 +120,7 @@
  * 
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-1997 Dario Ballabio (dario@milano.europe.dg.com)
+ *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that redistributions of source
@@ -329,9 +336,7 @@
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
 #undef  DEBUG_INTERRUPT
-#undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
-#undef  DEBUG_SMP
 
 #define MAX_ISA 3
 #define MAX_VESA 1 
@@ -341,7 +346,6 @@
 #define MAX_CHANNEL 1
 #define MAX_LUN 8
 #define MAX_TARGET 8
-#define MAX_IRQ 16
 #define MAX_MAILBOXES 16
 #define MAX_SGLIST 32
 #define MAX_SAFE_SGLIST 16
@@ -349,7 +353,7 @@
 #define MAX_CMD_PER_LUN 2
 #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)
 
-#define SKIP UINT_MAX
+#define SKIP ULONG_MAX
 #define FALSE 0
 #define TRUE 1
 #define FREE 0
@@ -424,7 +428,6 @@
    unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
    unsigned int last_cp_used;           /* Index of last mailbox used */
    unsigned int iocount;                /* Total i/o done for this board */
-   unsigned int multicount;             /* Total ... in second ihdlr loop */
    int board_number;                    /* Number of this board */
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
@@ -443,9 +446,12 @@
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
 static const char *driver_name = "Ux4F";
-static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
+static char sha[MAX_BOARDS];
 
-static unsigned int io_port[] __initdata = { 
+/* Initialize num_boards so that ihdlr can work while detect is in progress */
+static unsigned int num_boards = MAX_BOARDS;
+
+static unsigned long io_port[] __initdata = { 
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -462,10 +468,10 @@
 #define BN(board) (HD(board)->board_name)
 
 #define SWAP_BYTE(x) ((unsigned long)( \
-	(((unsigned long)(x) & 0x000000ffU) << 24) | \
-	(((unsigned long)(x) & 0x0000ff00U) <<  8) | \
-	(((unsigned long)(x) & 0x00ff0000U) >>  8) | \
-	(((unsigned long)(x) & 0xff000000U) >> 24)))
+        (((unsigned long)(x) & 0x000000ffU) << 24) | \
+        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
+        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
+        (((unsigned long)(x) & 0xff000000U) >> 24)))
 
 #if defined(__BIG_ENDIAN)
 #define H2DEV(x) SWAP_BYTE(x)
@@ -560,7 +566,7 @@
    return;
 }
 
-static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
+static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {
 
    while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {
       udelay(1L);
@@ -614,7 +620,7 @@
 }
 
 __initfunc (static inline int port_detect \
-      (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
    char *bus_type, dma_name[16];
@@ -637,8 +643,8 @@
       unsigned char heads;
       unsigned char sectors;
       } mapping_table[4] = { 
-	   { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
-	   };
+           { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
+           };
 
    struct config_1 {
       unsigned char bios_segment: 3;
@@ -659,7 +665,7 @@
    sprintf(name, "%s%d", driver_name, j);
 
    if(check_region(port_base, REGION_SIZE)) {
-      printk("%s: address 0x%03x in use, skipping probe.\n", name, port_base);
+      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
       return FALSE;
       }
 
@@ -676,17 +682,18 @@
    dma_channel = dma_channel_table[config_1.dma_channel];
    subversion = (in_byte & 0x0f);
 
-   /* Board detected, allocate its IRQ if not already done */
-   if ((irq >= MAX_IRQ) || (!irqlist[irq] && request_irq(irq,
-              u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
+   /* Board detected, allocate its IRQ */
+   if (request_irq(irq, u14_34f_interrupt_handler,
+             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
+             driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
       return FALSE;
       }
 
    if (subversion == ISA && request_dma(dma_channel, driver_name)) {
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
-	     name, dma_channel);
-      free_irq(irq, NULL);
+             name, dma_channel);
+      free_irq(irq, &sha[j]);
       return FALSE;
       }
 
@@ -695,7 +702,7 @@
    if (sh[j] == NULL) {
       printk("%s: unable to register host, detaching.\n", name);
 
-      if (!irqlist[irq]) free_irq(irq, NULL);
+      free_irq(irq, &sha[j]);
 
       if (subversion == ISA) free_dma(dma_channel);
 
@@ -734,7 +741,6 @@
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
    HD(j)->subversion = subversion;
    HD(j)->board_number = j;
-   irqlist[irq]++;
 
    if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
 
@@ -767,12 +773,12 @@
       HD(j)->board_id[40] = 0;
 
       if (strcmp(&HD(j)->board_id[32], "06000600")) {
-	 printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
-	 printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
-		BN(j), &HD(j)->board_id[32]);
-	 sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
-	 sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
-	 }
+         printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);
+         printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",
+                BN(j), &HD(j)->board_id[32]);
+         sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;
+         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
+         }
       }
 
    if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST");
@@ -792,10 +798,11 @@
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
-   printk("%s: %s 0x%03x, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
-          "lc:%c, mq:%d.\n", BN(j), bus_type, sh[j]->io_port, (int)sh[j]->base,
-          sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue,
-          YESNO(have_old_firmware), YESNO(linked_comm), max_queue_depth);
+   printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\
+          "lc:%c, mq:%d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port,
+          (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize,
+          sh[j]->can_queue, YESNO(have_old_firmware), YESNO(linked_comm),
+          max_queue_depth);
 
    if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
       printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
@@ -857,11 +864,6 @@
       }
 #endif
 
-   for (k = 0; k < MAX_IRQ; k++) {
-      irqlist[k] = 0;
-      calls[k] = 0;
-      }
-
    for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;
 
    for (k = 0; io_port[k]; k++) {
@@ -872,8 +874,9 @@
       }
 
    if (j > 0) 
-      printk("UltraStor 14F/34F: Copyright (C) 1994-1997 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
+   num_boards = j;
    restore_flags(flags);
    return j;
 }
@@ -938,26 +941,26 @@
       if (i >= sh[j]->can_queue) i = 0;
 
       if (HD(j)->cp_stat[i] == FREE) {
-	 HD(j)->last_cp_used = i;
-	 break;
-	 }
+         HD(j)->last_cp_used = i;
+         break;
+         }
       }
 
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
       if (HD(j)->in_reset) 
-	 printk("%s: qcomm, already in reset.\n", BN(j));
+         printk("%s: qcomm, already in reset.\n", BN(j));
       else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
                == SCSI_RESET_SUCCESS) 
-	 panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
+         panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
       SCpnt->result = DID_BUS_BUSY << 16; 
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
-      return 0;
+      return 1;
       }
 
    /* Set pointer to control packet structure */
@@ -969,16 +972,16 @@
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-			BN(j), i, SCpnt->channel, SCpnt->target, 
+                        BN(j), i, SCpnt->channel, SCpnt->target, 
                         SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
       if (SCpnt->cmnd[0] == data_out_cmds[k]) {
-	 cpp->xdir = DTD_OUT;
-	 break;
-	 }
+         cpp->xdir = DTD_OUT;
+         break;
+         }
 
    if (cpp->xdir == DTD_IN)
       for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)
@@ -1023,7 +1026,7 @@
              SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);
-      return 0;
+      return 1;
       }
 
    /* Store pointer in OGM address bytes */
@@ -1048,14 +1051,14 @@
    if (SCarg->host_scribble == NULL
        || SCarg->serial_number != SCarg->serial_number_at_timeout) {
       printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
-	     BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+             BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
    printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
-	  BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
+          BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -1076,8 +1079,8 @@
       printk("%s: abort, mbox %d is in use.\n", BN(j), i);
 
       if (SCarg != HD(j)->cp[i].SCpnt)
-	 panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
-	       BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
+         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",
+               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);
 
       if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED)
          printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);
@@ -1103,7 +1106,7 @@
       SCarg->host_scribble = NULL;
       HD(j)->cp_stat[i] = FREE;
       printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
-	     BN(j), i, SCarg->pid);
+             BN(j), i, SCarg->pid);
       SCarg->scsi_done(SCarg);
       restore_flags(flags);
       return SCSI_ABORT_SUCCESS;
@@ -1123,7 +1126,7 @@
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
    printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
-	  BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
    if (SCarg->host_scribble == NULL)
@@ -1160,13 +1163,13 @@
       if (HD(j)->cp_stat[i] == FREE) continue;
 
       if (HD(j)->cp_stat[i] == LOCKED) {
-	 HD(j)->cp_stat[i] = FREE;
-	 printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
-	 continue;
-	 }
+         HD(j)->cp_stat[i] = FREE;
+         printk("%s: reset, locked mbox %d forced free.\n", BN(j), i);
+         continue;
+         }
 
       if (!(SCpnt = HD(j)->cp[i].SCpnt))
-	 panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
       if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {
          HD(j)->cp_stat[i] = ABORTING;
@@ -1181,13 +1184,13 @@
          }
 
       if (SCpnt->host_scribble == NULL)
-	 panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
+         panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
       if (*(unsigned int *)SCpnt->host_scribble != i) 
-	 panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
+         panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
       if (SCpnt->scsi_done == NULL) 
-	 panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
+         panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
       }
@@ -1223,7 +1226,7 @@
          HD(j)->cp_stat[i] = LOCKED;
 
          printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else if (HD(j)->cp_stat[i] == ABORTING) {
@@ -1235,7 +1238,7 @@
          HD(j)->cp_stat[i] = FREE;
 
          printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
-	        BN(j), i, SCpnt->pid);
+                BN(j), i, SCpnt->pid);
          }
 
       else
@@ -1428,224 +1431,182 @@
       }
 }
 
-static void u14_34f_interrupt_handler(int irq, void *dev_id,
-                                      struct pt_regs *regs) {
+static void u14_34f_interrupt_handler(int irq, void *shap,
+                                               struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned long flags;
-   unsigned int i, j, k, c, status, tstatus, loops, total_loops = 0, reg, ret;
+   unsigned int i, j, k, c, status, tstatus, reg, ret;
    struct mscp *spp;
 
-   save_flags(flags);
-   cli();
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
 
-   if (!irqlist[irq]) {
-      printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq);
-      restore_flags(flags);
+   if (sh[j]->irq != irq)
+       panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
+
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
+
+   /* Check if this board need to be serviced */
+   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+
+   spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+
+   /* Clear interrupt pending flag */
+   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+
+   i = spp - HD(j)->cp;
+
+   if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+                                     || i >= sh[j]->can_queue)
+      panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
+            (void *)ret, HD(j)->cp);
+
+   if (HD(j)->cp_stat[i] == IGNORE) {
+      HD(j)->cp_stat[i] = FREE;
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == LOCKED) {
+      HD(j)->cp_stat[i] = FREE;
+      printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == FREE) {
+      printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+             HD(j)->iocount);
       return;
       }
+   else if (HD(j)->cp_stat[i] == IN_RESET)
+      printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE) 
+      panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
+
+   HD(j)->cp_stat[i] = FREE;
+   SCpnt = spp->SCpnt;
+
+   if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
+
+   if (SCpnt->host_scribble == NULL) 
+      panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+            SCpnt->pid, SCpnt);
+
+   if (*(unsigned int *)SCpnt->host_scribble != i) 
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", 
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
 
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", 
-			driver_name, irq, calls[irq]);
+   if (linked_comm && SCpnt->device->queue_depth > 2
+                                     && TLDEV(SCpnt->device->type))
+      flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
 
-   /* Service all the boards configured on this irq */
-   for (j = 0; sh[j] != NULL; j++) {
+   tstatus = status_byte(spp->target_status);
 
-      if (sh[j]->irq != irq) continue;
+   switch (spp->adapter_status) {
+      case ASOK:     /* status OK */
 
-      loops = 0;
-
-      /* Loop until all interrupts for a board are serviced */
-      while ((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED) {
-	 total_loops++;
-	 loops++;
-
-	 if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
-			      BN(j), HD(j)->iocount);
-
-	 spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
-
-	 /* Clear interrupt pending flag */
-	 outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
-
-	 i = spp - HD(j)->cp;
-
-	 if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
-                                            || i >= sh[j]->can_queue)
-	    panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n",
-                  BN(j), (void *)ret, HD(j)->cp);
-
-	 if (HD(j)->cp_stat[i] == IGNORE) {
-	    HD(j)->cp_stat[i] = FREE;
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == LOCKED) {
-	    HD(j)->cp_stat[i] = FREE;
-	    printk("%s: ihdlr, mbox %d unlocked, count %d.\n",
-		   BN(j), i, HD(j)->iocount);
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == FREE) {
-	    printk("%s: ihdlr, mbox %d is free, count %d.\n", 
-		   BN(j), i, HD(j)->iocount);
-	    continue;
-	    }
-	 else if (HD(j)->cp_stat[i] == IN_RESET)
-	    printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-	 else if (HD(j)->cp_stat[i] != IN_USE) 
-	    panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
-
-	 HD(j)->cp_stat[i] = FREE;
-	 SCpnt = spp->SCpnt;
-
-	 if (SCpnt == NULL) 
-	    panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
-
-	 if (SCpnt->host_scribble == NULL) 
-	    panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n",
-		  BN(j), i, SCpnt->pid, SCpnt);
-
-	 if (*(unsigned int *)SCpnt->host_scribble != i) 
-	    panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\
-		  " irq %d.\n", BN(j), i, SCpnt->pid, 
-		  *(unsigned int *)SCpnt->host_scribble, irq);
-
-         if (linked_comm && SCpnt->device->queue_depth > 2
-                                           && TLDEV(SCpnt->device->type))
-            flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
-
-	 tstatus = status_byte(spp->target_status);
-
-	 switch (spp->adapter_status) {
-	    case ASOK:     /* status OK */
-
-	       /* Forces a reset if a disk drive keeps returning BUSY */
-	       if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-		  status = DID_ERROR << 16;
-
-	       /* If there was a bus reset, redo operation on each target */
-	       else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-		        && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-		  status = DID_BUS_BUSY << 16;
-
-	       /* Works around a flaw in scsi.c */
-	       else if (tstatus == CHECK_CONDITION
-			&& SCpnt->device->type == TYPE_DISK
-			&& (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-		  status = DID_BUS_BUSY << 16;
-
-	       else
-		  status = DID_OK << 16;
-
-	       if (tstatus == GOOD)
-		  HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-
-	       if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-		  printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                         "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-			 SCpnt->channel, SCpnt->target, SCpnt->lun,
-                         SCpnt->pid, spp->target_status,
-                         SCpnt->sense_buffer[2]);
-
-	       HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-
-               if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
-
-	       break;
-	    case ASST:     /* Selection Time Out */
-
-	       if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-		  status = DID_ERROR << 16;
-	       else {
-		  status = DID_TIME_OUT << 16;
-		  HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-		  }
-
-	       break;
-
-            /* Perform a limited number of internal retries */
-	    case 0x93:     /* Unexpected bus free */
-	    case 0x94:     /* Target bus phase sequence failure */
-	    case 0x96:     /* Illegal SCSI command */
-	    case 0xa3:     /* SCSI bus reset error */
-
-	       for (c = 0; c <= sh[j]->max_channel; c++) 
-	          for (k = 0; k < sh[j]->max_id; k++) 
-	             HD(j)->target_redo[k][c] = TRUE;
-   
+         /* Forces a reset if a disk drive keeps returning BUSY */
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+            status = DID_ERROR << 16;
+
+         /* If there was a bus reset, redo operation on each target */
+         else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                  && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+            status = DID_BUS_BUSY << 16;
+
+         /* Works around a flaw in scsi.c */
+         else if (tstatus == CHECK_CONDITION
+                  && SCpnt->device->type == TYPE_DISK
+                  && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+            status = DID_BUS_BUSY << 16;
 
-	    case 0x92:     /* Data over/under-run */
+         else
+            status = DID_OK << 16;
 
-	       if (SCpnt->device->type != TYPE_TAPE
-                   && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-		  status = DID_BUS_BUSY << 16;
-		  HD(j)->retries++;
-                  HD(j)->last_retried_pid = SCpnt->pid;
-                  }
-	       else 
-		  status = DID_ERROR << 16;
-
-	       break;
-	    case 0x01:     /* Invalid command */
-	    case 0x02:     /* Invalid parameters */
-	    case 0x03:     /* Invalid data list */
-	    case 0x84:     /* SCSI bus abort error */
-	    case 0x9b:     /* Auto request sense error */
-	    case 0x9f:     /* Unexpected command complete message error */
-	    case 0xff:     /* Invalid parameter in the S/G list */
-	    default:
-	       status = DID_ERROR << 16;
-	       break;
-	    }
+         if (tstatus == GOOD)
+            HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
 
-	 SCpnt->result = status | spp->target_status;
-	 HD(j)->iocount++;
+         if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+            printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                   SCpnt->channel, SCpnt->target, SCpnt->lun,
+                   SCpnt->pid, spp->target_status,
+                   SCpnt->sense_buffer[2]);
 
-	 if (loops > 1) HD(j)->multicount++;
+         HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
 
-#if defined (DEBUG_INTERRUPT)
-	 if (SCpnt->result || do_trace) 
-#else
-	 if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-	     (spp->adapter_status != ASOK && 
-	      spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-              do_trace || msg_byte(spp->target_status))
-#endif
-	    printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-		   " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-		   BN(j), i, spp->adapter_status, spp->target_status,
-		   SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                   reg, HD(j)->iocount);
+         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
 
-	 /* Set the command state to inactive */
-	 SCpnt->host_scribble = NULL;
+         break;
+      case ASST:     /* Selection Time Out */
 
-	 restore_flags(flags);
-	 SCpnt->scsi_done(SCpnt);
-	 cli();
+         if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+            status = DID_ERROR << 16;
+         else {
+            status = DID_TIME_OUT << 16;
+            HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+            }
 
-	 }   /* Multiple command loop */
+         break;
 
-      }   /* Boards loop */
+      /* Perform a limited number of internal retries */
+      case 0x93:     /* Unexpected bus free */
+      case 0x94:     /* Target bus phase sequence failure */
+      case 0x96:     /* Illegal SCSI command */
+      case 0xa3:     /* SCSI bus reset error */
+
+         for (c = 0; c <= sh[j]->max_channel; c++) 
+            for (k = 0; k < sh[j]->max_id; k++) 
+               HD(j)->target_redo[k][c] = TRUE;
+   
 
-   calls[irq]++;
+      case 0x92:     /* Data over/under-run */
 
-#if defined (DEBUG_SMP)
-   if (total_loops == 0) 
-     printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
-	    driver_name, irq, calls[irq]);
-#endif
+         if (SCpnt->device->type != TYPE_TAPE
+             && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+            status = DID_BUS_BUSY << 16;
+            HD(j)->retries++;
+            HD(j)->last_retried_pid = SCpnt->pid;
+            }
+         else 
+            status = DID_ERROR << 16;
+
+         break;
+      case 0x01:     /* Invalid command */
+      case 0x02:     /* Invalid parameters */
+      case 0x03:     /* Invalid data list */
+      case 0x84:     /* SCSI bus abort error */
+      case 0x9b:     /* Auto request sense error */
+      case 0x9f:     /* Unexpected command complete message error */
+      case 0xff:     /* Invalid parameter in the S/G list */
+      default:
+         status = DID_ERROR << 16;
+         break;
+      }
 
-   if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
-			driver_name, irq, calls[irq]);
+   SCpnt->result = status | spp->target_status;
+   HD(j)->iocount++;
 
-#if defined (DEBUG_STATISTICS)
-   if ((calls[irq] % 100000) == 10000)
-      for (j = 0; sh[j] != NULL; j++)
-	 printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j),
-		calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount);
+#if defined (DEBUG_INTERRUPT)
+   if (SCpnt->result || do_trace) 
+#else
+   if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+       (spp->adapter_status != ASOK && 
+        spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+        do_trace || msg_byte(spp->target_status))
 #endif
+      printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+             " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+             BN(j), i, spp->adapter_status, spp->target_status,
+             SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+             reg, HD(j)->iocount);
+
+   /* Set the command state to inactive */
+   SCpnt->host_scribble = NULL;
+
+   SCpnt->scsi_done(SCpnt);
+
+   if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-   restore_flags(flags);
    return;
 }
 
@@ -1664,7 +1625,7 @@
    for (i = 0; i < sh[j]->can_queue; i++) 
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
-   if (! --irqlist[sh[j]->irq]) free_irq(sh[j]->irq, NULL);
+   free_irq(sh[j]->irq, &sha[j]);
 
    if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov