patch-1.3.15 linux/drivers/scsi/aic7xxx.c

Next file: linux/drivers/scsi/aic7xxx.h
Previous file: linux/drivers/scsi/aha1542.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.14/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
@@ -41,7 +41,7 @@
  *
  *    -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 04/03/95
  *
- *  $Id: aic7xxx.c,v 1.49 1995/06/28 05:41:09 deang Exp $
+ *  $Id: aic7xxx.c,v 2.0 1995/08/02 05:28:42 deang Exp $
  *-M*************************************************************************/
 
 #ifdef MODULE
@@ -51,6 +51,7 @@
 #include <stdarg.h>
 #include <asm/io.h>
 #include <linux/string.h>
+#include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/bios32.h>
@@ -64,10 +65,16 @@
 #include "hosts.h"
 #include "aic7xxx.h"
 
-#define AIC7XXX_C_VERSION  "$Revision: 1.49 $"
+#define AIC7XXX_C_VERSION  "$Revision: 2.0 $"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
-#define MIN(a,b) ((a < b) ? a : b)
+#define MIN(a,b)        ((a < b) ? a : b)
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
 
 /*
  * Defines for PCI bus support, testing twin bus support, DMAing of
@@ -395,13 +402,26 @@
 /*
  * Board Control (p. 3-43)
  */
-#define BCTL(x)		((x) + 0xC84ul)
+#define BCTL(x)			((x) + 0xC84ul)
 /*   RSVD			0xF0 */
 #define		ACE		0x08	/* Support for external processors */
 /*   RSVD			0x06 */
 #define		ENABLE		0x01
 
-#define BUSSPD(x)		((x) + 0xC86ul)	/* FIFO threshold bits ? */
+/*
+ * Bus On/Off Time (p. 3-44)
+ */
+#define BUSTIME(x)		((x) + 0xC85ul)
+#define		BOFF		0xF0
+#define		BON		0x0F
+
+/*
+ * Bus Speed (p. 3-45)
+ */
+#define	BUSSPD(x)		((x) + 0xC86ul)
+#define		DFTHRSH		0xC0
+#define		STBOFF		0x38
+#define		STBON		0x07
 
 /*
  * Host Control (p. 3-47) R/W
@@ -719,13 +739,45 @@
  * to zero inside the kernel - we have to initialize them all
  * explicitly.
  *
- * We support a maximum of one adapter card per IRQ level (see the
- * rationale for this above). On an interrupt, use the IRQ as an
- * index into aic7xxx_boards[] to locate the card information.
+ * We support multiple adapter cards per interrupt, but keep a
+ * linked list of Scsi_Host structures for each IRQ.  On an interrupt,
+ * use the IRQ as an index into aic7xxx_boards[] to locate the card
+ * information.
  */
 static struct Scsi_Host *aic7xxx_boards[MAXIRQ + 1];
 
 /*
+ * When we detect and register the card, it is possible to
+ * have the card raise a spurious interrupt.  Because we need
+ * to support multiple cards, we cannot tell which card caused
+ * the spurious interrupt.  And, we might not even have added
+ * the card info to the linked list at the time the spurious
+ * interrupt gets raised.  This variable is suppose to keep track
+ * of when we are registering a card and how many spurious
+ * interrupts we have encountered.
+ *
+ *   0 - do not allow spurious interrupts.
+ *   1 - allow 1 spurious interrupt
+ *   2 - have 1 spurious interrupt, do not allow any more.
+ *
+ * I've made it an integer instead of a boolean in case we
+ * want to allow more than one spurious interrupt for debugging
+ * purposes.  Otherwise, it could just go from true to false to
+ * true (or something like that).
+ *
+ * When the driver detects the cards, we'll set the count to 1
+ * for each card detection and registration.  After the registration
+ * of a card completes, we'll set the count back to 0.  So far, it
+ * seems to be enough to allow a spurious interrupt only during
+ * card registration; if a spurious interrupt is going to occur,
+ * this is where it happens.
+ *
+ * We should be able to find a way to avoid getting the spurious
+ * interrupt.  But until we do, we have to keep this ugly code.
+ */
+static int aic7xxx_spurious_count;
+
+/*
  * The driver keeps up to four scb structures per card in memory. Only the
  * first 26 bytes of the structure are valid for the hardware, the rest used
  * for driver level bookeeping. The driver is further optimized
@@ -801,7 +853,7 @@
 
 static struct {
   unsigned char errno;
-  char *errmesg;
+  const char *errmesg;
 } hard_error[] = {
   { ILLHADDR,  "Illegal Host Access" },
   { ILLSADDR,  "Illegal Sequencer Address referrenced" },
@@ -872,7 +924,7 @@
 static struct {
   short period;
   short rate;
-  char *english;
+  const char *english;
 } aic7xxx_syncrates[] = {
   { 100,   0,  "10.0" },
   { 125,   1,  "8.0"  },
@@ -911,7 +963,7 @@
 
   static int DFT[] = { 0, 50, 75, 100 };
   static int SST[] = { 256, 128, 64, 32 };
-  static char *BUSW[] = { "", "-TWIN", "-WIDE" };
+  static const char *BUSW[] = { "", "-TWIN", "-WIDE" };
 
   host_conf = inb(HA_HOSTCONF(p->base));
   scsi_conf = inb(HA_SCSICONF(p->base));
@@ -925,14 +977,14 @@
    */
   if ((p->type == AIC_274x) || (p->type == AIC_284x))
   {
-    brelease = scsi_conf & 0x3F;
     dfthresh = host_conf >> 6;
   }
   else
   {
-    brelease = p->busrtime;
     dfthresh = scsi_conf >> 6;
   }
+
+  brelease = p->busrtime;
   if (brelease == 0)
   {
     brelease = 2;
@@ -1031,7 +1083,7 @@
   char *p;
 
   static struct {
-    char *name;
+    const char *name;
     int *flag;
   } options[] = {
     { "extended",    &aic7xxx_extended },
@@ -1124,7 +1176,7 @@
 {
   unsigned long i;
 
-  i = jiffies + (seconds * 100);  /* compute time to stop */
+  i = jiffies + (seconds * HZ);  /* compute time to stop */
 
   while (jiffies < i)
   {
@@ -1327,7 +1379,7 @@
     length = cmd->request_bufflen;
   }
 
-  return(length);
+  return (length);
 }
 
 /*+F*************************************************************************
@@ -1380,7 +1432,7 @@
   unsigned char active, ha_flags, transfer;
   unsigned char scsi_id, bus_width;
   unsigned char offset, rate, scratch;
-  unsigned char max_offset;
+  unsigned char max_offset, rej_byte;
   unsigned char head, tail;
   unsigned short target_mask;
   long flags;
@@ -1389,40 +1441,58 @@
   int target, tcl;
   int scbptr;
   Scsi_Cmnd *cmd;
-#if 0
-static int_count = 0;
-#endif
 
   p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
-#ifdef AIC7XXX_SHARE_IRQS
+
   /*
-   * Search for the host with a pending interrupt.
+   * Search for the host with a pending interrupt.  If we can't find
+   * one, then we've encountered a spurious interrupt.
    */
   while ((p != NULL) && !(inb(INTSTAT(p->base)) & INT_PEND))
   {
-    p = (struct aic7xxx_host *) p->next->hostdata;
+    if (p->next == NULL)
+    {
+      p = NULL;
+    }
+    else
+    {
+      p = (struct aic7xxx_host *) p->next->hostdata;
+    }
   }
+
   if (p == NULL)
   {
-    printk("aic7xxx_isr: Encountered spurious interrupt.\n");
-    return;
-  }
-#endif
-  base = p->base;
-  if (p->isr_count == 0xffffffff)
-  {
-    p->isr_count = 0;
-  }
-  else
-  {
-    p->isr_count = p->isr_count + 1;
+    if (aic7xxx_spurious_count == 1)
+    {
+      aic7xxx_spurious_count = 2;
+      printk("aic7xxx_isr: Encountered spurious interrupt.\n");
+      return;
+    }
+    else
+    {
+      /*
+       * The best we can do is to set p back to head of list and process
+       * the erroneous interrupt - most likely a BRKADRINT.
+       */
+      p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
+    }
   }
+
+  p->isr_count++; /* Keep track of interrupts for /proc/scsi */
+
   if ((p->a_scanned == 0) && (p->isr_count == 1))
   {
-    /* Allow for one interrupt when the card is enabled. */
+    /*
+     * We must only have one card at this IRQ and it must have been
+     * added to the board data before the spurious interrupt occurred.
+     * It is sufficient that we check isr_count and not the spurious
+     * interrupt count.
+     */
+    printk("aic7xxx_isr: Encountered spurious interrupt.\n");
     return;
   }
 
+  base = p->base;
   /*
    * Handle all the interrupt sources - especially for SCSI
    * interrupts, we won't get a second chance at them.
@@ -1462,10 +1532,26 @@
     {
       case BAD_PHASE:
 	panic("aic7xxx_isr: unknown scsi bus phase\n");
+	break;
 
       case SEND_REJECT:
-	debug("aic7xxx_isr warning: issuing message reject, 1st byte 0x%x\n",
-	      inb(HA_REJBYTE(base)));
+        rej_byte = inb(HA_REJBYTE(base));
+        scsi_id = inb(SCSIID(base)) >> 0x04;
+        scbptr = inb(SCBPTR(base));
+        scb = &(p->scb_array[scbptr]);
+        if (rej_byte != 0x20)
+        {
+          debug("aic7xxx_isr warning: issuing message reject, 1st byte 0x%x\n",
+                rej_byte);
+        }
+        else
+        {
+          printk("aic7xxx_isr warning: Tagged message rejected for target %d,"
+                 " channel %c.\n",
+                 scsi_id, (inb(SBLKCTL(base)) & SELBUSB ? 'B': 'A'));
+          scb->cmd->device->tagged_supported = 0;
+          scb->cmd->device->tagged_queue = 0;
+        }
 	break;
 
       case NO_IDENT:
@@ -1572,7 +1658,7 @@
 	    /*
 	     * Send our own SDTR in reply.
 	     */
-	    printk("Sending SDTR!!\n");
+	    printk("aic7xxx_isr: Sending SDTR!!\n");
 	    outb(SEND_SDTR, HA_RETURN_1(base));
 	  }
 	}
@@ -1591,7 +1677,7 @@
 	{
 	  scsi_id = scsi_id + 8;  /* B channel */
 	}
-	printk("Received MSG_WDTR, scsi_id = %d, "
+	printk("aic7xxx_isr: Received MSG_WDTR, scsi_id = %d, "
 	       "needwdtr = 0x%x\n", scsi_id, p->needwdtr);
 	scratch = inb(HA_TARG_SCRATCH(base) + scsi_id);
 
@@ -1620,7 +1706,7 @@
 	  /*
 	   * Send our own WDTR in reply.
 	   */
-	  printk("Will send WDTR!!\n");
+	  printk("aic7xxx_isr: Will send WDTR!!\n");
 	  switch (bus_width)
 	  {
 	    case BUS_8_BIT:
@@ -1769,13 +1855,13 @@
 		       sizeof(scb->SCSI_cmd_pointer));
 #ifdef AIC7XXX_USE_SG
 		scb->SG_segment_count = 1;
-		memcpy (scb->SG_list_pointer, &req_buf,
+		memcpy(scb->SG_list_pointer, &req_buf,
 			sizeof(scb->SG_list_pointer));
 #else
 		scb->SG_segment_count = 0;
-		memcpy (scb->data_pointer, &req_buf,
+		memcpy(scb->data_pointer, &req_buf,
 			sizeof(scb->data_pointer));
-		memcpy (scb->data_count, &req_buflen, 3);
+		memcpy(scb->data_count, &req_buflen, 3);
 #endif
 
 		outb(SCBAUTO, SCBCNT(base));
@@ -1935,7 +2021,7 @@
 	  scb->next = p->free_scb;      /* preserve next pointer */
 	  p->free_scb = scb;            /* add at head of list */
 
-	  restore_flags (flags);
+	  restore_flags(flags);
 	  cmd->result = (DID_RETRY_COMMAND << 16);
 	  cmd->scsi_done(cmd);
 	}
@@ -1964,8 +2050,8 @@
 	   }
 	   else
 	   {
-	     panic ("aic7xxx_isr: AWAITING_SCB for an SCB that does "
-		    "not have a waiting message");
+	     panic("aic7xxx_isr: AWAITING_SCB for an SCB that does "
+		   "not have a waiting message");
 	   }
 	}
 	break;
@@ -2121,7 +2207,7 @@
 	}
 	else
 	{
-	  if (! (status & BUSFREE))
+	  if (!(status & BUSFREE))
 	  {
 	     /*
 	      * We don't know what's going on. Turn off the
@@ -2268,14 +2354,14 @@
     {
       if (inb(base + 4) & 1)
       {
-	return(AIC7xxx[i].type);
+	return (AIC7xxx[i].type);
       }
 
       printk("aic7xxx disabled at slot %d, ignored\n", slot);
     }
   }
 
-  return(AIC_NONE);
+  return (AIC_NONE);
 }
 
 /*+F*************************************************************************
@@ -2362,7 +2448,7 @@
   }
   if ((inb(SEECTL(base)) & SEERDY) == 0)
   {
-    outb (0, SEECTL(base));
+    outb(0, SEECTL(base));
     return (0);
   }
 
@@ -2372,7 +2458,7 @@
    * but only the first 32 are used by Adaptec BIOS.  The loop
    * will range from 0 to 31.
    */
-  for (k = 0; k < (sizeof(*sc) / 2); k = k + 1)
+  for (k = 0; k < (sizeof(*sc) / 2); k++)
   {
     /* Send chip select for one clock cycle. */
     outb(SEEMS | SEECK | SEECS, SEECTL(base));
@@ -2382,7 +2468,7 @@
      * Now we're ready to send the read command followed by the
      * address of the 16-bit register we want to read.
      */
-    for (i = 0; i < seeprom_read.len; i = i + 1)
+    for (i = 0; i < seeprom_read.len; i++)
     {
       temp = SEEMS | SEECS | (seeprom_read.bits[i] << 1);
       outb(temp, SEECTL(base));
@@ -2392,7 +2478,7 @@
       CLOCK_PULSE(base);
     }
     /* Send the 6 bit address (MSB first, LSB last). */
-    for (i = 5; i >= 0; i = i - 1)
+    for (i = 5; i >= 0; i--)
     {
       temp = k;
       temp = (temp >> i) & 1;  /* Mask out all but lower bit. */
@@ -2410,7 +2496,7 @@
      * with bit 0 (LSB).  The initial 0 will be shifted off the
      * top of our word as we let the loop run from 0 to 16.
      */
-    for (i = 0; i <= 16; i = i + 1)
+    for (i = 0; i <= 16; i++)
     {
       temp = SEEMS | SEECS;
       outb(temp, SEECTL(base));
@@ -2443,22 +2529,22 @@
 
   if (checksum != sc->checksum)
   {
-    printk ("aic7xxx : SEEPROM checksum error, ignoring SEEPROM settings.\n");
+    printk("aic7xxx: SEEPROM checksum error, ignoring SEEPROM settings.\n");
     return (0);
   }
 
 #if 0
-  printk ("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum);
-  printk ("Serial EEPROM:");
-  for (k = 0; k < (sizeof(*sc) / 2); k = k + 1)
+  printk("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum);
+  printk("Serial EEPROM:");
+  for (k = 0; k < (sizeof(*sc) / 2); k++)
   {
     if (((k % 8) == 0) && (k != 0))
     {
-      printk ("\n              ");
+      printk("\n              ");
     }
-    printk (" 0x%x", seeprom[k]);
+    printk(" 0x%x", seeprom[k]);
   }
-  printk ("\n");
+  printk("\n");
 #endif
 
   /* Release access to the memory port and the serial EEPROM. */
@@ -2531,7 +2617,7 @@
       break;
   }
 
-  return(maxscb);
+  return (maxscb);
 }
 
 /*+F*************************************************************************
@@ -2545,13 +2631,13 @@
 aic7xxx_register(Scsi_Host_Template *template, aha_type type,
 		 int base, unsigned char irq)
 {
-  static char * board_name[] = {"", "274x", "284x", "7870", "7850", "7872"};
+  static const char * board_name[] = {"", "274x", "284x", "7870", "7850", "7872"};
   int i;
   unsigned char sblkctl;
   int max_targets;
   int found = 1;
   unsigned char target_settings;
-  unsigned char scsi_conf;
+  unsigned char scsi_conf, host_conf;
   int have_seeprom = 0;
   struct Scsi_Host *host;
   struct aic7xxx_host *p;
@@ -2574,7 +2660,7 @@
   switch (type)
   {
     case AIC_274x:
-#if 1
+#if 0
       printk("aha274x: aic7770 hcntrl=0x%x\n", inb(HCNTRL(config.base)));
 #endif
       /*
@@ -2622,7 +2708,12 @@
        * since there was some issue about reseting the board.
        */
       config.irq = inb(HA_INTDEF(config.base)) & 0x0F;
-      config.busrtime = inb(HA_SCSICONF(config.base)) & 0x3C;
+      host_conf = inb(HA_HOSTCONF(config.base));
+      config.busrtime = host_conf & 0x3C;
+      /* XXX Is this valid for motherboard based controllers? */
+      /* Setup the FIFO threshold and the bus off time */
+      outb(host_conf & DFTHRSH, BUSSPD(config.base));
+      outb((host_conf << 2) & BOFF, BUSTIME(config.base));
 
       /*
        * A reminder until this can be detected automatically.
@@ -2632,7 +2723,7 @@
       break;
 
     case AIC_284x:
-#if 1
+#if 0
       printk("aha284x: aic7770 hcntrl=0x%x\n", inb(HCNTRL(config.base)));
 #endif
       outb(CHIPRST, HCNTRL(config.base));
@@ -2640,6 +2731,12 @@
       config.pause = REQ_PAUSE; /* DWG would like to be like the rest */
       config.extended = aic7xxx_extended;
       config.irq = inb(HA_INTDEF(config.base)) & 0x0F;
+      host_conf = inb(HA_HOSTCONF(config.base));
+      config.busrtime = host_conf & 0x3C;
+      /* XXX Is this valid for motherboard based controllers? */
+      /* Setup the FIFO threshold and the bus off time */
+      outb(host_conf & DFTHRSH, BUSSPD(config.base));
+      outb((host_conf << 2) & BOFF, BUSTIME(config.base));
 
       /*
        * A reminder until this can be detected automatically.
@@ -2651,7 +2748,7 @@
     case AIC_7850:
     case AIC_7870:
     case AIC_7872:
-#if 1
+#if 0
       printk("aic%s hcntrl=0x%x\n", board_name[type], inb(HCNTRL(config.base)));
 #endif
 
@@ -2661,15 +2758,15 @@
       config.extended = aic7xxx_extended;
       config.scsi_id = 7;
 
-      printk ("aic78xx: Reading SEEPROM... ");
+      printk("aic78xx: Reading SEEPROM... ");
       have_seeprom = read_seeprom(base, &sc);
-      if (! have_seeprom)
+      if (!have_seeprom)
       {
-	printk ("Unable to read SEEPROM\n");
+	printk("aic78xx: unable to read SEEPROM\n");
       }
       else
       {
-	printk ("done\n");
+	printk("done\n");
 	config.extended = (sc.bios_control & CFEXTEND) >> 7;
 	config.scsi_id = (sc.brtime_id & CFSCSIID);
 	config.parity = (sc.adapter_control & CFSPARITY) ?
@@ -2734,7 +2831,7 @@
     case 2:     /* Wide bus */
       config.scsi_id = inb(HA_SCSICONF(base) + 1) & 0x0F;
       config.bus_type = AIC_WIDE;
-      printk("aic7xxx : Enabling wide channel of %s-Wide\n",
+      printk("aic7xxx: Enabling wide channel of %s-Wide\n",
 	     board_name[config.type]);
       outb(WIDE_BUS, HA_FLAGS(base));
       break;
@@ -2744,12 +2841,12 @@
 #ifdef AIC7XXX_TWIN_SUPPORT
       config.scsi_id_b = inb(HA_SCSICONF(base) + 1) & 0x07;
       config.bus_type = AIC_TWIN;
-      printk("aic7xxx : Enabled channel B of %s-Twin\n",
+      printk("aic7xxx: Enabled channel B of %s-Twin\n",
 	     board_name[config.type]);
       outb(TWIN_BUS, HA_FLAGS(base));
 #else
       config.bus_type = AIC_SINGLE;
-      printk("aic7xxx : Channel B of %s-Twin will be ignored\n",
+      printk("aic7xxx: Channel B of %s-Twin will be ignored\n",
 	     board_name[config.type]);
       outb(0, HA_FLAGS(base));
 #endif
@@ -2759,7 +2856,7 @@
       printk("aic7xxx is an unsupported type 0x%x, please "
 	     "mail deang@ims.com\n", inb(SBLKCTL(base)));
       outb(0, HA_FLAGS(base));
-      return(0);
+      return (0);
   }
 
   /*
@@ -2784,7 +2881,7 @@
       && (config.irq < 9 || config.irq > 15))
   {
     printk("aic7xxx uses unsupported IRQ level, ignoring\n");
-    return(0);
+    return (0);
   }
 
   /*
@@ -2798,7 +2895,7 @@
    if (aic7xxx_boards[config.irq] != NULL)
    {
      printk("aic7xxx_register: Sharing of IRQs is not configured.\n");
-     return(0);
+     return (0);
    }
 #endif
 
@@ -2857,7 +2954,7 @@
   p = (struct aic7xxx_host *) host->hostdata;
 
   /* Initialize the scb array by setting the state to free. */
-  for (i = 0; i < AIC7XXX_MAXSCB; i = i + 1)
+  for (i = 0; i < AIC7XXX_MAXSCB; i++)
   {
     p->scb_array[i].state = SCB_FREE;
     p->scb_array[i].next = NULL;
@@ -2884,14 +2981,23 @@
   if (aic7xxx_boards[config.irq] == NULL)
   {
     /*
+     * Warning! This must be done before requesting the irq.  It is
+     * possible for some boards to raise an interrupt as soon as
+     * they are enabled.  So when we request the irq from the Linux
+     * kernel, an interrupt is triggered immediately.  Therefore, we
+     * must ensure the board data is correctly set before the request.
+     */
+    aic7xxx_boards[config.irq] = host;
+
+    /*
      * Register IRQ with the kernel.
      */
     if (request_irq(config.irq, aic7xxx_isr, SA_INTERRUPT, "aic7xxx"))
     {
       printk("aic7xxx couldn't register irq %d, ignoring\n", config.irq);
-      return(0);
+      aic7xxx_boards[config.irq] = NULL;
+      return (0);
     }
-    aic7xxx_boards[config.irq] = host;
   }
   else
   {
@@ -2966,7 +3072,7 @@
     max_targets = 16;
   }
 
-  for (i = 0; i < max_targets; i = i + 1)
+  for (i = 0; i < max_targets; i++)
   {
     if (have_seeprom)
     {
@@ -3007,14 +3113,16 @@
 
   p->needsdtr = p->needsdtr_copy;
   p->needwdtr = p->needwdtr_copy;
+#if 0
   printk("NeedSdtr = 0x%x, 0x%x\n", p->needsdtr_copy, p->needsdtr);
   printk("NeedWdtr = 0x%x, 0x%x\n", p->needwdtr_copy, p->needwdtr);
+#endif 0
 
-  /* 
+  /*
    * Clear the control byte for every SCB so that the sequencer
    * doesn't get confused and think that one of them is valid
    */
-  for (i = 0; i < config.maxscb; i = i + 1)
+  for (i = 0; i < config.maxscb; i++)
   {
     outb(i, SCBPTR(base));
     outb(0, SCBARRAY(base));
@@ -3052,6 +3160,21 @@
   if (!aic7xxx_no_reset)
   {
     printk("Resetting the SCSI bus...\n");
+    if (p->bus_type == AIC_TWIN)
+    {
+      /*
+       * Select channel B.
+       */
+      outb(2, SBLKCTL(base));
+      outb(SCSIRSTO, SCSISEQ(base));
+      udelay(1000);
+      outb(0, SCSISEQ(base));
+      /*
+       * Select channel A.
+       */
+      outb(0, SBLKCTL(base));
+    }
+
     outb(SCSIRSTO, SCSISEQ(base));
     udelay(1000);
     outb(0, SCSISEQ(base));
@@ -3064,7 +3187,7 @@
    * command is sent to us by the high-level SCSI code.
    */
   UNPAUSE_SEQUENCER(p);
-  return(found);
+  return (found);
 }
 
 /*+F*************************************************************************
@@ -3095,6 +3218,11 @@
   }
 
   /*
+   * Initialize the spurious count to 0.
+   */
+  aic7xxx_spurious_count = 0;
+
+  /*
    * EISA/VL-bus card signature probe.
    */
   for (slot = MINSLOT; slot <= MAXSLOT; slot++)
@@ -3113,8 +3241,13 @@
     type = aic7xxx_probe(slot, HID0(base));
     if (type != AIC_NONE)
     {
-      printk("aic7xxx: hcntrl=0x%x\n", inb(HCNTRL(base)));
+      /*
+       * We found a card, allow 1 spurious interrupt.
+       */
+      aic7xxx_spurious_count = 1;
+
 #if 0
+      printk("aic7xxx: hcntrl=0x%x\n", inb(HCNTRL(base)));
       outb(inb(HCNTRL(base)) | CHIPRST, HCNTRL(base));
       irq = inb(HA_INTDEF(base)) & 0x0F;
 #endif
@@ -3125,6 +3258,11 @@
        * it with the kernel without incident.
        */
       found += aic7xxx_register(template, type, base, irq);
+
+      /*
+       * Disallow spurious interrupts.
+       */
+      aic7xxx_spurious_count = 0;
     }
   }
 
@@ -3135,10 +3273,6 @@
 #define DEVSTATUS 0x41
 #define RAMPSM    0x02
 
-/* This should be defined in pci.h */
-#define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
-#define PCI_DEVICE_ID_ADAPTEC_7872	0x7278
-
   /*
    * PCI-bus probe.
    */
@@ -3212,36 +3346,51 @@
 	 */
 	base = io_port - 0xC01;
 
+	/*
+	 * I don't think we need to bother with allowing
+	 * spurious interrupts for the 787x/7850, but what
+	 * the hey.
+	 */
+	aic7xxx_spurious_count = 1;
+
+#if 0
 	printk("aic7xxx: hcntrl=0x%x\n", inb(HCNTRL(base)));
+#endif
 	outb(inb(HCNTRL(base)) | CHIPRST, HCNTRL(base));
 
 	error = pcibios_read_config_byte(pci_bus, pci_device_fn,
 					 DEVREVID, &devrevid);
 	if (devrevid < 3)
 	{
-	  printk ("aic7xxx_detect: AIC-7870 Rev %c\n", rev_id[devrevid]);
+	  printk("aic7xxx_detect: AIC-7870 Rev %c\n", rev_id[devrevid]);
 	}
 	error = pcibios_read_config_byte(pci_bus, pci_device_fn,
 					 DEVCONFIG, &devconfig);
 	error = pcibios_read_config_byte(pci_bus, pci_device_fn,
 					 DEVSTATUS, &devstatus);
-	printk ("aic7xxx_detect: devconfig 0x%x, devstatus 0x%x\n",
-		devconfig, devstatus);
+	printk("aic7xxx_detect: devconfig 0x%x, devstatus 0x%x\n",
+	       devconfig, devstatus);
 	if (devstatus & RAMPSM)
 	{
-	  printk ("aic7xxx_detect: detected external SCB RAM, "
-		  "mail deang@ims.com for test patch");
+	  printk("aic7xxx_detect: detected external SCB RAM, "
+		 "mail deang@ims.com for test patch");
 	}
 
 	found += aic7xxx_register(template, type, base, irq);
+
+	/*
+	 * Disable spurious interrupts.
+	 */
+	aic7xxx_spurious_count = 0;
+
 	index += 1;
       }
     }
   }
 #endif CONFIG_PCI
 
-  template->name = (char *) aic7xxx_info(NULL);
-  return(found);
+  template->name = aic7xxx_info(NULL);
+  return (found);
 }
 
 
@@ -3270,8 +3419,8 @@
   {
     if (cmd->device->tagged_queue == 0)
     {
-      printk ("aic7xxx_buildscb: Enabling tagged queuing for target %d, "
-	      "channel %d\n", cmd->target, cmd->channel);
+      printk("aic7xxx_buildscb: Enabling tagged queuing for target %d, "
+	     "channel %d\n", cmd->target, cmd->channel);
       cmd->device->tagged_queue = 1;
       cmd->device->current_tag = 1;  /* enable tagging */
     }
@@ -3346,8 +3495,8 @@
   else
   {
 #if 0
-    debug ("aic7xxx_buildscb: Creating scatterlist, addr=0x%lx, length=%d.\n",
-	   (unsigned long) cmd->request_buffer, cmd->request_bufflen);
+    debug("aic7xxx_buildscb: Creating scatterlist, addr=0x%lx, length=%d.\n",
+	  (unsigned long) cmd->request_buffer, cmd->request_bufflen);
 #endif
 #ifdef AIC7XXX_USE_SG
     scb->SG_segment_count = 1;
@@ -3455,7 +3604,7 @@
       memset(scb, 0, sizeof(*scb));
 
       scb->position = p->numscb;
-      p->numscb = p->numscb + 1;
+      p->numscb++;
       scb->state = SCB_ACTIVE;
       scb->next_waiting = SCB_LIST_NULL;
       memcpy(scb->host_scb, &scb, sizeof(scb));
@@ -3526,11 +3675,11 @@
   aic7xxx_status(cmd) = 0;
 
   cmd->result = 0;
-  memset (&cmd->sense_buffer, 0, sizeof (cmd->sense_buffer));
+  memset(&cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
 
   UNPAUSE_SEQUENCER(p);
   restore_flags(flags);
-  return(0);
+  return (0);
 }
 
 /* return values from aic7xxx_kill */
@@ -3597,7 +3746,7 @@
     if (scbsave[i] == scb->position)
     {
       found = 1;
-      i = i - 1;
+      i--;
     }
   }
 
@@ -3722,7 +3871,7 @@
   p->free_scb = scb;              /* add at head of free list */
   cmd->result = cmd->result << 16;
   cmd->scsi_done(cmd);
-  return(status);
+  return (status);
 }
 
 /*+F*************************************************************************
@@ -3751,7 +3900,7 @@
   }
 
   restore_flags(flags);
-  return(rv);
+  return (rv);
 }
 
 /*+F*************************************************************************
@@ -3836,7 +3985,7 @@
   }
 
   restore_flags(flags);
-  return(SCSI_RESET_SUCCESS);
+  return (SCSI_RESET_SUCCESS);
 }
 
 /*+F*************************************************************************
@@ -3874,7 +4023,7 @@
   geom[1] = sectors;
   geom[2] = cylinders;
 
-  return(0);
+  return (0);
 }
 
 #ifdef MODULE
@@ -3884,3 +4033,21 @@
 #include "scsi_module.c"
 #endif
 
+/*
+ * Overrides for Emacs so that we almost follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this