patch-2.4.0-test2 linux/drivers/scsi/aic7xxx.c

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

diff -u --recursive --new-file v2.4.0-test1/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
@@ -243,6 +243,8 @@
 #include <linux/blk.h>
 #include <linux/tqueue.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
 #include "sd.h"
 #include "scsi.h"
 #include "hosts.h"
@@ -264,7 +266,7 @@
  */
 #define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
 
-#define AIC7XXX_C_VERSION  "5.2.0"
+#define AIC7XXX_C_VERSION  "5.2.1"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -281,45 +283,12 @@
 #  define FALSE 0
 #endif
 
-/*
- * We need the bios32.h file if we are kernel version 2.1.92 or less.  The
- * full set of pci_* changes wasn't in place until 2.1.93
- */
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
-#  if defined(__sparc_v9__) || defined(__powerpc__)
-#    error "PPC and Sparc platforms are only support under 2.1.92 and above"
-#  endif
-#  include <linux/bios32.h>
-#endif
-
-#if defined(__powerpc__)
-#  define MMAPIO
-#  ifdef mb
-#    undef mb
-#  endif
-#  define mb() \
-     __asm__ __volatile__("eieio" ::: "memory")
-#elif defined(__i386__)
+#if defined(__powerpc__) || defined(__i386)
 #  define MMAPIO
-#  ifdef mb
-#    undef mb
-#  endif
-#  define mb() \
-     __asm__ __volatile__("lock ; addl $0,0(%%esp)": : :"memory")
-#elif defined(__alpha__)
-#  ifdef mb
-#    undef mb
-#  endif
-#  define mb() \
-     __asm__ __volatile__("mb": : :"memory")
 #endif
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-#  include <linux/spinlock.h>
-#  include <linux/smp.h>
-#  define cpuid smp_processor_id()
 #  if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+#    define cpuid smp_processor_id()
 #    define DRIVER_LOCK_INIT \
        spin_lock_init(&p->spin_lock);
 #    define DRIVER_LOCK \
@@ -337,17 +306,6 @@
 #    define DRIVER_LOCK
 #    define DRIVER_UNLOCK
 #  endif
-#else
-#  define cpuid 0
-#  define DRIVER_LOCK_INIT
-#  define DRIVER_LOCK \
-       save_flags(cpu_flags); \
-       cli();
-#  define DRIVER_UNLOCK \
-       restore_flags(cpu_flags);
-#  define le32_to_cpu(x) (x)
-#  define cpu_to_le32(x) (x)
-#endif
 
 /*
  * You can try raising me if tagged queueing is enabled, or lowering
@@ -359,13 +317,6 @@
 #define AIC7XXX_CMDS_PER_DEVICE 8
 #endif
 
-/* Set this to the delay in seconds after SCSI bus reset. */
-#ifdef CONFIG_AIC7XXX_RESET_DELAY
-#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY
-#else
-#define AIC7XXX_RESET_DELAY 5
-#endif
-
 /*
  * Control collection of SCSI transfer statistics for the /proc filesystem.
  *
@@ -377,28 +328,6 @@
 #endif
 
 /*
- * NOTE: Uncommenting the define below no longer has any effect, the
- *       tagged queue value array is always active now.  I've added
- *       a setup option to set this particular array and I'm hoping
- *       insmod will be smart enough to set it properly as well.  It's
- *       by use of this array that a person can enable tagged queueing.
- *       The DEFAULT_TAG_COMMANDS define has been changed to disable
- *       tagged queueing by default, so if your devices can handle tagged
- *       queueing you will need to add a line to their lilo.conf file like:
- *       append="aic7xxx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}"
- *       which will result in the first four devices on the first two
- *       controllers being set to a tagged queue depth of 32.
- *
- * Set this for defining the number of tagged commands on a device
- * by device, and controller by controller basis.  The first set
- * of tagged commands will be used for the first detected aic7xxx
- * controller, the second set will be used for the second detected
- * aic7xxx controller, and so on.  These values will *only* be used
- * for targets that are tagged queueing capable; these values will
- * be ignored in all other cases.  The tag_commands is an array of
- * 16 to allow for wide and twin adapters.  Twin adapters will use
- * indexes 0-7 for channel 0, and indexes 8-15 for channel 1.
- *
  * *** Determining commands per LUN ***
  * 
  * When AIC7XXX_CMDS_PER_DEVICE is not defined, the driver will use its
@@ -408,7 +337,6 @@
  * use an internal queue depth of 3, with no more than one of those
  * three commands active at one time.
  */
-/* #define AIC7XXX_TAGGED_QUEUEING_BY_DEVICE */
 
 typedef struct
 {
@@ -453,8 +381,8 @@
 
 /*
  * NOTE: The below structure is for reference only, the actual structure
- *       to modify in order to change things is located around line
- *       number 1305
+ *       to modify in order to change things is found after this fake one.
+ *
 adapter_tag_info_t aic7xxx_tag_info[] =
 {
   {DEFAULT_TAG_COMMANDS},
@@ -509,6 +437,7 @@
   "Adaptec AHA-394X Ultra SCSI host adapter",           /* AIC_7882 */
   "Adaptec AHA-398X Ultra SCSI host adapter",           /* AIC_7883 */
   "Adaptec AHA-2944 Ultra SCSI host adapter",           /* AIC_7884 */
+  "Adaptec AHA-2940UW Pro Ultra SCSI host adapter",     /* AIC_7887 */
   "Adaptec AIC-7895 Ultra SCSI host adapter",           /* AIC_7895 */
   "Adaptec AIC-7890/1 Ultra2 SCSI host adapter",        /* AIC_7890 */
   "Adaptec AHA-293X Ultra2 SCSI host adapter",          /* AIC_7890 */
@@ -565,7 +494,7 @@
  * AIC-7770 I/O range to reserve for a card
  */
 #define MINREG                0xC00
-#define MAXREG                0xCBF
+#define MAXREG                0xCFF
 
 #define INTDEF                0x5C      /* Interrupt Definition Register */
 
@@ -828,7 +757,8 @@
   *  and what flags weren't.  This way, I could clean up the flag usage on
   *  a use by use basis.  Doug Ledford
   */
-        AHC_NO_STPWR              = 0x00040000,
+        AHC_MOTHERBOARD           = 0x00020000,
+        AHC_NO_STPWEN             = 0x00040000,
         AHC_RESET_DELAY           = 0x00080000,
         AHC_A_SCANNED             = 0x00100000,
         AHC_B_SCANNED             = 0x00200000,
@@ -1056,11 +986,8 @@
   struct timer_list        dev_timer;
   unsigned long            dev_expires[MAX_TARGETS];
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
   spinlock_t               spin_lock;
   volatile unsigned char   cpu_lock_count[NR_CPUS];
-#endif
-
 
   Scsi_Cmnd               *dev_dtr_cmnd[MAX_TARGETS];
 
@@ -1384,9 +1311,7 @@
  */
 #ifdef MODULE
 static char * aic7xxx = NULL;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)
 MODULE_PARM(aic7xxx, "s");
-#endif
 
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -1444,32 +1369,6 @@
  *
  ***************************************************************************/
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-static inline void
-mdelay(int milliseconds)
-{
-  int i;
-
-  for(i=0; i<milliseconds; i++)
-    udelay(1000);
-}
-
-static inline int
-time_after_eq(unsigned long a, unsigned long b)
-{
-  return((long)((a) - (b)) >= 0L);
-}
-
-static inline int
-timer_pending(struct timer_list *timer)
-{
-  return( timer->prev != NULL );
-}
-
-#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
-
-#endif
-
 static inline unsigned char
 aic_inb(struct aic7xxx_host *p, long port)
 {
@@ -1483,7 +1382,6 @@
   {
     x = inb(p->base + port);
   }
-  mb();
   return(x);
 #else
   return(inb(p->base + port));
@@ -1497,14 +1395,17 @@
   if(p->maddr)
   {
     writeb(val, p->maddr + port);
+    mb(); /* locked operation in order to force CPU ordering */
+    readb(p->maddr + HCNTRL); /* dummy read to flush the PCI write */
   }
   else
   {
     outb(val, p->base + port);
+    mb(); /* locked operation in order to force CPU ordering */
   }
-  mb();
 #else
   outb(val, p->base + port);
+  mb(); /* locked operation in order to force CPU ordering */
 #endif
 }
 
@@ -1642,7 +1543,7 @@
         }
         else if (!strncmp(p, "verbose", n))
         {
-          *(options[i].flag) = 0xff09;
+          *(options[i].flag) = 0xff29;
         }
         else
         {
@@ -1669,7 +1570,7 @@
  *   is important since the sequencer can disable pausing for critical
  *   sections.
  *-F*************************************************************************/
-static inline void
+static void
 pause_sequencer(struct aic7xxx_host *p)
 {
   aic_outb(p, p->pause, HCNTRL);
@@ -1677,6 +1578,10 @@
   {
     ;
   }
+  if(p->features & AHC_ULTRA2)
+  {
+    aic_inb(p, CCSCBCTL);
+  }
 }
 
 /*+F*************************************************************************
@@ -1687,7 +1592,7 @@
  *   Unpause the sequencer. Unremarkable, yet done often enough to
  *   warrant an easy way to do it.
  *-F*************************************************************************/
-static inline void
+static void
 unpause_sequencer(struct aic7xxx_host *p, int unpause_always)
 {
   if (unpause_always ||
@@ -1706,7 +1611,7 @@
  *   Restart the sequencer program from address zero.  This assumes
  *   that the sequencer is already paused.
  *-F*************************************************************************/
-static inline void
+static void
 restart_sequencer(struct aic7xxx_host *p)
 {
   aic_outb(p, 0, SEQADDR0);
@@ -1787,7 +1692,6 @@
   struct ins_format1 *fmt1_ins;
   struct ins_format3 *fmt3_ins;
   unsigned char opcode;
-  volatile unsigned char hcntrl;
 
   instr = *(union ins_formats*) &seqprog[instrptr * 4];
 
@@ -1889,14 +1793,10 @@
         }
       }
       aic_outb(p, (instr.integer & 0xff), SEQRAM);
-      hcntrl = aic_inb(p, HCNTRL);
       aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
-      hcntrl = aic_inb(p, HCNTRL);
       aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
-      hcntrl = aic_inb(p, HCNTRL);
       aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
-      hcntrl = aic_inb(p, HCNTRL);
-      udelay(50);
+      udelay(10);
       break;
 
     default:
@@ -2151,7 +2051,7 @@
      * Use async transfers for this target
      */
     *options = 0;
-    *period = 0;
+    *period = 255;
     syncrate = NULL;
   }
   return (syncrate);
@@ -2950,6 +2850,7 @@
 #define WIDE_INQUIRY_BITS 0x60
 #define SYNC_INQUIRY_BITS 0x10
 #define SCSI_VERSION_BITS 0x07
+#define SCSI_DT_BIT       0x04
       if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
            (p->features & AHC_WIDE) )
       {
@@ -2968,48 +2869,66 @@
                                                    AHC_TRANS_CUR) );
         unpause_sequencer(p, FALSE);
       }
-      if (buffer[7] & SYNC_INQUIRY_BITS)
+      if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
+            p->transinfo[tindex].user_offset )
       {
-        p->needsdtr |= (1<<tindex);
-        p->needsdtr_copy |= (1<<tindex);
-
         p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
         p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
-        if (p->transinfo[tindex].user_offset)
+        if (p->features & AHC_ULTRA2)
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+        else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+        else
+          p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+        if ( (((buffer[2] & SCSI_VERSION_BITS) == 3) ||
+               (buffer[56] & SCSI_DT_BIT) ||
+	       (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
+               (p->transinfo[tindex].user_period <= 9) &&
+               (p->transinfo[tindex].user_options) )
         {
-          if (p->features & AHC_ULTRA2)
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-          else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
-          else
-            p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+          p->needppr |= (1<<tindex);
+          p->needppr_copy |= (1<<tindex);
+          p->needsdtr &= ~(1<<tindex);
+          p->needsdtr_copy &= ~(1<<tindex);
+          p->needwdtr &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
+          p->dev_flags[tindex] |= DEVICE_SCSI_3;
+        }
+        else
+        {
+          p->needsdtr |= (1<<tindex);
+          p->needsdtr_copy |= (1<<tindex);
+          p->transinfo[tindex].goal_period = 
+            MAX(10, p->transinfo[tindex].goal_period);
+          p->transinfo[tindex].goal_options = 0;
         }
       }
       else
       {
         p->needsdtr &= ~(1<<tindex);
         p->needsdtr_copy &= ~(1<<tindex);
-        p->transinfo[tindex].goal_period = 0;
+        p->transinfo[tindex].goal_period = 255;
         p->transinfo[tindex].goal_offset = 0;
         p->transinfo[tindex].goal_options = 0;
       }
-      if ( (buffer[2] & SCSI_VERSION_BITS) == 3 )
+      /*
+       * This is needed to work around a sequencer bug for now.  Regardless
+       * of the controller in use, if we have a Quantum drive, we need to
+       * limit the speed to 80MByte/sec.  As soon as I get a fixed version
+       * of the sequencer, this code will get yanked.
+       */
+      if(!strncmp(buffer + 8, "QUANTUM", 7) &&
+         p->transinfo[tindex].goal_options )
       {
-        p->dev_flags[tindex] |= DEVICE_SCSI_3;
-        /*
-         * OK, we are a SCSI 3 device and we are in need of negotiation.
-         * Use PPR messages instead of WDTR and SDTR messages.
-         */
-        if ( (p->needsdtr & (1<<tindex)) ||
-             (p->needwdtr & (1<<tindex)) )
-        {
-          p->needppr |= (1<<tindex);
-          p->needppr_copy |= (1<<tindex);
-        }
-        p->needwdtr &= ~(1<<tindex);
-        p->needwdtr_copy &= ~(1<<tindex);
-        p->needsdtr &= ~(1<<tindex);
-        p->needsdtr_copy &= ~(1<<tindex);
+        p->transinfo[tindex].goal_period = 
+          MAX(p->transinfo[tindex].goal_period, 10);
+        p->transinfo[tindex].goal_options = 0;
+        p->needppr &= ~(1<<tindex);
+        p->needppr_copy &= ~(1<<tindex);
+        p->needsdtr |= (1<<tindex);
+        p->needsdtr_copy |= (1<<tindex);
+        p->needwdtr |= (1<<tindex);
+        p->needwdtr_copy |= (1<<tindex);
       }
       /*
        * Get the INQUIRY checksum.  We use this on Ultra 160/m
@@ -3039,6 +2958,7 @@
 #undef WIDE_INQUIRY_BITS
 #undef SYNC_INQUIRY_BITS
 #undef SCSI_VERSION_BITS
+#undef SCSI_DT_BIT
     }
   }
   else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
@@ -4170,12 +4090,7 @@
 {
   unsigned char status1;
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
   pci_read_config_byte(p->pdev, PCI_STATUS + 1, &status1);
-#else
-  pcibios_read_config_byte(p->pci_bus, p->pci_device_fn,
-                           PCI_STATUS + 1, &status1);
-#endif
 
   if ( (status1 & DPE) && (aic7xxx_verbose & VERBOSE_MINOR_ERROR) )
     printk(WARN_LEAD "Data Parity Error during PCI address or PCI write"
@@ -4196,12 +4111,7 @@
     printk(WARN_LEAD "Data Parity Error has been reported via PCI pin "
       "PERR#\n", p->host_no, -1, -1, -1);
   
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
   pci_write_config_byte(p->pdev, PCI_STATUS + 1, status1);
-#else
-  pcibios_write_config_byte(p->pci_bus, p->pci_device_fn,
-                            PCI_STATUS + 1, status1);
-#endif
   if (status1 & (DPR|RMA|RTA))
     aic_outb(p,  CLRPARERR, CLRINT);
 
@@ -4226,11 +4136,7 @@
   unsigned long cpu_flags = 0;
   struct aic7xxx_scb *scb;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)   
-  DRIVER_LOCK
-#else
   spin_lock_irqsave(&io_request_lock, cpu_flags);
-#endif
   p->dev_timer_active &= ~(0x01 << MAX_TARGETS);
   if ( (p->dev_timer_active & (0x01 << p->scsi_id)) &&
        time_after_eq(jiffies, p->dev_expires[p->scsi_id]) )
@@ -4287,11 +4193,7 @@
   }
 
   aic7xxx_run_waiting_queues(p);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)   
-  DRIVER_UNLOCK
-#else
   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
-#endif
 }
 
 /*+F*************************************************************************
@@ -4673,7 +4575,9 @@
            * As per the draft specs, any device capable of supporting any of
            * the option values other than 0 are not allowed to reject the
            * PPR message.  Instead, they must negotiate out what they do
-           * support instead of rejecting our offering.
+           * support instead of rejecting our offering or else they cause
+           * a parity error during msg_out phase to signal that they don't
+           * like our settings.
            */
           p->needppr &= ~target_mask;
           p->needppr_copy &= ~target_mask;
@@ -4813,39 +4717,36 @@
             case CHECK_CONDITION:
               if ( !(scb->flags & SCB_SENSE) )
               {
-		unsigned char *sense_buffer;
-                /*
-                 * XXX - How do we save the residual (if there is one).
-                 */
-                if ( hscb->residual_SG_segment_count != 0 )
-                  aic7xxx_calculate_residual(p, scb);
-
                 /*
-                   * Send a sense command to the requesting target.
+                 * Send a sense command to the requesting target.
                  * XXX - revisit this and get rid of the memcopys.
-                   */
+                 */
                 memcpy(scb->sense_cmd, &generic_sense[0],
                        sizeof(generic_sense));
 
                 scb->sense_cmd[1] = (cmd->lun << 5);
                 scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
 
-		sense_buffer = cmd->sense_buffer;
                 scb->sg_list[0].length = 
                   cpu_to_le32(sizeof(cmd->sense_buffer));
+		scb->sg_list[0].address =
+                        cpu_to_le32(pci_map_single(p->pdev, cmd->sense_buffer,
+                                                   sizeof(cmd->sense_buffer),
+                                                   PCI_DMA_FROMDEVICE));
 
                 /*
                  * XXX - We should allow disconnection, but can't as it
                  * might allow overlapped tagged commands.
                  */
-                  /* hscb->control &= DISCENB; */
+                /* hscb->control &= DISCENB; */
                 hscb->control = 0;
                 hscb->target_status = 0;
                 hscb->SG_list_pointer = 
 		  cpu_to_le32(SCB_DMA_ADDR(scb, scb->sg_list));
-                hscb->data_count = scb->sg_list[0].length;
                 hscb->SCSI_cmd_pointer = 
                   cpu_to_le32(SCB_DMA_ADDR(scb, scb->sense_cmd));
+                hscb->data_count = scb->sg_list[0].length;
+                hscb->data_pointer = scb->sg_list[0].address;
                 hscb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
                 hscb->residual_SG_segment_count = 0;
                 hscb->residual_data_count[0] = 0;
@@ -4855,53 +4756,6 @@
                 scb->sg_count = hscb->SG_segment_count = 1;
                 scb->sg_length = sizeof(cmd->sense_buffer);
                 scb->tag_action = 0;
-                /*
-                 * This problem could be caused if the target has lost power
-                 * or found some other way to loose the negotiation settings,
-                 * so if needed, we'll re-negotiate while doing the sense cmd.
-                 * However, if this SCB already was attempting to negotiate,
-                 * then we assume this isn't the problem and skip this part.
-                 */
-                if ( (scb->cmd->cmnd[0] != TEST_UNIT_READY) &&
-                     (p->dev_flags[tindex] & DEVICE_SCANNED) &&
-                     !(p->dtr_pending & target_mask) ) 
-                {
-                  p->needppr |= (p->needppr_copy & target_mask);
-                  p->needwdtr |= (p->needwdtr_copy & target_mask);
-                  p->needsdtr |= (p->needsdtr_copy & target_mask);
-                }
-                else if ( scb->cmd == p->dev_dtr_cmnd[tindex] )
-                {
-                  /*
-                   * This is already a negotiation command, so we must have
-                   * already done PPR, WDTR or SDTR.  Since our negotiation
-                   * could have gotten rejected, we don't really know the
-                   * full state of things.  Don't do anything here, and allow
-                   * the negotiation_complete() handler to do the right
-                   * thing.
-                   */
-
-                  /*
-                   * This is the important part though.  We are getting sense
-                   * info back from this device.  It's going into a fake
-                   * command.  We need to put that into the real command
-                   * instead so that the mid level SCSI code can act upon it.
-                   * So, when we set up these fake commands, the next pointer
-                   * is used to point to the real command.  Use that to change
-                   * the address of our sense_buffer[] to the real command.
-                   * However, don't do this if the real command is also a
-                   * TEST_UNIT_READY as it will most likely pull down its own
-                   * SENSE information anyway.
-                   */
-                  if (cmd->next->cmnd[0] != TEST_UNIT_READY)
-		    sense_buffer = cmd->next->sense_buffer;
-                }
-		scb->sg_list[0].address =
-                        cpu_to_le32(pci_map_single(p->pdev, sense_buffer,
-                                                   sizeof(cmd->sense_buffer),
-                                                   PCI_DMA_FROMDEVICE));
-                hscb->data_pointer = scb->sg_list[0].address;
-
                 scb->flags |= SCB_SENSE;
                 /*
                  * Ensure the target is busy since this will be an
@@ -4924,7 +4778,7 @@
                 aic7xxx_error(cmd) = DID_OK;
                 break;
               }  /* first time sense, no errors */
-              aic7xxx_error(cmd) = DID_OK;
+              aic7xxx_error(cmd) = DID_ERROR;
               scb->flags &= ~SCB_SENSE;
               break;
 
@@ -5171,51 +5025,14 @@
         }
         else if (scb->flags & SCB_MSGOUT_PPR)
         {
-          unsigned int max_sync, period;
-          unsigned char options = 0;
-
-          if (p->features & AHC_ULTRA2)
-          {
-            if ( (aic_inb(p, SBLKCTL) & ENAB40) &&
-                !(aic_inb(p, SSTAT2) & EXP_ACTIVE) )
-            {
-              if( (p->features & AHC_ULTRA3) &&
-                  (p->dev_flags[tindex] & DEVICE_SCSI_3) &&
-                  (p->transinfo[tindex].goal_width ==
-                   MSG_EXT_WDTR_BUS_16_BIT) &&
-                  (p->transinfo[tindex].goal_options != 0) )
-              {
-                max_sync = AHC_SYNCRATE_ULTRA3;
-                options = p->transinfo[tindex].goal_options;
-              }
-              else
-              {
-                max_sync = AHC_SYNCRATE_ULTRA2;
-              }
-            }
-            else
-            {
-              max_sync = AHC_SYNCRATE_ULTRA;
-            }
-          }
-          else if (p->features & AHC_ULTRA)
-          {
-            max_sync = AHC_SYNCRATE_ULTRA;
-          }
-          else
-          {
-            max_sync = AHC_SYNCRATE_FAST;
-          }
-          period = p->transinfo[tindex].goal_period;
-          aic7xxx_find_syncrate(p, &period, max_sync, &options);
-          p->transinfo[tindex].goal_period = period;
-          p->transinfo[tindex].goal_options = options;
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Sending PPR (%d/%d/%d/%d) message.\n",
-                   p->host_no, CTL_OF_SCB(scb), period,
+                   p->host_no, CTL_OF_SCB(scb),
+                   p->transinfo[tindex].goal_period,
                    p->transinfo[tindex].goal_offset,
-                   p->transinfo[tindex].goal_width, options);
+                   p->transinfo[tindex].goal_width,
+                   p->transinfo[tindex].goal_options);
           }
           aic7xxx_construct_ppr(p, scb);
         }
@@ -5261,8 +5078,7 @@
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
             printk(INFO_LEAD "Sending SDTR %d/%d message.\n", p->host_no,
-                   CTL_OF_SCB(scb),
-                   p->transinfo[tindex].goal_period,
+                   CTL_OF_SCB(scb), period,
                    p->transinfo[tindex].goal_offset);
           }
           aic7xxx_construct_sdtr(p, period,
@@ -5375,15 +5191,15 @@
         resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
         resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
           (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
-          (aic_inb(p, SCB_RESID_DCNT + 2) << 24);
-        index = scb->sg_count - resid_sgcnt;
+          (aic_inb(p, SCB_RESID_DCNT + 2) << 16);
+        index = scb->sg_count - (resid_sgcnt + 1);
         native_addr = le32_to_cpu(scb->sg_list[index].address);
         native_length = le32_to_cpu(scb->sg_list[index].length);
         /*
          * Make sure this is a valid sg_seg for the given pointer
          */
         if(cur_addr < native_addr ||
-           cur_addr > (native_addr + native_length))
+           cur_addr > (native_addr + native_length + 1))
         {
           printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
                  p->host_no, CTL_OF_SCB(scb), cur_addr);
@@ -5400,16 +5216,31 @@
                    p->host_no, CTL_OF_SCB(scb),
                    le32_to_cpu(scb->sg_list[index + 1].address),
                    le32_to_cpu(scb->sg_list[index + 1].length));
+          printk(WARN_LEAD "  cur_address:0x%x resid_dcnt:0x%06x\n",
+                 p->host_no, CTL_OF_SCB(scb),
+                 cur_addr, resid_dcnt);
           break;
         }
 
-        /*
-         * If our current address matches the sg_seg->address then we
-         * have to back up the sg array to the previous segment and set
-         * it up to have only one byte of transfer left to go.
-         */
-        if(cur_addr == native_addr)
+        if( (resid_sgcnt == 0) &&
+            ((resid_dcnt == 0) || (resid_dcnt == 0xffffff)))
+        {
+          /*
+           * We are at the end of the transfer and this is about a byte
+           * we ignored already (because the sequencer knew this was
+           * the last segment and set the adapter to ignore any wide
+           * residue bytes that might come through, which is only done
+           * on the last scatter gather segment of transfers).
+           */
+          break;
+        }
+        else if(cur_addr == native_addr)
         {
+          /*
+           * If our current address matches the sg_seg->address then we
+           * have to back up the sg array to the previous segment and set
+           * it up to have only one byte of transfer left to go.
+           */
           if(index == 0)
           {
             printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
@@ -5439,39 +5270,6 @@
           aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
           aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
           aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
-          /*
-           * The sequencer actually wants to find the new address and byte
-           * count in the SHCNT and SHADDR register sets.  These registers
-           * are a shadow of the regular HCNT and HADDR registers.  On the
-           * Ultra2 controllers, these registers are read only and the way
-           * we have to set their values is to put the values we want into
-           * the HCNT and HADDR registers and then output PRELOADEN into
-           * the DFCNTRL register which causes the card to latch the current
-           * values in the HADDR and HCNT registers and drop it through to
-           * the shadow registers.  On older cards we copy them directly
-           * across by hand.
-           */
-          if(p->features & AHC_ULTRA2)
-          {
-            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-            i=0;
-            udelay(1);
-            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
-            {
-              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-              udelay(1);
-            }
-          }
-          else
-          {
-            aic_outb(p, 1, STCNT); 
-            aic_outb(p, 0, STCNT + 1); 
-            aic_outb(p, 0, STCNT + 2); 
-            aic_outb(p, cur_addr & 0xff, SHADDR);
-            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
-            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
-            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
-          }
         }
         else
         {
@@ -5491,28 +5289,46 @@
           aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
           aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
           aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
-          if(p->features & AHC_ULTRA2)
+        }
+        /*
+         * The sequencer actually wants to find the new address and byte
+         * count in the SHCNT and SHADDR register sets.  These registers
+         * are a shadow of the regular HCNT and HADDR registers.  On the
+         * Ultra2 controllers, these registers are read only and the way
+         * we have to set their values is to put the values we want into
+         * the HCNT and HADDR registers and then output PRELOADEN into
+         * the DFCNTRL register which causes the card to latch the current
+         * values in the HADDR and HCNT registers and drop it through to
+         * the shadow registers.  On older cards we copy them directly
+         * across by hand.
+         */
+        if(p->features & AHC_ULTRA2)
+        {
+          aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+          i=0;
+          udelay(1);
+          while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
           {
-            aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-            i=0;
             udelay(1);
-            while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
-            {
-              aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
-              udelay(1);
-            }
           }
-          else
+          aic_outb(p, aic_inb(p, DMAPARAMS) & ~(SCSIEN|HDMAEN), DFCNTRL);
+          i=0;
+          udelay(1);
+          while(((aic_inb(p, DFCNTRL) & (SCSIEN|HDMAEN)) != 0) && (i++ < 1000))
           {
-            aic_outb(p, resid_dcnt & 0xff, STCNT); 
-            aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
-            aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
-            aic_outb(p, cur_addr & 0xff, SHADDR);
-            aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
-            aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
-            aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+            udelay(1);
           }
         }
+        else
+        {
+          aic_outb(p, resid_dcnt & 0xff, STCNT); 
+          aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1); 
+          aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2); 
+          aic_outb(p, cur_addr & 0xff, SHADDR);
+          aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+          aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+          aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+        }
       }
       break;
 
@@ -5921,6 +5737,7 @@
           reply = TRUE;
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_PPR;
+	  p->dev_flags[tindex] |= DEVICE_SCSI_3;
           if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
           {
             /*
@@ -5954,7 +5771,6 @@
               p->transinfo[tindex].user_width;
             p->transinfo[tindex].goal_options =
               p->transinfo[tindex].user_options;
-            p->needppr_copy |= target_mask;
           }
           if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
           {
@@ -5988,6 +5804,25 @@
               break;
             }
           }
+          if ( (p->transinfo[tindex].goal_period > 9) ||
+               (p->transinfo[tindex].goal_options == 0) )
+          {
+            scb->flags &= ~SCB_MSGOUT_BITS;
+            reject = TRUE;
+            reply = FALSE;
+            p->needppr &= ~(1 << tindex);
+            p->needppr_copy &= ~(1 << tindex);
+            if ( p->transinfo[tindex].goal_offset )
+            {
+              p->needsdtr |= (1 << tindex);
+              p->needsdtr_copy |= (1 << tindex);
+            }
+            if ( p->transinfo[tindex].goal_width )
+            {
+              p->needwdtr |= (1 << tindex);
+              p->needwdtr_copy |= (1 << tindex);
+            }
+          }
         }
         else
         {
@@ -5995,7 +5830,7 @@
           {
             default:
             {
-              reply = TRUE;
+              reject = TRUE;
               if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
                    ((p->dev_flags[tindex] & DEVICE_PRINT_DTR) ||
                     (aic7xxx_verbose > 0xffff)) )
@@ -6021,27 +5856,18 @@
           }
         }
 
-        aic7xxx_set_width(p, target, channel, lun, bus_width,
-                          AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-        syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
-                                         &new_trans_options);
-        aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
-        aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                             offset, new_trans_options,
-                             AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-
-        if( (offset != saved_offset) ||
-            (trans_options != new_trans_options) ||
-            ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) !=
-             (SCB_MSGOUT_SENT|SCB_MSGOUT_PPR)) )
+        if ( !reject )
         {
           aic7xxx_set_width(p, target, channel, lun, bus_width,
-                            AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+                            AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          syncrate = aic7xxx_find_syncrate(p, &period, maxsync,
+                                           &new_trans_options);
+          aic7xxx_validate_offset(p, syncrate, &offset, bus_width);
           aic7xxx_set_syncrate(p, syncrate, target, channel, period,
                                offset, new_trans_options,
-                               AHC_TRANS_GOAL|AHC_TRANS_QUITE);
-          reply = TRUE;
+                               AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
         }
+
         p->dtr_pending &= ~target_mask;
         p->needppr &= ~target_mask;
         if(reply)
@@ -6445,15 +6271,33 @@
       }
     }
     /*
-     * Restarting the sequencer will stop the selection and make sure devices
-     * are allowed to reselect in.
+     * Keep the sequencer from trying to restart any selections
+     */
+    aic_outb(p, aic_inb(p, SCSISEQ) & ~ENSELO, SCSISEQ);
+    /*
+     * Make sure the data bits on the bus are released
+     * Don't do this on 7770 chipsets, it makes them give us
+     * a BRKADDRINT and kills the card.
      */
-    aic_outb(p, 0, SCSISEQ);
+    if( (p->chip & ~AHC_CHIPID_MASK) == AHC_PCI )
+      aic_outb(p, 0, SCSIBUSL);
+
+    /*
+     * Delay for the selection timeout delay period then stop the selection
+     */
+    udelay(301);
     aic_outb(p, CLRSELINGO, CLRSINT0);
+    /*
+     * Clear out all the interrupt status bits
+     */
     aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
     p->flags &= ~AHC_HANDLING_REQINITS;
     aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
     aic_outb(p, CLRSCSIINT, CLRINT);
+    /*
+     * Restarting the sequencer will stop the selection and make sure devices
+     * are allowed to reselect in.
+     */
     restart_sequencer(p);
     unpause_sequencer(p, TRUE);
   }
@@ -6519,7 +6363,9 @@
      * A parity error has occurred during a data
      * transfer phase. Flag it and continue.
      */
-    if( (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) && (lastphase == P_DATAIN) )
+    if( (p->features & AHC_ULTRA3) && 
+        (aic_inb(p, SCSIRATE) & AHC_SYNCRATE_CRC) &&
+        (lastphase == P_DATAIN) )
     {
       printk(WARN_LEAD "CRC error during %s phase.\n",
              p->host_no, CTL_OF_SCB(scb), phase);
@@ -6544,13 +6390,50 @@
                p->host_no, CTL_OF_SCB(scb));
       }
     }
-    else
+    else if( (lastphase == P_MESGOUT) &&
+             (cmd == p->dev_dtr_cmnd[tindex]) &&
+             (scb->flags & SCB_MSGOUT_PPR) )
     {
-      printk(WARN_LEAD "Parity error during %s phase.\n",
-             p->host_no, CTL_OF_SCB(scb), phase);
+      /*
+       * As per the draft specs, any device capable of supporting any of
+       * the option values other than 0 are not allowed to reject the
+       * PPR message.  Instead, they must negotiate out what they do
+       * support instead of rejecting our offering or else they cause
+       * a parity error during msg_out phase to signal that they don't
+       * like our settings.
+       */
+      p->needppr &= ~(1 << tindex);
+      p->needppr_copy &= ~(1 << tindex);
+      aic7xxx_set_width(p, scb->cmd->target, scb->cmd->channel, scb->cmd->lun,
+                        MSG_EXT_WDTR_BUS_8_BIT,
+                        (AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE));
+      aic7xxx_set_syncrate(p, NULL, scb->cmd->target, scb->cmd->channel, 0, 0,
+                           0, AHC_TRANS_ACTIVE|AHC_TRANS_CUR|AHC_TRANS_QUITE);
+      p->transinfo[tindex].goal_options = 0;
+      p->dtr_pending &= ~(1 << tindex);
+      scb->flags &= ~SCB_MSGOUT_BITS;
+      if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+      {
+        printk(INFO_LEAD "parity error during PPR message, reverting "
+               "to WDTR/SDTR\n", p->host_no, CTL_OF_SCB(scb));
+      }
+      if ( p->transinfo[tindex].goal_width )
+      {
+        p->needwdtr |= (1 << tindex);
+        p->needwdtr_copy |= (1 << tindex);
+      }
+      if ( p->transinfo[tindex].goal_offset )
+      {
+        if( p->transinfo[tindex].goal_period <= 9 )
+        {
+          p->transinfo[tindex].goal_period = 10;
+        }
+        p->needsdtr |= (1 << tindex);
+        p->needsdtr_copy |= (1 << tindex);
+      }
+      scb = NULL;
     }
-
-    if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
+    else if(p->dev_flags[tindex] & DEVICE_PARITY_ERROR)
     {
       struct aic7xxx_syncrate *syncrate;
       unsigned int period = p->transinfo[tindex].cur_period;
@@ -6562,6 +6445,8 @@
        * instead of slowing down if those exist.  That's hard to do with simple
        * checksums though.
        */
+      printk(WARN_LEAD "Parity error during %s phase.\n",
+             p->host_no, CTL_OF_SCB(scb), phase);
       if((syncrate = aic7xxx_find_syncrate(p, &period, 0, &options)) != NULL)
       {
         syncrate++;
@@ -6569,20 +6454,59 @@
             (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
         {
           p->transinfo[tindex].goal_period = syncrate->period;
-          if( !(syncrate->sxfr_ultra2 & 0x40) )
+          if( p->transinfo[tindex].goal_period > 9 )
           {
             p->transinfo[tindex].goal_options = 0;
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr |= (1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy |= (1<<tindex);
+            if (p->transinfo[tindex].goal_width)
+            {
+              p->needwdtr |= (1<<tindex);
+              p->needwdtr_copy |= (1<<tindex);
+            }
+          }
+        }
+        else if (p->transinfo[tindex].goal_width)
+        {
+          p->transinfo[tindex].goal_width = 0;
+          p->needwdtr &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
+          p->transinfo[tindex].goal_offset =
+            p->transinfo[tindex].user_offset;
+          p->transinfo[tindex].goal_period =
+            p->transinfo[tindex].user_period;
+          p->transinfo[tindex].goal_options =
+            p->transinfo[tindex].user_options;
+          if( p->transinfo[tindex].goal_period <= 9 )
+          {
+            p->needppr |= (1<<tindex);
+            p->needsdtr &= ~(1<<tindex);
+            p->needppr_copy |= (1<<tindex);
+            p->needsdtr_copy &= ~(1<<tindex);
+          }
+          else
+          {
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr |= (1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy |= (1<<tindex);
           }
         }
         else
         {
           p->transinfo[tindex].goal_offset = 0;
-          p->transinfo[tindex].goal_period = 0;
+          p->transinfo[tindex].goal_period = 255;
           p->transinfo[tindex].goal_options = 0;
+          p->transinfo[tindex].goal_width = 0;
+          p->needppr &= ~(1<<tindex);
+          p->needsdtr &= ~(1<<tindex);
+          p->needwdtr &= ~(1<<tindex);
+          p->needppr_copy &= ~(1<<tindex);
+          p->needsdtr_copy &= ~(1<<tindex);
+          p->needwdtr_copy &= ~(1<<tindex);
         }
-        p->needppr |= (p->needppr_copy & (1<<tindex));
-        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
-        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
       }
       p->dev_flags[tindex] &= ~DEVICE_PARITY_ERROR;
     }
@@ -6600,6 +6524,7 @@
     if (mesg_out != MSG_NOOP)
     {
       aic_outb(p, mesg_out, MSG_OUT);
+      aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
       scb = NULL;
     }
     aic_outb(p, CLRSCSIPERR, CLRSINT1);
@@ -6791,7 +6716,7 @@
 {
   struct aic7xxx_scb *scb = NULL;
   Scsi_Cmnd *cmd;
-  unsigned char scb_index;
+  unsigned char scb_index, tindex;
 
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
   if( (p->isr_count < 16) && (aic7xxx_verbose > 0xffff) )
@@ -6817,23 +6742,21 @@
     scb_index = p->qoutfifo[p->qoutfifonext];
     p->qoutfifo[p->qoutfifonext++] = SCB_LIST_NULL;
     if ( scb_index >= p->scb_data->numscbs )
-      scb = NULL;
-    else
-      scb = p->scb_data->scb_array[scb_index];
-    if (scb == NULL)
     {
       printk(WARN_LEAD "CMDCMPLT with invalid SCB index %d\n", p->host_no,
         -1, -1, -1, scb_index);
       continue;
     }
-    else if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+    scb = p->scb_data->scb_array[scb_index];
+    if (!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
     {
       printk(WARN_LEAD "CMDCMPLT without command for SCB %d, SCB flags "
         "0x%x, cmd 0x%lx\n", p->host_no, -1, -1, -1, scb_index, scb->flags,
         (unsigned long) scb->cmd);
       continue;
     }
-    else if (scb->flags & SCB_QUEUED_ABORT)
+    tindex = TARGET_INDEX(scb->cmd);
+    if (scb->flags & SCB_QUEUED_ABORT)
     {
       pause_sequencer(p);
       if ( ((aic_inb(p, LASTPHASE) & PHASE_MASK) != P_BUSFREE) &&
@@ -6856,6 +6779,43 @@
        */
       scb->flags &= ~(SCB_ABORT|SCB_RESET);
     }
+    else if (scb->flags & SCB_SENSE)
+    {
+      char *buffer = &scb->cmd->sense_buffer[0];
+      if (scb->cmd == p->dev_dtr_cmnd[tindex])
+      {
+        struct aic7xxx_scb *old_scb;
+        /*
+         * We have valid sense data, send it back immediately.
+         */
+        old_scb = p->scb_data->scb_array[scb->cmd->next->tag];
+        *old_scb->cmd->sense_buffer = *scb->cmd->sense_buffer;
+        old_scb->hscb->target_status = scb->hscb->target_status;
+        old_scb->cmd->result = scb->hscb->target_status;
+        old_scb->cmd->result |= (DID_ERROR << 16);
+        aic7xxx_status(old_scb->cmd) = scb->hscb->target_status;
+        scbq_remove(&p->waiting_scbs, old_scb);
+        scbq_remove(&p->delayed_scbs[tindex], old_scb);
+        scb->cmd->next = NULL;
+	aic7xxx_done(p, scb);
+        aic7xxx_done(p, old_scb);
+	continue;
+      } 
+      else if (buffer[12] == 0x47 || buffer[12] == 0x54)
+      {
+        /*
+         * SCSI errors, run domain validation and re-run negotiation
+         */
+        p->needdv |= (1<<tindex);
+        /*
+         * Signal that we need to re-negotiate things, this also gets us our
+         * INQUIRY command to re-checksum off of.
+         */
+        p->needppr |= (p->needppr_copy & (1<<tindex));
+        p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
+        p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
+      }
+    }
     switch (status_byte(scb->hscb->target_status))
     {
       case QUEUE_FULL:
@@ -6985,6 +6945,13 @@
 
   if (intstat & SEQINT)
   {
+    /*
+     * Read the CCSCBCTL register to work around a bug in the Ultra2 cards
+     */
+    if(p->features & AHC_ULTRA2)
+    {
+      aic_inb(p, CCSCBCTL);
+    }
     aic7xxx_handle_seqint(p, intstat);
   }
 
@@ -7019,10 +6986,10 @@
   p = (struct aic7xxx_host *)dev_id;
   if(!p)
     return;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
   spin_lock_irqsave(&io_request_lock, cpu_flags);
   if(test_and_set_bit(AHC_IN_ISR_BIT, (void *)&p->flags))
   {
+    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
     return;
   }
   do
@@ -7033,21 +7000,6 @@
   aic7xxx_run_waiting_queues(p);
   clear_bit(AHC_IN_ISR_BIT, (void *)&p->flags);
   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
-#else
-  if(set_bit(AHC_IN_ISR_BIT, (int *)&p->flags))
-  {
-    return;
-  }
-  DRIVER_LOCK
-  do
-  {
-    aic7xxx_isr(irq, dev_id, regs);
-  } while ( (aic_inb(p, INTSTAT) & INT_PEND) );
-  DRIVER_UNLOCK
-  aic7xxx_done_cmds_complete(p);
-  aic7xxx_run_waiting_queues(p);
-  clear_bit(AHC_IN_ISR_BIT, (int *)&p->flags);
-#endif
 }
 
 /*+F*************************************************************************
@@ -7067,7 +7019,7 @@
  *   with queue depths for individual devices.  It also allows tagged
  *   queueing to be [en|dis]abled for a specific adapter.
  *-F*************************************************************************/
-static void
+static int
 aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
 {
   int default_depth = 3;
@@ -7077,6 +7029,14 @@
   tindex = device->id | (device->channel << 3);
   target_mask = (1 << tindex);
 
+  if (p->dev_max_queue_depth[tindex] > 1)
+  {
+    /*
+     * We've already scanned this device, leave it alone
+     */
+    return(p->dev_max_queue_depth[tindex]);
+  }
+
   device->queue_depth = default_depth;
   p->dev_temp_queue_depth[tindex] = 1;
   p->dev_max_queue_depth[tindex] = 1;
@@ -7145,6 +7105,7 @@
       }
     }
   }
+  return(p->dev_max_queue_depth[tindex]);
 }
 
 /*+F*************************************************************************
@@ -7172,8 +7133,7 @@
   {
     if (device->host == host)
     {
-      aic7xxx_device_queue_depth(p, device);
-      scbnum += device->queue_depth;
+      scbnum += aic7xxx_device_queue_depth(p, device);
     }
   }
   while (scbnum > p->scb_data->numscbs)
@@ -7481,7 +7441,6 @@
    */
   CLOCK_PULSE(p);
   aic_outb(p, 0, SEECTL);
-  CLOCK_PULSE(p);
 }
 
 /*+F*************************************************************************
@@ -7757,8 +7716,6 @@
   }
 }
 
-#undef CLOCK_PULSE
-
 /*+F*************************************************************************
  * Function:
  *   aic785x_cable_detect
@@ -7773,16 +7730,64 @@
   unsigned char brdctl;
 
   aic_outb(p, BRDRW | BRDCS, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   aic_outb(p, 0, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   brdctl = aic_inb(p, BRDCTL);
-  udelay(1);
+  CLOCK_PULSE(p);
   *int_50 = !(brdctl & BRDDAT5);
   *ext_present = !(brdctl & BRDDAT6);
   *eeprom = (aic_inb(p, SPIOCAP) & EEPROM);
 }
 
+#undef CLOCK_PULSE
+
+/*+F*************************************************************************
+ * Function:
+ *   aic2940_uwpro_cable_detect
+ *
+ * Description:
+ *   Detect the cables that are present on the 2940-UWPro cards
+ *
+ * NOTE: This functions assumes the SEEPROM will have already been aquired
+ *       prior to invocation of this function.
+ *-F*************************************************************************/
+static void
+aic2940_uwpro_wide_cable_detect(struct aic7xxx_host *p, int *int_68,
+    int *ext_68, int *eeprom)
+{
+  unsigned char brdctl;
+
+  /*
+   * First read the status of our cables.  Set the rom bank to
+   * 0 since the bank setting serves as a multiplexor for the
+   * cable detection logic.  BRDDAT5 controls the bank switch.
+   */
+  write_brdctl(p, 0);
+
+  /*
+   * Now we read the state of the internal 68 connector.  BRDDAT6
+   * is don't care, BRDDAT7 is internal 68.  The cable is
+   * present if the bit is 0
+   */
+  brdctl = read_brdctl(p);
+  *int_68 = !(brdctl & BRDDAT7);
+
+  /*
+   * Set the bank bit in brdctl and then read the external cable state
+   * and the EEPROM status
+   */
+  write_brdctl(p, BRDDAT5);
+  brdctl = read_brdctl(p);
+
+  *ext_68 = !(brdctl & BRDDAT6);
+  *eeprom = !(brdctl & BRDDAT7);
+
+  /*
+   * We're done, the calling function will release the SEEPROM for us
+   */
+}
+
 /*+F*************************************************************************
  * Function:
  *   aic787x_cable_detect
@@ -7887,59 +7892,182 @@
       max_target = 8;
     aic_outb(p, SEEMS | SEECS, SEECTL);
     sxfrctl1 &= ~STPWEN;
-    if ( (p->adapter_control & CFAUTOTERM) ||
-         (p->features & AHC_NEW_AUTOTERM) )
+    /*
+     * The termination/cable detection logic is split into three distinct
+     * groups.  Ultra2 and later controllers, 2940UW-Pro controllers, and
+     * older 7850, 7860, 7870, 7880, and 7895 controllers.  Each has its
+     * own unique way of detecting their cables and writing the results
+     * back to the card.
+     */
+    if (p->features & AHC_ULTRA2)
     {
-      if ( (p->adapter_control & CFAUTOTERM) &&
-          !(p->features & AHC_NEW_AUTOTERM) )
+      /*
+       * As long as user hasn't overridden term settings, always check the
+       * cable detection logic
+       */
+      if (aic7xxx_override_term == -1)
       {
-        printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) Please verify driver detected settings are "
-          "correct.\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) If not, then please properly set the device "
-          "termination\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting CTRL-A "
-          "when prompted\n", p->host_no);
-        printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
+        aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
+                                   &enableLVD_low, &enableLVD_high,
+                                   &eprom_present);
+      }
+      
+      /*
+       * If the user is overriding settings, then they have been preserved
+       * to here as fake adapter_control entries.  Parse them and allow
+       * them to override the detected settings (if we even did detection).
+       */
+      if (!(p->adapter_control & CFSEAUTOTERM))
+      {
+        enableSE_low = (p->adapter_control & CFSTERM);
+        enableSE_high = (p->adapter_control & CFWSTERM);
+      }
+      if (!(p->adapter_control & CFAUTOTERM))
+      {
+        enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
       }
-      /* Configure auto termination. */
 
-      if (p->features & AHC_NEW_AUTOTERM)
+      /*
+       * Now take those settings that we have and translate them into the
+       * values that must be written into the registers.
+       *
+       * Flash Enable = BRDDAT7
+       * Secondary High Term Enable = BRDDAT6
+       * Secondary Low Term Enable = BRDDAT5
+       * LVD/Primary High Term Enable = BRDDAT4
+       * LVD/Primary Low Term Enable = STPWEN bit in SXFRCTL1
+       */
+      if (enableLVD_low != 0)
+      {
+        sxfrctl1 |= STPWEN;
+        p->flags |= AHC_TERM_ENB_LVD;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) LVD/Primary Low byte termination "
+                 "Enabled\n", p->host_no);
+      }
+          
+      if (enableLVD_high != 0)
+      {
+        brddat |= BRDDAT4;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) LVD/Primary High byte termination "
+                 "Enabled\n", p->host_no);
+      }
+
+      if (enableSE_low != 0)
+      {
+        brddat |= BRDDAT5;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) Secondary Low byte termination "
+                 "Enabled\n", p->host_no);
+      }
+
+      if (enableSE_high != 0)
       {
-        if (aic7xxx_override_term == -1)
-          aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
-                                     &enableLVD_low, &enableLVD_high,
-                                     &eprom_present);
-        if (!(p->adapter_control & CFSEAUTOTERM))
+        brddat |= BRDDAT6;
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) Secondary High byte termination "
+                 "Enabled\n", p->host_no);
+      }
+    }
+    else if (p->features & AHC_NEW_AUTOTERM)
+    {
+      /*
+       * The 50 pin connector termination is controlled by STPWEN in the
+       * SXFRCTL1 register.  Since the Adaptec docs typically say the
+       * controller is not allowed to be in the middle of a cable and
+       * this is the only connection on that stub of the bus, there is
+       * no need to even check for narrow termination, it's simply
+       * always on.
+       */
+      sxfrctl1 |= STPWEN;
+      if (aic7xxx_verbose & VERBOSE_PROBE2)
+        printk(KERN_INFO "(scsi%d) Narrow channel termination Enabled\n",
+               p->host_no);
+
+      if (p->adapter_control & CFAUTOTERM)
+      {
+        aic2940_uwpro_wide_cable_detect(p, &internal68_present,
+                                        &external_present,
+                                        &eprom_present);
+        printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+               "Ext-68 %s)\n", p->host_no,
+               "Don't Care",
+               internal68_present ? "YES" : "NO",
+               external_present ? "YES" : "NO");
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
+        if (internal68_present && external_present)
         {
-          enableSE_low = (p->adapter_control & CFSTERM);
-          enableSE_high = (p->adapter_control & CFWSTERM);
+          brddat = 0;
+          p->flags &= ~AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Disabled\n",
+                   p->host_no);
         }
-        if (!(p->adapter_control & CFAUTOTERM))
+        else
         {
-          enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
         }
-        internal50_present = 0;
-        internal68_present = 1;
-        external_present = 1;
-      }
-      else if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
-      {
-        aic787x_cable_detect(p, &internal50_present, &internal68_present,
-          &external_present, &eprom_present);
       }
       else
       {
-        aic785x_cable_detect(p, &internal50_present, &external_present,
-          &eprom_present);
+        /*
+         * The termination of the Wide channel is done more like normal
+         * though, and the setting of this termination is done by writing
+         * either a 0 or 1 to BRDDAT6 of the BRDDAT register
+         */
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat = BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+                   p->host_no);
+        }
+        else
+        {
+          brddat = 0;
+        }
       }
-      
-      if (max_target <= 8)
-        internal68_present = 0;
-
-      if ( !(p->features & AHC_NEW_AUTOTERM) )
+    }
+    else
+    {
+      if (p->adapter_control & CFAUTOTERM)
       {
+        if (p->flags & AHC_MOTHERBOARD)
+        {
+          printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
+                 p->host_no);
+          printk(KERN_INFO "(scsi%d) Please verify driver detected settings "
+            "are correct.\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) If not, then please properly set the "
+            "device termination\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting "
+            "CTRL-A when prompted\n", p->host_no);
+          printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
+        }
+        /* Configure auto termination. */
+
+        if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
+        {
+          aic787x_cable_detect(p, &internal50_present, &internal68_present,
+            &external_present, &eprom_present);
+        }
+        else
+        {
+          aic785x_cable_detect(p, &internal50_present, &external_present,
+            &eprom_present);
+        }
+
+        if (max_target <= 8)
+          internal68_present = 0;
+
         if (max_target > 8)
         {
           printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
@@ -7955,100 +8083,73 @@
                  internal50_present ? "YES" : "NO",
                  external_present ? "YES" : "NO");
         }
-      }
-      if (aic7xxx_verbose & VERBOSE_PROBE2)
-        printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
-             eprom_present ? "is" : "is not");
+        if (aic7xxx_verbose & VERBOSE_PROBE2)
+          printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+               eprom_present ? "is" : "is not");
 
-      /*
-       * Now set the termination based on what we found.  BRDDAT6
-       * controls wide termination enable.
-       * Flash Enable = BRDDAT7
-       * SE High Term Enable = BRDDAT6
-       * SE Low Term Enable = BRDDAT5 (7890)
-       * LVD High Term Enable = BRDDAT4 (7890)
-       */
-      if ( !(p->features & AHC_NEW_AUTOTERM) &&
-           (internal50_present && internal68_present && external_present) )
-      {
-        printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
-               p->host_no);
-        printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
-               "in use at a time!\n", p->host_no);
         /*
-         * Force termination (low and high byte) on.  This is safer than
-         * leaving it completely off, especially since this message comes
-         * most often from motherboard controllers that don't even have 3
-         * connectors, but instead are failing the cable detection.
+         * Now set the termination based on what we found.  BRDDAT6
+         * controls wide termination enable.
+         * Flash Enable = BRDDAT7
+         * SE High Term Enable = BRDDAT6
          */
-        internal50_present = external_present = 0;
-        enableSE_high = enableSE_low = 1;
-      }
-
-      if ((max_target > 8) &&
-          ((external_present == 0) || (internal68_present == 0) ||
-           (enableSE_high != 0)))
-      {
-        brddat |= BRDDAT6;
-        p->flags |= AHC_TERM_ENB_SE_HIGH;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+        if (internal50_present && internal68_present && external_present)
+        {
+          printk(KERN_INFO "(scsi%d) Illegal cable configuration!!  Only two\n",
                  p->host_no);
-      }
+          printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
+                 "in use at a time!\n", p->host_no);
+          /*
+           * Force termination (low and high byte) on.  This is safer than
+           * leaving it completely off, especially since this message comes
+           * most often from motherboard controllers that don't even have 3
+           * connectors, but instead are failing the cable detection.
+           */
+          internal50_present = external_present = 0;
+          enableSE_high = enableSE_low = 1;
+        }
 
-      if ( (((internal50_present ? 1 : 0) +
-             (internal68_present ? 1 : 0) +
-             (external_present   ? 1 : 0)) <= 1) ||
-           (enableSE_low != 0) )
-      {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
-          sxfrctl1 |= STPWEN;
-        p->flags |= AHC_TERM_ENB_SE_LOW;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
-      }
+        if ((max_target > 8) &&
+            ((external_present == 0) || (internal68_present == 0)) )
+        {
+          brddat |= BRDDAT6;
+          p->flags |= AHC_TERM_ENB_SE_HIGH;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
 
-      if (enableLVD_low != 0)
-      {
-        sxfrctl1 |= STPWEN;
-        p->flags |= AHC_TERM_ENB_LVD;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n",
-                 p->host_no);
-      }
-          
-      if (enableLVD_high != 0)
-      {
-        brddat |= BRDDAT4;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n",
-                 p->host_no);
+        if ( ((internal50_present ? 1 : 0) +
+              (internal68_present ? 1 : 0) +
+              (external_present   ? 1 : 0)) <= 1 )
+        {
+          sxfrctl1 |= STPWEN;
+          p->flags |= AHC_TERM_ENB_SE_LOW;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
       }
-    }
-    else
-    {
-      if (p->adapter_control & CFSTERM)
+      else /* p->adapter_control & CFAUTOTERM */
       {
-        if (p->features & AHC_NEW_AUTOTERM)
-          brddat |= BRDDAT5;
-        else
+        if (p->adapter_control & CFSTERM)
+        {
           sxfrctl1 |= STPWEN;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
-                 p->host_no);
-      }
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+                   p->host_no);
+        }
 
-      if (p->adapter_control & CFWSTERM)
-      {
-        brddat |= BRDDAT6;
-        if (aic7xxx_verbose & VERBOSE_PROBE2)
-          printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
-                 p->host_no);
+        if (p->adapter_control & CFWSTERM)
+        {
+          brddat |= BRDDAT6;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+                   p->host_no);
+        }
       }
     }
+
     aic_outb(p, sxfrctl1, SXFRCTL1);
     write_brdctl(p, brddat);
     release_seeprom(p);
@@ -8236,23 +8337,8 @@
   }
   aic_outb(p, 0, SEQ_FLAGS);
 
-  /*
-   * We are starting to do real work on the card....it's possible we could
-   * generate some spurious interrupts at this point, especially in the
-   * event of a PCI error or some such.  If there are other devices already
-   * registered on the same interrupt as us, this could cause the machine
-   * to lock up.  So, we disable the interrupt this card is on until we
-   * finish our card setup.  We only need to do this for modules, if we are
-   * compiled into the kernel then interrupts are already off during this
-   * part of the code.
-   */
-#ifdef MODULE
-  disable_irq(p->irq);
-#endif
-
   detect_maxscb(p);
 
-
   printk("%d/%d SCBs\n", p->scb_data->maxhscbs, p->scb_data->maxscbs);
   if (aic7xxx_verbose & VERBOSE_PROBE2)
   {
@@ -8277,12 +8363,7 @@
     {
       unsigned char devconfig;
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
       pci_read_config_byte(p->pdev, DEVCONFIG, &devconfig);
-#else
-      pcibios_read_config_byte(p->pci_bus, p->pci_device_fn,
-                               DEVCONFIG, &devconfig);
-#endif
       if ( (aic7xxx_stpwlev >> p->instance) & 0x01 )
       {
         devconfig |= STPWLEVEL;
@@ -8295,12 +8376,7 @@
         if (aic7xxx_verbose & VERBOSE_PROBE2)
           printk("(scsi%d) Force clearing STPWLEVEL bit\n", p->host_no);
       }
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
       pci_write_config_byte(p->pdev, DEVCONFIG, devconfig);
-#else
-      pcibios_write_config_byte(p->pci_bus, p->pci_device_fn,
-                                DEVCONFIG, devconfig);
-#endif
     }
   }
 #endif
@@ -8404,7 +8480,7 @@
    * we won't have a power source for the SCSI termination, which means
    * we'll see infinite incoming bus resets.
    */
-  if(p->flags & AHC_NO_STPWR)
+  if(p->flags & AHC_NO_STPWEN)
     aic_outb(p, ENSELTIMO | ENSCSIPERR, SIMODE1);
   else
     aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -8484,9 +8560,6 @@
       printk("(scsi%d) Unable to allocate hardware SCB array; "
              "failing detection.\n", p->host_no);
       aic_outb(p, 0, SIMODE1);
-#ifdef MODULE
-      enable_irq(p->irq);
-#endif
       p->irq = 0;
       return(0);
     }
@@ -8670,9 +8743,6 @@
     printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
            "controller.\n", p->host_no, p->irq);
     aic_outb(p, 0, SIMODE1);
-#ifdef MODULE
-    enable_irq(p->irq);
-#endif
     p->irq = 0;
     return (0);
   }
@@ -8682,10 +8752,6 @@
       p->host_no, -1, -1 , -1);
   aic7xxx_clear_intstat(p);
 
-#ifdef MODULE
-  enable_irq(p->irq);
-#endif
-
   unpause_sequencer(p, /* unpause_always */ TRUE);
 
   return (found);
@@ -8715,10 +8781,10 @@
    * In the future, we may call this function as a last resort for
    * error handling.  Let's be nice and not do any unecessary delays.
    */
-  wait = 1000;  /* 1 second (1000 * 1 msec) */
+  wait = 1000;  /* 1 msec (1000 * 1 msec) */
   while (--wait && !(aic_inb(p, HCNTRL) & CHIPRSTACK))
   {
-    udelay(1);  /* 1 msec */
+    udelay(1);  /* 1 usec */
   }
 
   pause_sequencer(p);
@@ -8794,7 +8860,7 @@
     p->orderedtag = 0;
     for (i=0; i<MAX_TARGETS; i++)
     {
-      p->transinfo[i].goal_period = 0;
+      p->transinfo[i].goal_period = 255;
       p->transinfo[i].goal_offset = 0;
       p->transinfo[i].goal_options = 0;
       p->transinfo[i].goal_width = MSG_EXT_WDTR_BUS_8_BIT;
@@ -9369,11 +9435,7 @@
   /*
    * PCI-bus probe.
    */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
   if (pci_present())
-#else
-  if (pcibios_present())
-#endif
   {
     struct
     {
@@ -9412,7 +9474,7 @@
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
        AHC_AIC7860_FE,                                       7,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AHC_AIC7860,
@@ -9420,7 +9482,8 @@
        AHC_AIC7860_FE,                                       8,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AHC_AIC7870,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,      9,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7870_FE,                                       9,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AHC_AIC7870,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     10,
@@ -9437,7 +9500,8 @@
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE,     13,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7880, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     14,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+       AHC_AIC7880_FE,                                      14,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7881, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     15,
@@ -9460,105 +9524,93 @@
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
-       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 18,
+       AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 19,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
        AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE,     18,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7895_FE,                                      19,
+       AHC_AIC7895_FE,                                      20,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      20,
+       AHC_AIC7890_FE,                                      21,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      21,
+       AHC_AIC7890_FE,                                      22,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7890_FE,                                      22,
+       AHC_AIC7890_FE,                                      23,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      23,
+       AHC_AIC7896_FE,                                      24,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      24,
+       AHC_AIC7896_FE,                                      25,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7896_FE,                                      25,
+       AHC_AIC7896_FE,                                      26,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
-       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_NO_STPWR,
-       AHC_AIC7860_FE,                                      26,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_NO_STPWEN,
+       AHC_AIC7860_FE,                                      27,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
-       AHC_AIC7892_FE,                                      27,
+       AHC_AIC7892_FE,                                      28,
        32, C46 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
       {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
-       AHC_AIC7899_FE,                                      28,
+       AHC_AIC7899_FE,                                      29,
        32, C56_66 },
     };
 
     unsigned short command;
     unsigned int  devconfig, i, oldverbose;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
     struct pci_dev *pdev = NULL;
-#else
-    int index;
-    unsigned int piobase, mmapbase;
-    unsigned char pci_bus, pci_devfn, pci_irq;
-#endif
 
     for (i = 0; i < NUMBER(aic_pdevs); i++)
     {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
       pdev = NULL;
       while ((pdev = pci_find_device(aic_pdevs[i].vendor_id,
                                      aic_pdevs[i].device_id,
-                                     pdev)))
-#else
-      index = 0;
-      while (!(pcibios_find_device(aic_pdevs[i].vendor_id,
-                                   aic_pdevs[i].device_id,
-                                   index++, &pci_bus, &pci_devfn)) )
-#endif
-      {
+                                     pdev))) {
+	if (pci_enable_device(pdev))
+		continue;
         if ( i == 0 ) /* We found one, but it's the 7810 RAID cont. */
         {
           if (aic7xxx_verbose & (VERBOSE_PROBE|VERBOSE_PROBE2))
@@ -9582,19 +9634,19 @@
           /*
            * Read sundry information from PCI BIOS.
            */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
           temp_p->irq = pdev->irq;
           temp_p->pdev = pdev;
           temp_p->pci_bus = pdev->bus->number;
           temp_p->pci_device_fn = pdev->devfn;
-          temp_p->base = pdev->resource[0].start;
-          temp_p->mbase = pdev->resource[1].start;
+          temp_p->base = pci_resource_start(pdev, 0);
+          temp_p->mbase = pci_resource_start(pdev, 1);
           current_p = list_p;
 	  while(current_p && temp_p)
 	  {
 	    if ( ((current_p->pci_bus == temp_p->pci_bus) &&
 	          (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
-                  (current_p->base == temp_p->base) )
+                 (temp_p->base && (current_p->base == temp_p->base)) ||
+                 (temp_p->mbase && (current_p->mbase == temp_p->mbase)) )
 	    {
               /* duplicate PCI entry, skip it */
 	      kfree(temp_p);
@@ -9634,69 +9686,8 @@
           devconfig |= 0x80000040;
           pci_write_config_dword(pdev, DEVCONFIG, devconfig);
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
-#else  /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
-          temp_p->pci_bus = pci_bus;
-          temp_p->pci_device_fn = pci_devfn;
-          pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
-            &pci_irq);
-          temp_p->irq = pci_irq;
-          pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
-            &piobase);
-          temp_p->base = piobase;
-          pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_1,
-            &mmapbase);
-          temp_p->mbase = mmapbase;
-          temp_p->base &= PCI_BASE_ADDRESS_IO_MASK;
-          temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
-          current_p = list_p;
-	  while(current_p)
-	  {
-	    if ( ((current_p->pci_bus == temp_p->pci_bus) &&
-	          (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
-                  (current_p->base == temp_p->base) )
-	    {
-              /* duplicate PCI entry, skip it */
-	      kfree(temp_p);
-	      temp_p = NULL;
-	    }
-	    current_p = current_p->next;
-	  }
-	  if ( temp_p == NULL )
-            continue;
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
-              board_names[aic_pdevs[i].board_name_index],
-              temp_p->pci_bus,
-              PCI_SLOT(temp_p->pci_device_fn),
-              PCI_FUNC(temp_p->pci_device_fn));
-          pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-          {
-            printk("aic7xxx: Initial PCI_COMMAND value was 0x%x\n",
-              (int)command);
-          }
-#ifdef AIC7XXX_STRICT_PCI_SETUP
-          command |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
-            PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
-#else
-          command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
-#endif
-          command &= ~PCI_COMMAND_INVALIDATE;
-          if (aic7xxx_pci_parity == 0)
-            command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
-          pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, command);
-#ifdef AIC7XXX_STRICT_PCI_SETUP
-          pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG, &devconfig);
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-          {
-            printk("aic7xxx: Initial DEVCONFIG value was 0x%x\n", devconfig);
-          }
-          devconfig |= 0x80000040;
-          pcibios_write_config_dword(pci_bus, pci_devfn, DEVCONFIG, devconfig);
-#endif /* AIC7XXX_STRICT_PCI_SETUP */
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
 
-          if(check_region(temp_p->base, MAXREG - MINREG))
+          if(temp_p->base && check_region(temp_p->base, MAXREG - MINREG))
           {
             printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
@@ -9727,7 +9718,7 @@
           }
 
 #ifdef MMAPIO
-          if ( !(temp_p->flags & AHC_MULTI_CHANNEL) ||
+          if ( !(temp_p->base) || !(temp_p->flags & AHC_MULTI_CHANNEL) ||
                ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) &&
                 (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) )
           {
@@ -9735,11 +9726,7 @@
 
             base = temp_p->mbase & PAGE_MASK;
             page_offset = temp_p->mbase - base;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
             temp_p->maddr = ioremap_nocache(base, page_offset + 256);
-#else
-            temp_p->maddr = vremap(base, page_offset + 256);
-#endif
             if(temp_p->maddr)
             {
               temp_p->maddr += page_offset;
@@ -9759,12 +9746,20 @@
                   PCI_FUNC(temp_p->pci_device_fn));
                 printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
                                  "Programmed I/O.\n");
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
                 iounmap((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
-#else
-                vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
-#endif
                 temp_p->maddr = 0;
+                if(temp_p->base == 0)
+                {
+                  printk("aic7xxx: <%s> at PCI %d/%d/%d\n", 
+                    board_names[aic_pdevs[i].board_name_index],
+                    temp_p->pci_bus,
+                    PCI_SLOT(temp_p->pci_device_fn),
+                    PCI_FUNC(temp_p->pci_device_fn));
+                  printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
+                  kfree(temp_p);
+                  temp_p = NULL;
+                  continue;
+                }
               }
             }
           }
@@ -9773,7 +9768,8 @@
           /*
            * Lock out other contenders for our i/o space.
            */
-          request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
+          if(temp_p->base)
+            request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
 
           /*
            * We HAVE to make sure the first pause_sequencer() and all other
@@ -9825,12 +9821,7 @@
            * bit of DEVCONFIG
            */
           aic_outb(temp_p, sxfrctl1, SXFRCTL1);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-          pcibios_write_config_dword(temp_p->pci_bus, temp_p->pci_device_fn,
-            DEVCONFIG, devconfig);
-#else
           pci_write_config_dword(temp_p->pdev, DEVCONFIG, devconfig);
-#endif
           sxfrctl1 &= STPWEN;
 
           /*
@@ -9865,7 +9856,6 @@
             case AHC_AIC7895: /* 7895 */
             case AHC_AIC7896: /* 7896/7 */
             case AHC_AIC7899: /* 7899 */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
               if (PCI_FUNC(pdev->devfn) != 0)
               {
                 temp_p->flags |= AHC_CHNLB;
@@ -9881,25 +9871,6 @@
                 devconfig |= SCBSIZE32;
                 pci_write_config_dword(pdev, DEVCONFIG, devconfig);
               }
-#else
-              if (PCI_FUNC(temp_p->pci_device_fn) != 0)
-              {
-                temp_p->flags |= AHC_CHNLB;
-              }
-              /*
-               * The 7895 is the only chipset that sets the SCBSIZE32 param
-               * in the DEVCONFIG register.  The Ultra2 chipsets use
-               * the DSCOMMAND0 register instead.
-               */
-              if ((temp_p->chip & AHC_CHIPID_MASK) == AHC_AIC7895)
-              {
-                pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG,
-                  &devconfig);
-                devconfig |= SCBSIZE32;
-                pcibios_write_config_dword(pci_bus, pci_devfn, DEVCONFIG,
-                  devconfig);
-              }
-#endif
               break;
             default:
               break;
@@ -9964,12 +9935,7 @@
               /*
                * Check the rev of the chipset before we change DSCOMMAND0
                */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
               pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
-#else
-              pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG,
-                                        &devconfig);
-#endif
               if ((devconfig & 0xff) >= 1)
               {
                 aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
@@ -10039,12 +10005,7 @@
             case AHC_AIC7895:
             case AHC_AIC7896:
             case AHC_AIC7899:
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
               pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
-#else
-              pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG,
-                                        &devconfig);
-#endif
               if (temp_p->features & AHC_ULTRA2)
               {
                 if ( (aic_inb(temp_p, DSCOMMAND0) & RAMPSM_ULTRA2) &&
@@ -10086,12 +10047,7 @@
                          "but not enabled\n");
                 }
               }
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
               pci_write_config_dword(pdev, DEVCONFIG, devconfig);
-#else
-              pcibios_write_config_dword(pci_bus, pci_devfn, DEVCONFIG,
-                                         devconfig);
-#endif
               if ( (temp_p->flags & AHC_EXTERNAL_SRAM) &&
                    (temp_p->flags & AHC_CHNLB) )
                 aic_outb(temp_p, 1, CCSCBBADDR);
@@ -10686,20 +10642,59 @@
               (!(p->features & AHC_ULTRA2) || (syncrate->sxfr_ultra2 == 0)) )
           {
             p->transinfo[tindex].goal_period = syncrate->period;
-            if( !(syncrate->sxfr_ultra2 & 0x40) )
+            if( p->transinfo[tindex].goal_period > 9 )
             {
               p->transinfo[tindex].goal_options = 0;
+              p->needppr &= ~(1<<tindex);
+              p->needsdtr |= (1<<tindex);
+              p->needppr_copy &= ~(1<<tindex);
+              p->needsdtr_copy |= (1<<tindex);
+              if (p->transinfo[tindex].goal_width)
+              {
+                p->needwdtr |= (1<<tindex);
+                p->needwdtr_copy |= (1<<tindex);
+              }
+            }
+          }
+          else if (p->transinfo[tindex].goal_width)
+          {
+            p->transinfo[tindex].goal_width = 0;
+            p->needwdtr &= ~(1<<tindex);
+            p->needwdtr_copy &= ~(1<<tindex);
+            p->transinfo[tindex].goal_offset =
+              p->transinfo[tindex].user_offset;
+            p->transinfo[tindex].goal_period =
+              p->transinfo[tindex].user_period;
+            p->transinfo[tindex].goal_options =
+              p->transinfo[tindex].user_options;
+            if( p->transinfo[tindex].goal_period <= 9 )
+            {
+              p->needppr |= (1<<tindex);
+              p->needsdtr &= ~(1<<tindex);
+              p->needppr_copy |= (1<<tindex);
+              p->needsdtr_copy &= ~(1<<tindex);
+            }
+            else
+            {
+              p->needppr &= ~(1<<tindex);
+              p->needsdtr |= (1<<tindex);
+              p->needppr_copy &= ~(1<<tindex);
+              p->needsdtr_copy |= (1<<tindex);
             }
           }
           else
           {
             p->transinfo[tindex].goal_offset = 0;
-            p->transinfo[tindex].goal_period = 0;
+            p->transinfo[tindex].goal_period = 255;
             p->transinfo[tindex].goal_options = 0;
+            p->transinfo[tindex].goal_width = 0;
+            p->needppr &= ~(1<<tindex);
+            p->needsdtr &= ~(1<<tindex);
+            p->needwdtr &= ~(1<<tindex);
+            p->needppr_copy &= ~(1<<tindex);
+            p->needsdtr_copy &= ~(1<<tindex);
+            p->needwdtr_copy &= ~(1<<tindex);
           }
-          p->needppr |= (p->needppr_copy & (1<<tindex));
-          p->needsdtr |= (p->needsdtr_copy & (1<<tindex));
-          p->needwdtr |= (p->needwdtr_copy & (1<<tindex));
         }
         p->needdv &= ~(1<<tindex);
       }
@@ -10750,8 +10745,16 @@
    * and we didn't follow up with SDTR yet, then this will get it started.
    * For all other cases, this should work out to be a no-op, unless we are
    * doing domain validation and happen to need a new negotiation command.
+   *
+   * In case we don't want this to go any further, the cmdcmplt interrupt
+   * handler will NULL out the cmd->next entry so that the real SCSI command
+   * can be sent back to the mid layer code with SENSE data intact.  We'll
+   * finish things up when the cmd gets sent back down to us, so no worries.
    */
-  aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
+  if(cmd->next)
+  {
+    aic7xxx_build_negotiation_cmnd(p, cmd->next, tindex);
+  }
   return;
 }
 
@@ -10873,13 +10876,13 @@
    */
   hscb->control = 0;
   scb->tag_action = 0;
+  cmd->tag = hscb->tag;
   if (p->discenable & mask)
   {
     hscb->control |= DISCENB;
     if ( (p->tagenable & mask) &&
          (cmd->cmnd[0] != TEST_UNIT_READY) )
     {
-      cmd->tag = hscb->tag;
       p->dev_commands_sent[tindex]++;
       if (p->dev_commands_sent[tindex] < 200)
       {
@@ -11321,13 +11324,6 @@
 void
 aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-  int i, mask, found, need_tag;
-  struct aic7xxx_scb *scb;
-  unsigned char qinpos, hscbp;
-
-  found = FALSE;
-#endif
 
   printk("aic7xxx driver version %s/%s\n", AIC7XXX_C_VERSION,
          UTS_RELEASE);
@@ -11340,121 +11336,7 @@
   disable_irq(p->irq);
   aic7xxx_print_card(p);
   aic7xxx_print_scratch_ram(p);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-  for(i=0; i<MAX_TARGETS; i++)
-  {
-    if(p->dev_flags[i] & DEVICE_PRESENT)
-    {
-      mask = (0x01 << i);
-      printk(INFO_LEAD "dev_flags=0x%x, Pending:%c, PPR:%c/%c, WDTR:%c/%c, "
-             "SDTR:%c/%c, q_depth=%d:%d\n",
-        p->host_no, 0, i, 0, p->dev_flags[i],
-        (p->dtr_pending & mask) ? 'Y' : 'N',
-        (p->needppr & mask) ? 'Y' : 'N',
-        (p->needppr_copy & mask) ? 'Y' : 'N',
-        (p->needwdtr & mask) ? 'Y' : 'N',
-        (p->needwdtr_copy & mask) ? 'Y' : 'N',
-        (p->needsdtr & mask) ? 'Y' : 'N',
-        (p->needsdtr_copy & mask) ? 'Y' : 'N',
-        p->dev_active_cmds[i],
-        p->dev_max_queue_depth[i] );
-      printk(INFO_LEAD "targ_scsirate=0x%x", p->host_no, 0, i, 0,
-             aic_inb(p, TARG_SCSIRATE + i));
-      if (p->features & AHC_ULTRA2)
-        printk(", targ_offset=%d", aic_inb(p, TARG_OFFSET + i));
-      printk("\n");
-    }
-  }
-  /*
-   * Search for this command and see if we can't track it down, it's the
-   * one causing the timeout.  Print out this command first, then all other
-   * active commands afterwords.
-   */
-  need_tag = -1;
-  if ( cmd )
-  {
-    scb = p->scb_data->scb_array[aic7xxx_position(cmd)];
-    if ( (scb->flags & SCB_ACTIVE) && (scb->cmd == cmd) )
-    {
-      printk("Timed out command is scb #%d:\n", scb->hscb->tag);
-      printk("Tag%d: flags=0x%x, control=0x%x, TCL=0x%x, %s\n", scb->hscb->tag,
-             scb->flags, scb->hscb->control, scb->hscb->target_channel_lun,
-             (scb->flags & SCB_WAITINGQ) ? "WAITINGQ" : "Sent" );
-      need_tag = scb->hscb->tag;
-      if (scb->flags & SCB_WAITINGQ) found=TRUE;
-    }
-  }
-  printk("QINFIFO: (TAG) ");
-  qinpos = aic_inb(p, QINPOS);
-  while ( qinpos != p->qinfifonext )
-  {
-    if (p->qinfifo[qinpos] == need_tag)
-      found=TRUE;
-    printk("%d ", p->qinfifo[qinpos++]);
-  }  
-  printk("\n");
-  printk("Current SCB: (SCBPTR/TAG/CONTROL) %d/%d/0x%x\n", aic_inb(p, SCBPTR),
-         aic_inb(p, SCB_TAG), aic_inb(p, SCB_CONTROL) );
-  if (aic_inb(p, SCB_TAG) == need_tag)  found=TRUE;
-  printk("WAITING_SCBS: (SCBPTR/TAG/CONTROL) %d->",
-         hscbp = aic_inb(p, WAITING_SCBH));
-  while (hscbp != SCB_LIST_NULL)
-  {
-    aic_outb(p, hscbp, SCBPTR);
-    printk("%d/%d/0x%x ", hscbp, aic_inb(p, SCB_TAG), aic_inb(p, SCB_CONTROL));
-    hscbp = aic_inb(p, SCB_NEXT);
-    if (aic_inb(p, SCB_TAG) == need_tag)  found=TRUE;
-  }
-  printk("\n");
-  printk("DISCONNECTED_SCBS: (SCBPTR/TAG/CONTROL) %d->",
-         hscbp = aic_inb(p, DISCONNECTED_SCBH));
-  while (hscbp != SCB_LIST_NULL)
-  {
-    aic_outb(p, hscbp, SCBPTR);
-    printk("%d/%d/0x%x ", hscbp, aic_inb(p, SCB_TAG), aic_inb(p, SCB_CONTROL));
-    hscbp = aic_inb(p, SCB_NEXT);
-    if (aic_inb(p, SCB_TAG) == need_tag)  found=TRUE;
-  }
-  printk("\n");
-  printk("FREE_SCBS: (SCBPTR/TAG/CONTROL) %d->",
-         hscbp = aic_inb(p, FREE_SCBH));
-  while (hscbp != SCB_LIST_NULL)
-  {
-    aic_outb(p, hscbp, SCBPTR);
-    printk("%d/%d/0x%x ", hscbp, aic_inb(p, SCB_TAG), aic_inb(p, SCB_CONTROL));
-    hscbp = aic_inb(p, SCB_NEXT);
-  }
-  printk("\n");
-
-  if (found == FALSE)
-  {
-    /*
-     * We haven't found the offending SCB yet, and it should be around
-     * somewhere, so go look for it in the cards SCBs.
-     */
-    printk("SCBPTR CONTROL TAG NEXT\n");
-    for(i=0; i<p->scb_data->maxhscbs; i++)
-    {
-      aic_outb(p, i, SCBPTR);
-      printk("   %3d      %02x  %02x   %02x\n", i,
-             aic_inb(p, SCB_CONTROL), aic_inb(p, SCB_TAG),
-             aic_inb(p, SCB_NEXT));
-    }
-  }
-  
-
-  for (i=0; i < p->scb_data->numscbs; i++)
-  {
-    scb = p->scb_data->scb_array[i];
-    if ( (scb->flags & SCB_ACTIVE) && (scb->cmd != cmd) )
-    {
-      printk("Tag%d: flags=0x%x, control=0x%x, TCL=0x%x, %s\n", scb->hscb->tag,
-             scb->flags, scb->hscb->control, scb->hscb->target_channel_lun,
-             (scb->flags & SCB_WAITINGQ) ? "WAITINGQ" : "Sent" );
-    }
-  }
-#endif
-  sti();
+  spin_unlock_irq(&io_request_lock);
   for(;;) barrier();
 }
 
@@ -11500,7 +11382,6 @@
  *  we are following a straight code path without entering the scheduler
  *  code.
  */
-
   pause_sequencer(p);
   while ( (aic_inb(p, INTSTAT) & INT_PEND) && !(p->flags & AHC_IN_ISR))
   {
@@ -12163,15 +12044,12 @@
 
   if(p->irq)
     free_irq(p->irq, p);
-  release_region(p->base, MAXREG - MINREG);
+  if(p->base)
+    release_region(p->base, MAXREG - MINREG);
 #ifdef MMAPIO
   if(p->maddr)
   {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-    vfree((void *) (((unsigned long) p->maddr) & PAGE_MASK));
-#else
     iounmap((void *) (((unsigned long) p->maddr) & PAGE_MASK));
-#endif
   }
 #endif /* MMAPIO */
   prev = NULL;
@@ -12242,31 +12120,7 @@
           0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
           0xe0, 0xf1, 0xf4, 0xfc} },
   };
-#ifdef CONFIG_PCI
-  static struct register_ranges cards_ns[] = {
-    { 0, {0,} }, /* none */
-    { 0, {0,} }, /* 7771 */
-    { 7, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x28, 0x2b, 0x30, 0x33,
-          0x3c, 0x41, 0x43, 0x47} },
-    { 7, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x28, 0x2b, 0x30, 0x33,
-          0x3c, 0x41, 0x43, 0x47} },
-    { 5, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x30, 0x33, 0x3c, 0x41} },
-    { 5, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x30, 0x34, 0x3c, 0x47} },
-    { 5, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3} },
-    { 6, {0x04, 0x08, 0x0c, 0x0e, 0x10, 0x17, 0x30, 0x34, 0x3c, 0x47,
-          0xdc, 0xe3} },
-    { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
-          0xff, 0xff} },
-    { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
-          0xff, 0xff} },
-    { 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
-          0xff, 0xff} }
-  };
-#endif
   chip = p->chip & AHC_CHIPID_MASK;
-  /*
-   * Let's run through the PCI space first....
-   */
   printk("%s at ",
          board_names[p->board_name_index]);
   switch(p->chip & ~AHC_CHIPID_MASK)
@@ -12284,38 +12138,8 @@
       break;
   }
 
-#ifdef CONFIG_PCI
-  {
-    unsigned char temp;
-    
-    printk("PCI Dump:\n");
-    k=0;
-    for(i=0; i<cards_ns[chip].num_ranges; i++)
-    {
-      for(j  = cards_ns[chip].range_val[ i * 2 ];
-          j <= cards_ns[chip].range_val[ i * 2 + 1 ] ;
-          j++)
-      {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
-        pci_read_config_byte(p->pdev, j, &temp);
-#else
-        pcibios_read_config_byte(p->pci_bus, p->pci_device_fn, j, &temp);
-#endif
-        printk("%02x:%02x ", j, temp);
-        if(++k == 13)
-        {
-          printk("\n");
-          k = 0;
-        }
-      }
-    }
-  }
-  if(k != 0)
-    printk("\n");
-#endif /* CONFIG_PCI */
-
   /*
-   * Now the registers on the card....
+   * the registers on the card....
    */
   printk("Card Dump:\n");
   k = 0;
@@ -12335,21 +12159,6 @@
   }
   if(k != 0)
     printk("\n");
-  if (p->flags & AHC_SEEPROM_FOUND)
-  {
-    unsigned short *sc1;
-    sc1 = (unsigned short *)&p->sc;
-    
-    printk("SEEPROM dump.\n");
-    for(i=1; i<=32; i++)
-    {
-      printk("0x%04x", sc1[i-1]);
-      if ( (i % 8) == 0 )
-        printk("\n");
-      else
-        printk("  ");
-    }
-  }
 
   /*
    * If this was an Ultra2 controller, then we just hosed the card in terms

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)