]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.34pre9 2.0.34pre9
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:43 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:43 +0000 (15:11 -0500)
16 files changed:
drivers/net/Space.c
drivers/net/eepro100.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/README.BusLogic
drivers/scsi/README.Mylex
drivers/scsi/aic7xxx.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
include/linux/modversions.h [deleted file]
net/ipv4/ip_fragment.c
net/ipv4/proc.c
net/ipv4/tcp_input.c
scripts/Configure

index 6eb6eb8040200cadc98e199a417aa2c33fd7c4f6..d2723a2746525f01c53b0c7573deb401277d2d64 100644 (file)
@@ -82,7 +82,7 @@ extern int ariadne_probe(struct device *);
 extern int hydra_probe(struct device *);
 extern int yellowfin_probe(struct device *);
 extern int eepro100_probe(struct device *);
-extern int epic_probe(struct device *);
+extern int epic100_probe(struct device *);
 extern int rtl8139_probe(struct device *);
 extern int tlan_probe(struct device *);
 extern int isa515_probe(struct device *);
@@ -112,8 +112,8 @@ ethif_probe(struct device *dev)
 #ifdef CONFIG_EEXPRESS_PRO100B /* Intel EtherExpress Pro100B */
        && eepro100_probe(dev)
 #endif
-#ifdef CONFIG_SMC_EPIC
-       && epic_probe(dev)
+#ifdef CONFIG_EPIC
+       && epic100_probe(dev)
 #endif
 #if defined(CONFIG_HP100)
        && hp100_probe(dev)
index 5c0a6a2aa35fae184921f9723b4d45686665cca9..f708b6b1c8a36e3458d330a84ba3e90af38b547a 100644 (file)
@@ -943,7 +943,7 @@ speedo_start_xmit(struct sk_buff *skb, struct device *dev)
                        return 1;
                }
                speedo_tx_timeout(dev);
-               return 0;
+               return 1;
        }
 
        /* Caution: the write order is important here, set the base address
index a658b1174f7d8aa5185d9294ed65f532fed6cba4..89b129f9d6cc09b1ddff57b3be424e47f701f272 100644 (file)
@@ -2,7 +2,7 @@
 
   Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
 
-  Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
@@ -26,8 +26,8 @@
 */
 
 
-#define BusLogic_DriverVersion         "2.0.12"
-#define BusLogic_DriverDate            "29 March 1998"
+#define BusLogic_DriverVersion         "2.0.13"
+#define BusLogic_DriverDate            "17 April 1998"
 
 
 #include <linux/version.h>
@@ -111,15 +111,6 @@ static BusLogic_HostAdapter_T
   *BusLogic_LastRegisteredHostAdapter =                NULL;
 
 
-/*
-  BusLogic_RegisteredHostAdapters is an array of linked lists of all the
-  registered BusLogic Host Adapters, indexed by IRQ Channel.
-*/
-
-static BusLogic_HostAdapter_T
-  *BusLogic_RegisteredHostAdapters[NR_IRQS] =  { NULL };
-
-
 /*
   BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
 */
@@ -149,16 +140,6 @@ static char
   *BusLogic_CommandFailureReason;
 
 
-/*
-  BusLogic_FirstCompletedCCB and BusLogic_LastCompletedCCB are pointers
-  to the first and last CCBs that are queued for completion processing.
-*/
-
-static BusLogic_CCB_T
-  *BusLogic_FirstCompletedCCB =                        NULL,
-  *BusLogic_LastCompletedCCB =                 NULL;
-
-
 /*
   BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
 */
@@ -178,7 +159,7 @@ static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter)
   BusLogic_Announce("***** BusLogic SCSI Driver Version "
                    BusLogic_DriverVersion " of "
                    BusLogic_DriverDate " *****\n", HostAdapter);
-  BusLogic_Announce("Copyright 1995 by Leonard N. Zubkoff "
+  BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
                    "<lnz@dandelion.com>\n", HostAdapter);
 }
 
@@ -203,7 +184,7 @@ const char *BusLogic_DriverInfo(SCSI_Host_T *Host)
 
 static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
 {
-  HostAdapter->NextAll = NULL;
+  HostAdapter->Next = NULL;
   if (BusLogic_FirstRegisteredHostAdapter == NULL)
     {
       BusLogic_FirstRegisteredHostAdapter = HostAdapter;
@@ -211,20 +192,9 @@ static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     }
   else
     {
-      BusLogic_LastRegisteredHostAdapter->NextAll = HostAdapter;
+      BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
       BusLogic_LastRegisteredHostAdapter = HostAdapter;
     }
-  HostAdapter->Next = NULL;
-  if (BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] != NULL)
-    {
-      BusLogic_HostAdapter_T *LastHostAdapter =
-       BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel];
-      BusLogic_HostAdapter_T *NextHostAdapter;
-      while ((NextHostAdapter = LastHostAdapter->Next) != NULL)
-       LastHostAdapter = NextHostAdapter;
-      LastHostAdapter->Next = HostAdapter;
-    }
-  else BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] = HostAdapter;
 }
 
 
@@ -238,7 +208,7 @@ static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
   if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
     {
       BusLogic_FirstRegisteredHostAdapter =
-       BusLogic_FirstRegisteredHostAdapter->NextAll;
+       BusLogic_FirstRegisteredHostAdapter->Next;
       if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
        BusLogic_LastRegisteredHostAdapter = NULL;
     }
@@ -246,25 +216,12 @@ static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     {
       BusLogic_HostAdapter_T *PreviousHostAdapter =
        BusLogic_FirstRegisteredHostAdapter;
-      while (PreviousHostAdapter != NULL &&
-            PreviousHostAdapter->NextAll != HostAdapter)
-       PreviousHostAdapter = PreviousHostAdapter->NextAll;
-      if (PreviousHostAdapter != NULL)
-       PreviousHostAdapter->NextAll = HostAdapter->NextAll;
-    }
-  HostAdapter->NextAll = NULL;
-  if (BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] != HostAdapter)
-    {
-      BusLogic_HostAdapter_T *PreviousHostAdapter =
-       BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel];
       while (PreviousHostAdapter != NULL &&
             PreviousHostAdapter->Next != HostAdapter)
        PreviousHostAdapter = PreviousHostAdapter->Next;
       if (PreviousHostAdapter != NULL)
        PreviousHostAdapter->Next = HostAdapter->Next;
     }
-  else BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel] =
-        HostAdapter->Next;
   HostAdapter->Next = NULL;
 }
 
@@ -466,7 +423,7 @@ static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
   unsigned char *ReplyPointer = (unsigned char *) ReplyData;
   BusLogic_StatusRegister_T StatusRegister;
   BusLogic_InterruptRegister_T InterruptRegister;
-  unsigned long ProcessorFlags = 0;
+  ProcessorFlags_T ProcessorFlags = 0;
   int ReplyBytes = 0, Result;
   long TimeoutCounter;
   /*
@@ -875,6 +832,7 @@ static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T
          Address should not be probed.
        */
        HostAdapter->IO_Address = IO_Address;
+       BusLogic_InterruptReset(HostAdapter);
        if (BusLogic_Command(HostAdapter,
                             BusLogic_InquirePCIHostAdapterInformation,
                             NULL, 0, &PCIHostAdapterInformation,
@@ -1479,12 +1437,11 @@ static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T
 
 /*
   BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
-  Host Adapter.  It also determines the IRQ Channel for non-PCI Host Adapters.
+  Host Adapter.
 */
 
 static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
 {
-  BusLogic_Configuration_T Configuration;
   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
   BusLogic_RequestedReplyLength_T RequestedReplyLength;
   boolean Result = true;
@@ -1492,31 +1449,6 @@ static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     FlashPoint Host Adapters do not require this protection.
   */
   if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
-  /*
-    Issue the Inquire Configuration command if the IRQ Channel is unknown.
-  */
-  if (HostAdapter->IRQ_Channel == 0)
-    {
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration,
-                          NULL, 0, &Configuration, sizeof(Configuration))
-         == sizeof(Configuration))
-       {
-         if (Configuration.IRQ_Channel9)
-           HostAdapter->IRQ_Channel = 9;
-         else if (Configuration.IRQ_Channel10)
-           HostAdapter->IRQ_Channel = 10;
-         else if (Configuration.IRQ_Channel11)
-           HostAdapter->IRQ_Channel = 11;
-         else if (Configuration.IRQ_Channel12)
-           HostAdapter->IRQ_Channel = 12;
-         else if (Configuration.IRQ_Channel14)
-           HostAdapter->IRQ_Channel = 14;
-         else if (Configuration.IRQ_Channel15)
-           HostAdapter->IRQ_Channel = 15;
-         else Result = false;
-       }
-      else Result = false;
-    }
   /*
     Issue the Inquire Extended Setup Information command.  Only genuine
     BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
@@ -1743,11 +1675,27 @@ static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
   */
   HostAdapter->SCSI_ID = Configuration.HostAdapterID;
   /*
-    Determine the Bus Type and save it in the Host Adapter structure,
-    and determine and save the DMA Channel for ISA Host Adapters.
+    Determine the Bus Type and save it in the Host Adapter structure, determine
+    and save the IRQ Channel if necessary, and determine and save the DMA
+    Channel for ISA Host Adapters.
   */
   HostAdapter->HostAdapterBusType =
     BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
+  if (HostAdapter->IRQ_Channel == 0)
+    {
+      if (Configuration.IRQ_Channel9)
+       HostAdapter->IRQ_Channel = 9;
+      else if (Configuration.IRQ_Channel10)
+       HostAdapter->IRQ_Channel = 10;
+      else if (Configuration.IRQ_Channel11)
+       HostAdapter->IRQ_Channel = 11;
+      else if (Configuration.IRQ_Channel12)
+       HostAdapter->IRQ_Channel = 12;
+      else if (Configuration.IRQ_Channel14)
+       HostAdapter->IRQ_Channel = 14;
+      else if (Configuration.IRQ_Channel15)
+       HostAdapter->IRQ_Channel = 15;
+    }
   if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
     {
       if (Configuration.DMA_Channel5)
@@ -1890,7 +1838,7 @@ static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
   HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
   HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
   /*
-    Select appropriate values for the Mailbox Count, Driver Queue Depth, 
+    Select appropriate values for the Mailbox Count, Driver Queue Depth,
     Initial CCBs, and Incremental CCBs variables based on whether or not Strict
     Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
     then there is no performance degradation in using the maximum possible
@@ -1982,12 +1930,10 @@ static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
   */
 Common:
   /*
-    Initialize the Host Adapter Full Model Name and Interrupt Label fields
-    from the Model Name.
+    Initialize the Host Adapter Full Model Name from the Model Name.
   */
   strcpy(HostAdapter->FullModelName, "BusLogic ");
   strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
-  strcpy(HostAdapter->InterruptLabel, HostAdapter->FullModelName);
   /*
     Select an appropriate value for the Tagged Queue Depth either from a
     BusLogic Driver Options specification, or based on whether this Host
@@ -2305,8 +2251,6 @@ static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T
 
 static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
 {
-  BusLogic_HostAdapter_T *FirstHostAdapter =
-    BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel];
   if (HostAdapter->IRQ_Channel == 0)
     {
       BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
@@ -2314,24 +2258,15 @@ static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
       return false;
     }
   /*
-    Acquire exclusive or shared access to the IRQ Channel if necessary.
+    Acquire shared access to the IRQ Channel.
   */
-  if (FirstHostAdapter->Next == NULL)
+  if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
+                 SA_INTERRUPT | SA_SHIRQ,
+                 HostAdapter->FullModelName, HostAdapter) < 0)
     {
-      if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
-                     SA_INTERRUPT | SA_SHIRQ,
-                     HostAdapter->InterruptLabel, NULL) < 0)
-       {
-         BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
-                        HostAdapter, HostAdapter->IRQ_Channel);
-         return false;
-       }
-    }
-  else if (strlen(FirstHostAdapter->InterruptLabel) + 11
-          < sizeof(FirstHostAdapter->InterruptLabel))
-    {
-      strcat(FirstHostAdapter->InterruptLabel, " + ");
-      strcat(FirstHostAdapter->InterruptLabel, HostAdapter->ModelName);
+      BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
+                    HostAdapter, HostAdapter->IRQ_Channel);
+      return false;
     }
   HostAdapter->IRQ_ChannelAcquired = true;
   /*
@@ -2364,14 +2299,11 @@ static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
 
 static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter)
 {
-  BusLogic_HostAdapter_T *FirstHostAdapter =
-    BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel];
   /*
-    Release exclusive or shared access to the IRQ Channel.
+    Release shared access to the IRQ Channel.
   */
   if (HostAdapter->IRQ_ChannelAcquired)
-    if (FirstHostAdapter->Next == NULL)
-      free_irq(HostAdapter->IRQ_Channel, NULL);
+    free_irq(HostAdapter->IRQ_Channel, HostAdapter);
   /*
     Release exclusive access to the DMA Channel.
   */
@@ -2393,6 +2325,12 @@ static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T
   BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest;
   BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest;
   int TargetID;
+  /*
+    Initialize the pointers to the first and last CCBs that are queued for
+    completion processing.
+  */
+  HostAdapter->FirstCompletedCCB = NULL;
+  HostAdapter->LastCompletedCCB = NULL;
   /*
     Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
     Command Successful Flag, Active Commands, and Commands Since Reset
@@ -2773,7 +2711,7 @@ static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host,
   if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
     for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
         HostAdapter != NULL;
-        HostAdapter = HostAdapter->NextAll)
+        HostAdapter = HostAdapter->Next)
       BusLogic_ReportTargetDeviceInfo(HostAdapter);
 }
 
@@ -2875,9 +2813,7 @@ int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
       Host->select_queue_depths = BusLogic_SelectQueueDepths;
       /*
        Add Host Adapter to the end of the list of registered BusLogic
-       Host Adapters.  In order for Command Complete Interrupts to be
-       properly dismissed by BusLogic_InterruptHandler, the Host Adapter
-       must be registered.
+       Host Adapters.
       */
       BusLogic_RegisterHostAdapter(HostAdapter);
       /*
@@ -2970,19 +2906,20 @@ int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
 
 static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB)
 {
+  BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
   CCB->Status = BusLogic_CCB_Completed;
   CCB->Next = NULL;
-  if (BusLogic_FirstCompletedCCB == NULL)
+  if (HostAdapter->FirstCompletedCCB == NULL)
     {
-      BusLogic_FirstCompletedCCB = CCB;
-      BusLogic_LastCompletedCCB = CCB;
+      HostAdapter->FirstCompletedCCB = CCB;
+      HostAdapter->LastCompletedCCB = CCB;
     }
   else
     {
-      BusLogic_LastCompletedCCB->Next = CCB;
-      BusLogic_LastCompletedCCB = CCB;
+      HostAdapter->LastCompletedCCB->Next = CCB;
+      HostAdapter->LastCompletedCCB = CCB;
     }
-  CCB->HostAdapter->ActiveCommands[CCB->TargetID]--;
+  HostAdapter->ActiveCommands[CCB->TargetID]--;
 }
 
 
@@ -3105,25 +3042,23 @@ static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter)
 
 
 /*
-  BusLogic_ProcessCompletedCCBs iterates over the completed CCBs setting
-  the SCSI Command Result Codes, deallocating the CCBs, and calling the
-  SCSI Subsystem Completion Routines.  Interrupts should already have been
-  disabled by the caller.
+  BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
+  Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
+  calling the SCSI Subsystem Completion Routines.  The Host Adapter's Lock
+  should already have been acquired by the caller.
 */
 
-static void BusLogic_ProcessCompletedCCBs(void)
+static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
 {
-  static boolean ProcessCompletedCCBsActive = false;
-  if (ProcessCompletedCCBsActive) return;
-  ProcessCompletedCCBsActive = true;
-  while (BusLogic_FirstCompletedCCB != NULL)
+  if (HostAdapter->ProcessCompletedCCBsActive) return;
+  HostAdapter->ProcessCompletedCCBsActive = true;
+  while (HostAdapter->FirstCompletedCCB != NULL)
     {
-      BusLogic_CCB_T *CCB = BusLogic_FirstCompletedCCB;
+      BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
       SCSI_Command_T *Command = CCB->Command;
-      BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
-      BusLogic_FirstCompletedCCB = CCB->Next;
-      if (BusLogic_FirstCompletedCCB == NULL)
-       BusLogic_LastCompletedCCB = NULL;
+      HostAdapter->FirstCompletedCCB = CCB->Next;
+      if (HostAdapter->FirstCompletedCCB == NULL)
+       HostAdapter->LastCompletedCCB = NULL;
       /*
        Process the Completed CCB.
       */
@@ -3259,7 +3194,7 @@ static void BusLogic_ProcessCompletedCCBs(void)
          Command->scsi_done(Command);
        }
     }
-  ProcessCompletedCCBsActive = false;
+  HostAdapter->ProcessCompletedCCBsActive = false;
 }
 
 
@@ -3272,107 +3207,84 @@ static void BusLogic_InterruptHandler(int IRQ_Channel,
                                      void *DeviceIdentifier,
                                      Registers_T *InterruptRegisters)
 {
-  BusLogic_HostAdapter_T *FirstHostAdapter =
-    BusLogic_RegisteredHostAdapters[IRQ_Channel];
-  boolean HostAdapterResetRequired = false;
-  BusLogic_HostAdapter_T *HostAdapter;
-  BusLogic_Lock_T Lock;
+  BusLogic_HostAdapter_T *HostAdapter =
+    (BusLogic_HostAdapter_T *) DeviceIdentifier;
+  ProcessorFlags_T ProcessorFlags;
   /*
-    Iterate over the installed BusLogic Host Adapters accepting any Incoming
-    Mailbox entries and saving the completed CCBs for processing.  This
-    interrupt handler is installed as a fast interrupt, so interrupts are
-    disabled when the interrupt handler is entered.
+    Acquire exclusive access to Host Adapter.
   */
-  for (HostAdapter = FirstHostAdapter;
-       HostAdapter != NULL;
-       HostAdapter = HostAdapter->Next)
+  BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+  /*
+    Handle Interrupts appropriately for each Host Adapter type.
+  */
+  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
     {
+      BusLogic_InterruptRegister_T InterruptRegister;
       /*
-       Acquire exclusive access to Host Adapter.
-      */
-      BusLogic_AcquireHostAdapterLockID(HostAdapter, &Lock);
-      /*
-       Handle Interrupts appropriately for each Host Adapter type.
+       Read the Host Adapter Interrupt Register.
       */
-      if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
+      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+      if (InterruptRegister.Bits.InterruptValid)
        {
-         BusLogic_InterruptRegister_T InterruptRegister;
          /*
-           Read the Host Adapter Interrupt Register.
+           Acknowledge the interrupt and reset the Host Adapter
+           Interrupt Register.
          */
-         InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-         if (InterruptRegister.Bits.InterruptValid)
-           {
-             /*
-               Acknowledge the interrupt and reset the Host Adapter
-               Interrupt Register.
-             */
-             BusLogic_InterruptReset(HostAdapter);
-             /*
-               Process valid External SCSI Bus Reset and Incoming Mailbox
-               Loaded Interrupts.  Command Complete Interrupts are noted,
-               and Outgoing Mailbox Available Interrupts are ignored, as
-               they are never enabled.
-             */
-             if (InterruptRegister.Bits.ExternalBusReset)
-               {
-                 HostAdapter->HostAdapterExternalReset = true;
-                 HostAdapterResetRequired = true;
-               }
-             else if (InterruptRegister.Bits.IncomingMailboxLoaded)
-               BusLogic_ScanIncomingMailboxes(HostAdapter);
-             else if (InterruptRegister.Bits.CommandComplete)
-               HostAdapter->HostAdapterCommandCompleted = true;
-           }
-       }
-      else
-       {
+         BusLogic_InterruptReset(HostAdapter);
          /*
-           Check if there is a pending interrupt for this Host Adapter.
+           Process valid External SCSI Bus Reset and Incoming Mailbox
+           Loaded Interrupts.  Command Complete Interrupts are noted,
+           and Outgoing Mailbox Available Interrupts are ignored, as
+           they are never enabled.
          */
-         if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
-           switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
-             {
-             case FlashPoint_NormalInterrupt:
-               break;
-             case FlashPoint_ExternalBusReset:
-               HostAdapter->HostAdapterExternalReset = true;
-               HostAdapterResetRequired = true;
-               break;
-             case FlashPoint_InternalError:
-               BusLogic_Warning("Internal FlashPoint Error detected"
-                                " - Resetting Host Adapter\n", HostAdapter);
-               HostAdapter->HostAdapterInternalError = true;
-               HostAdapterResetRequired = true;
-               break;
-             }
+         if (InterruptRegister.Bits.ExternalBusReset)
+           HostAdapter->HostAdapterExternalReset = true;
+         else if (InterruptRegister.Bits.IncomingMailboxLoaded)
+           BusLogic_ScanIncomingMailboxes(HostAdapter);
+         else if (InterruptRegister.Bits.CommandComplete)
+           HostAdapter->HostAdapterCommandCompleted = true;
        }
+    }
+  else
+    {
       /*
-       Release exclusive access to Host Adapter.
+       Check if there is a pending interrupt for this Host Adapter.
       */
-      BusLogic_ReleaseHostAdapterLockID(HostAdapter, &Lock);
+      if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
+       switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
+         {
+         case FlashPoint_NormalInterrupt:
+           break;
+         case FlashPoint_ExternalBusReset:
+           HostAdapter->HostAdapterExternalReset = true;
+           break;
+         case FlashPoint_InternalError:
+           BusLogic_Warning("Internal FlashPoint Error detected"
+                            " - Resetting Host Adapter\n", HostAdapter);
+           HostAdapter->HostAdapterInternalError = true;
+           break;
+         }
     }
   /*
     Process any completed CCBs.
   */
-  if (BusLogic_FirstCompletedCCB != NULL)
-    BusLogic_ProcessCompletedCCBs();
+  if (HostAdapter->FirstCompletedCCB != NULL)
+    BusLogic_ProcessCompletedCCBs(HostAdapter);
   /*
-    Iterate over the Host Adapters performing any requested
-    Host Adapter Resets.
+    Reset the Host Adapter if requested.
   */
-  if (HostAdapterResetRequired)
-    for (HostAdapter = FirstHostAdapter;
-        HostAdapter != NULL;
-        HostAdapter = HostAdapter->Next)
-      if (HostAdapter->HostAdapterExternalReset ||
-         HostAdapter->HostAdapterInternalError)
-       {
-         BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
-         HostAdapter->HostAdapterExternalReset = false;
-         HostAdapter->HostAdapterInternalError = false;
-         scsi_mark_host_reset(HostAdapter->SCSI_Host);
-       }
+  if (HostAdapter->HostAdapterExternalReset ||
+      HostAdapter->HostAdapterInternalError)
+    {
+      BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
+      HostAdapter->HostAdapterExternalReset = false;
+      HostAdapter->HostAdapterInternalError = false;
+      scsi_mark_host_reset(HostAdapter->SCSI_Host);
+    }
+  /*
+    Release exclusive access to Host Adapter.
+  */
+  BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
 }
 
 
@@ -3436,7 +3348,7 @@ int BusLogic_QueueCommand(SCSI_Command_T *Command,
   void *BufferPointer = Command->request_buffer;
   int BufferLength = Command->request_bufflen;
   int SegmentCount = Command->use_sg;
-  BusLogic_Lock_T Lock;
+  ProcessorFlags_T ProcessorFlags;
   BusLogic_CCB_T *CCB;
   /*
     SCSI REQUEST_SENSE commands will be executed automatically by the Host
@@ -3452,7 +3364,7 @@ int BusLogic_QueueCommand(SCSI_Command_T *Command,
   /*
     Acquire exclusive access to Host Adapter.
   */
-  BusLogic_AcquireHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
   /*
     Allocate a CCB from the Host Adapter's free list.  In the unlikely event
     that there are none available and memory allocation fails, wait 1 second
@@ -3633,13 +3545,13 @@ int BusLogic_QueueCommand(SCSI_Command_T *Command,
        been called, or it may still be pending.
       */
       if (CCB->Status == BusLogic_CCB_Completed)
-       BusLogic_ProcessCompletedCCBs();
+       BusLogic_ProcessCompletedCCBs(HostAdapter);
     }
   /*
     Release exclusive access to Host Adapter.
   */
 Done:
-  BusLogic_ReleaseHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
   return 0;
 }
 
@@ -3653,7 +3565,7 @@ int BusLogic_AbortCommand(SCSI_Command_T *Command)
   BusLogic_HostAdapter_T *HostAdapter =
     (BusLogic_HostAdapter_T *) Command->host->hostdata;
   int TargetID = Command->target;
-  BusLogic_Lock_T Lock;
+  ProcessorFlags_T ProcessorFlags;
   BusLogic_CCB_T *CCB;
   int Result;
   BusLogic_IncrementErrorCounter(
@@ -3661,7 +3573,7 @@ int BusLogic_AbortCommand(SCSI_Command_T *Command)
   /*
     Acquire exclusive access to Host Adapter.
   */
-  BusLogic_AcquireHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
   /*
     If this Command has already completed, then no Abort is necessary.
   */
@@ -3754,7 +3666,7 @@ int BusLogic_AbortCommand(SCSI_Command_T *Command)
       Result = SCSI_ABORT_PENDING;
       if (CCB->Status == BusLogic_CCB_Completed)
        {
-         BusLogic_ProcessCompletedCCBs();
+         BusLogic_ProcessCompletedCCBs(HostAdapter);
          Result = SCSI_ABORT_SUCCESS;
        }
     }
@@ -3762,7 +3674,7 @@ int BusLogic_AbortCommand(SCSI_Command_T *Command)
     Release exclusive access to Host Adapter.
   */
 Done:
-  BusLogic_ReleaseHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
   return Result;
 }
 
@@ -3776,7 +3688,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
                                     SCSI_Command_T *Command,
                                     unsigned int ResetFlags)
 {
-  BusLogic_Lock_T Lock;
+  ProcessorFlags_T ProcessorFlags;
   BusLogic_CCB_T *CCB;
   int TargetID, Result;
   boolean HardReset;
@@ -3800,7 +3712,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
   /*
     Acquire exclusive access to Host Adapter.
   */
-  BusLogic_AcquireHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
   /*
     If this is an Asynchronous Reset and this Command has already completed,
     then no Reset is necessary.
@@ -3923,7 +3835,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
     Release exclusive access to Host Adapter.
   */
 Done:
-  BusLogic_ReleaseHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
   return Result;
 }
 
@@ -3939,14 +3851,14 @@ static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
 {
   int TargetID = Command->target;
   BusLogic_CCB_T *CCB, *XCCB;
-  BusLogic_Lock_T Lock;
+  ProcessorFlags_T ProcessorFlags;
   int Result = -1;
   BusLogic_IncrementErrorCounter(
     &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
   /*
     Acquire exclusive access to Host Adapter.
   */
-  BusLogic_AcquireHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
   /*
     If this is an Asynchronous Reset and this Command has already completed,
     then no Reset is necessary.
@@ -4098,7 +4010,7 @@ static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
     if (CCB->Status == BusLogic_CCB_Completed)
       {
-       BusLogic_ProcessCompletedCCBs();
+       BusLogic_ProcessCompletedCCBs(HostAdapter);
        Result = SCSI_RESET_SUCCESS;
       }
   /*
@@ -4111,7 +4023,7 @@ Done:
   /*
     Release exclusive access to Host Adapter.
   */
-  BusLogic_ReleaseHostAdapterLock(HostAdapter, &Lock);
+  BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
   return Result;
 }
 
@@ -4307,7 +4219,7 @@ int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer,
   if (WriteFlag) return 0;
   for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
        HostAdapter != NULL;
-       HostAdapter = HostAdapter->NextAll)
+       HostAdapter = HostAdapter->Next)
     if (HostAdapter->HostNumber == HostNumber) break;
   if (HostAdapter == NULL)
     {
@@ -5073,8 +4985,6 @@ void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers)
 
 #ifdef MODULE
 
-MODULE_PARM(BusLogic_Options, "s");
-
 SCSI_Host_Template_T driver_template = BUSLOGIC;
 
 #include "scsi_module.c"
index 0e07abe1f2a81852f4e5f5e35cec1d993c3fc92d..f60ee071835e581f4aba2569c3330822bf73c927 100644 (file)
@@ -2,7 +2,7 @@
 
   Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
 
-  Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
@@ -36,6 +36,7 @@
 
 typedef kdev_t KernelDevice_T;
 typedef struct proc_dir_entry PROC_DirectoryEntry_T;
+typedef unsigned long ProcessorFlags_T;
 typedef struct pt_regs Registers_T;
 typedef struct partition PartitionTable_T;
 typedef Scsi_Host_Template SCSI_Host_Template_T;
@@ -965,16 +966,6 @@ BusLogic_SetCCBFormatRequest_T;
 typedef unsigned char BusLogic_RequestedReplyLength_T;
 
 
-/*
-  Define the Lock data structure.  Until a true symmetric multiprocessing
-  kernel with fine grained locking is available, acquiring the lock is
-  implemented as saving the processor flags and disabling interrupts, and
-  releasing the lock restores the saved processor flags.
-*/
-
-typedef unsigned long BusLogic_Lock_T;
-
-
 /*
   Define the Outgoing Mailbox Action Codes.
 */
@@ -1374,7 +1365,6 @@ typedef struct BusLogic_HostAdapter
   unsigned char ModelName[9];
   unsigned char FirmwareVersion[6];
   unsigned char FullModelName[18];
-  unsigned char InterruptLabel[68];
   unsigned char Bus;
   unsigned char Device;
   unsigned char IRQ_Channel;
@@ -1401,7 +1391,8 @@ typedef struct BusLogic_HostAdapter
   boolean HostAdapterInitialized:1;
   boolean HostAdapterExternalReset:1;
   boolean HostAdapterInternalError:1;
-  volatile boolean HostAdapterCommandCompleted:1;
+  boolean ProcessCompletedCCBsActive;
+  volatile boolean HostAdapterCommandCompleted;
   unsigned short HostAdapterScatterGatherLimit;
   unsigned short DriverScatterGatherLimit;
   unsigned short MaxTargetDevices;
@@ -1430,9 +1421,10 @@ typedef struct BusLogic_HostAdapter
   FlashPoint_Info_T FlashPointInfo;
   FlashPoint_CardHandle_T CardHandle;
   struct BusLogic_HostAdapter *Next;
-  struct BusLogic_HostAdapter *NextAll;
   BusLogic_CCB_T *All_CCBs;
   BusLogic_CCB_T *Free_CCBs;
+  BusLogic_CCB_T *FirstCompletedCCB;
+  BusLogic_CCB_T *LastCompletedCCB;
   BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
   BusLogic_ErrorRecoveryStrategy_T
     ErrorRecoveryStrategy[BusLogic_MaxTargetDevices];
@@ -1514,9 +1506,9 @@ SCSI_Inquiry_T;
 
 static inline
 void BusLogic_AcquireHostAdapterLock(BusLogic_HostAdapter_T *HostAdapter,
-                                    BusLogic_Lock_T *Lock)
+                                    ProcessorFlags_T *ProcessorFlags)
 {
-  save_flags(*Lock);
+  save_flags(*ProcessorFlags);
   cli();
 }
 
@@ -1527,32 +1519,32 @@ void BusLogic_AcquireHostAdapterLock(BusLogic_HostAdapter_T *HostAdapter,
 
 static inline
 void BusLogic_ReleaseHostAdapterLock(BusLogic_HostAdapter_T *HostAdapter,
-                                    BusLogic_Lock_T *Lock)
+                                    ProcessorFlags_T *ProcessorFlags)
 {
-  restore_flags(*Lock);
+  restore_flags(*ProcessorFlags);
 }
 
 
 /*
-  BusLogic_AcquireHostAdapterLockID acquires exclusive access to Host Adapter,
-  but is only called when interrupts are disabled.
+  BusLogic_AcquireHostAdapterLockIH acquires exclusive access to Host Adapter,
+  but is only called from the interrupt handler when interrupts are disabled.
 */
 
 static inline
-void BusLogic_AcquireHostAdapterLockID(BusLogic_HostAdapter_T *HostAdapter,
-                                      BusLogic_Lock_T *Lock)
+void BusLogic_AcquireHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
+                                      ProcessorFlags_T *ProcessorFlags)
 {
 }
 
 
 /*
-  BusLogic_ReleaseHostAdapterLockID releases exclusive access to Host Adapter,
-  but is only called when interrupts are disabled.
+  BusLogic_ReleaseHostAdapterLockIH releases exclusive access to Host Adapter,
+  but is only called from the interrupt handler when interrupts are disabled.
 */
 
 static inline
-void BusLogic_ReleaseHostAdapterLockID(BusLogic_HostAdapter_T *HostAdapter,
-                                      BusLogic_Lock_T *Lock)
+void BusLogic_ReleaseHostAdapterLockIH(BusLogic_HostAdapter_T *HostAdapter,
+                                      ProcessorFlags_T *ProcessorFlags)
 {
 }
 
@@ -1685,8 +1677,8 @@ static inline void *Bus_to_Virtual(BusLogic_BusAddress_T BusAddress)
 
 /*
   Virtual_to_32Bit_Virtual maps between Kernel Virtual Addresses and
-  32 Bit Kernel Virtual Addresses.  This avoids compilation warnings
-  on 64 Bit architectures.
+  32 bit Kernel Virtual Addresses.  This avoids compilation warnings
+  on 64 bit architectures.
 */
 
 static inline
@@ -1750,17 +1742,6 @@ static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
 }
 
 
-/*
-  Define compatibility macros between Linux 2.0 and Linux 2.1.
-*/
-
-#if LINUX_VERSION_CODE < 0x20100
-
-#define MODULE_PARM(Variable, Type)
-
-#endif
-
-
 /*
   Define the version number of the FlashPoint Firmware (SCCB Manager).
 */
index 05ac7412cd143114d5945a2281af57fee0eb9bbf..d7126695be8b66e8b6f8f0fdb6f8812da7981442 100644 (file)
@@ -1,16 +1,16 @@
           BusLogic MultiMaster and FlashPoint SCSI Driver for Linux
 
-                        Version 2.0.12 for Linux 2.0
+                        Version 2.0.13 for Linux 2.0
 
                              PRODUCTION RELEASE
 
-                                29 March 1998
+                                17 April 1998
 
                               Leonard N. Zubkoff
                               Dandelion Digital
                               lnz@dandelion.com
 
-          Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>
+        Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
 
 
                                 INTRODUCTION
@@ -591,7 +591,7 @@ To install the new BusLogic SCSI driver, you may use the following commands,
 replacing "/usr/src" with wherever you keep your Linux kernel source tree:
 
   cd /usr/src
-  tar -xvzf BusLogic-2.0.12.tar.gz
+  tar -xvzf BusLogic-2.0.13.tar.gz
   mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi
   patch -p < BusLogic.patch
   cd linux
index a33898af5149a206820f7164843589374ed878ce..a786fabc699187a716d0d9b6ce71cafef40520f4 100644 (file)
@@ -4,9 +4,3 @@ Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters.
 The Mylex DAC960 PCI RAID Controllers are not supported at the present time,
 but work on a Linux driver for the DAC960 is in progress.  Please consult
 http://www.dandelion.com/Linux/ for further information on the DAC960 driver.
-Please see the file README.BusLogic for information about Linux support for
-Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters.
-
-The Mylex DAC960 PCI RAID Controllers are not supported at the present time,
-but work on a Linux driver for the DAC960 is in progress.  Please consult
-http://www.dandelion.com/Linux/ for further information on the DAC960 driver.
index cc265ecb7a48d1171882dfe9d99ebe9f89927fcd..17b17fe0c501e62f9467ff4987f6558e7ee7e5b2 100644 (file)
@@ -2298,7 +2298,22 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
   {
     scbp = scbq_remove_head(&p->delayed_scbs[tindex]);
     if (scbp)
-      scbq_insert_tail(&p->waiting_scbs, scbp);
+    {
+      if (queue_depth == 1)
+      {
+        /*
+         * Give extra preference to untagged devices, such as CD-R devices
+         * This makes it more likely that a drive *won't* stuff up while
+         * waiting on data at a critical time, such as CD-R writing and
+         * audio CD ripping operations.  Should also benefit tape drives.
+         */
+        scbq_insert_head(&p->waiting_scbs, scbp);
+      }
+      else
+      {
+        scbq_insert_tail(&p->waiting_scbs, scbp);
+      }
+    }
     if ( (queue_depth > p->dev_active_cmds[tindex]) && scbp)
     {
       scbp = scbq_remove_head(&p->delayed_scbs[tindex]);
@@ -2726,7 +2741,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
         if (aic7xxx_match_scb(p, prev_scbp, target, channel, lun, tag))
         {
           scbq_remove(&p->delayed_scbs[i], prev_scbp);
-          if ( !(prev_scbp->flags & SCB_QUEUED_ABORT) )
+          if ( !(prev_scbp->flags & SCB_WAITINGQ) )
           {
             p->dev_active_cmds[i]++;
             p->activescbs++;
@@ -2785,7 +2800,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
       if (aic7xxx_match_scb(p, prev_scbp, target, channel, lun, tag))
       {
         scbq_remove(&p->waiting_scbs, prev_scbp);
-        if ( !(prev_scbp->flags & SCB_QUEUED_ABORT) )
+        if ( !(prev_scbp->flags & SCB_WAITINGQ) )
         {
           p->dev_active_cmds[TARGET_INDEX(prev_scbp->cmd)]++;
           p->activescbs++;
@@ -2838,6 +2853,11 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
         if (aic7xxx_match_scb(p, scbp, target, channel, lun, tag))
         {
           next = aic7xxx_abort_waiting_scb(p, scbp, next, prev);
+          if ( !(scbp->flags & SCB_WAITINGQ) )
+          {
+            p->dev_active_cmds[TARGET_INDEX(scbp->cmd)]++;
+            p->activescbs++;
+          }
           scbp->flags &= ~(SCB_ACTIVE | SCB_WAITINGQ);
           scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
           if (prev == SCB_LIST_NULL)
@@ -2893,6 +2913,11 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
         if (aic7xxx_match_scb(p, scbp, target, channel, lun, tag))
         {
           next = aic7xxx_rem_scb_from_disc_list(p, next);
+          if ( !(scbp->flags & SCB_WAITINGQ) )
+          {
+            p->dev_active_cmds[TARGET_INDEX(scbp->cmd)]++;
+            p->activescbs++;
+          }
           scbp->flags &= ~(SCB_ACTIVE | SCB_WAITINGQ);
           scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
           scbp->hscb->control = 0;
@@ -5008,6 +5033,21 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
           (unsigned long) scb->cmd);
         continue;
       }
+      else if (scb->flags & SCB_QUEUED_ABORT)
+      {
+        pause_sequencer(p);
+        if ( ((aic_inb(p, LASTPHASE) & PHASE_MASK) != P_BUSFREE) &&
+             (aic_inb(p, SCB_TAG) == scb->hscb->tag) )
+        {
+          unpause_sequencer(p, FALSE);
+          continue;
+        }
+        aic7xxx_reset_device(p, scb->cmd->target, scb->cmd->channel,
+          scb->cmd->lun, scb->cmd->lun);
+        scb->flags &= ~(SCB_QUEUED_FOR_DONE | SCB_RESET | SCB_ABORT |
+          SCB_QUEUED_ABORT);
+        unpause_sequencer(p, FALSE);
+      }
       switch (status_byte(scb->hscb->target_status))
       {
         case QUEUE_FULL:
@@ -8185,7 +8225,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
       if ( (lastphase != P_MESGOUT) && (lastphase != P_MESGIN) )
       {
         /* Send the abort message to the active SCB. */
-        aic_outb(p, MSG_BUS_DEV_RESET, MSG_OUT);
+        aic_outb(p, HOST_MSG, MSG_OUT);
         aic_outb(p, lastphase | ATNO, SCSISIGO);
         if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
           printk(INFO_LEAD "Device reset message in "
index da2603a6af0d0b61abb51cb65b41162e89981942..ffd1e00e10910d72993c0fce09464ec581594a18 100644 (file)
@@ -1,6 +1,22 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
- *   
+ *
+ *      18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
+ *          Reworked interrupt handler.
+ *
+ *      11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
+ *          Major reliability improvement: when a batch with overlapping
+ *          requests is detected, requests are queued one at a time
+ *          eliminating any possible board or drive reordering.
+ *
+ *      10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
+ *          Improved SMP support (if linux version >= 2.1.95).
+ *
+ *       9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94
+ *          Added support for new PCI code and IO-APIC remapping of irqs.
+ *          Performance improvement: when sequential i/o is detected,
+ *          always use direct sort instead of reverse sort.
+ *
  *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
  *          io_port is now unsigned long.
  *
@@ -8,7 +24,6 @@
  *          Use new scsi error handling code (if linux version >= 2.1.88).
  *          Use new interrupt code.
  *
- *
  *      12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
  *          Use of udelay inside the wait loops to avoid timeout
  *          problems with fast cpus.
@@ -22,7 +37,7 @@
  *          Use of serial_number_at_timeout in abort and reset processing.
  *          Use of the __initfunc and __initdata macro in setup code.
  *          Minor cleanups in the list_statistics code.
- *          Increased controller busy timeout in order to better support 
+ *          Increased controller busy timeout in order to better support
  *          slow SCSI devices.
  *
  *      24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26
@@ -31,7 +46,7 @@
  *          Fixed data transfer direction for some SCSI opcodes.
  *          Immediate acknowledge to request sense commands.
  *          Linked commands to each disk device are now reordered by elevator
- *          sorting. Rare cases in which reordering of write requests could 
+ *          sorting. Rare cases in which reordering of write requests could
  *          cause wrong results are managed.
  *          Fixed spurious timeouts caused by long simple queue tag sequences.
  *          New command line option (tm:[0-3]) to choose the type of tags:
  *
  *      28 Jan 1995 rev. 1.14 for linux 1.1.86
  *          Added module support.
- *          Log and do a retry when a disk drive returns a target status 
+ *          Log and do a retry when a disk drive returns a target status
  *          different from zero on a recovered error.
  *
  *      24 Jan 1995 rev. 1.13 for linux 1.1.85
  *
  *      17 Dec 1994 rev. 1.11 for linux 1.1.74
  *          Use the scsicam_bios_param routine. This allows an easy
- *          migration path from disk partition tables created using 
+ *          migration path from disk partition tables created using
  *          different SCSI drivers and non optimal disk geometry.
  *
  *      15 Dec 1994 rev. 1.10 for linux 1.1.74
  *  The DPT PM2001 provides only the EATA/PIO interface and hence is not
  *  supported by this driver.
  *
- *  This code has been tested with up to 3 Distributed Processing Technology 
+ *  This code has been tested with up to 3 Distributed Processing Technology
  *  PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers,
  *  in any combination of private and shared IRQ.
- *  PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS 
+ *  PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS
  *  v003.D0, firmware v07G.0).
  *
  *  DPT SmartRAID boards support "Hardware Array" - a group of disk drives
  *
  *  WARNING: to create a RAID-0 "Hardware Array" you must select "Other Unix"
  *  as the current OS in the DPTMGR "Initial System Installation" menu.
- *  Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0), 
+ *  Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0),
  *  which is not supported by the actual SCSI subsystem.
  *  To get the "Array Group" functionality, the Linux MD driver must be used
  *  instead of the DPT "Array Group" feature.
  *
  *  Multiple ISA, EISA and PCI boards can be configured in the same system.
  *  It is suggested to put all the EISA boards on the same IRQ level, all
- *  the PCI  boards on another IRQ level, while ISA boards cannot share 
+ *  the PCI  boards on another IRQ level, while ISA boards cannot share
  *  interrupts.
  *
  *  If you configure multiple boards on the same IRQ, the interrupt must
  *  bus, or even if you system has no EISA bus at all.
  *  Do not force any ISA address on EATA PCI boards.
  *
- *  If PCI bios support is configured into the kernel, BIOS32 is used to 
+ *  If PCI bios support is configured into the kernel, BIOS32 is used to
  *  include in the list of i/o ports to be probed all the PCI SCSI controllers.
  *
  *  Due to a DPT BIOS "feature", it might not be possible to force an EISA
  *
  *  The sequence of detection probes is:
  *
- *  - ISA 0x1F0; 
+ *  - ISA 0x1F0;
  *  - PCI SCSI controllers (only if BIOS32 is available);
  *  - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15);
  *  - ISA  0x170, 0x230, 0x330.
- * 
+ *
  *  The above list of detection probes can be totally replaced by the
  *  boot command line option: "eata=port0,port1,port2,...", where the
  *  port0, port1... arguments are ISA/EISA/PCI addresses to be probed.
  *  in the elevator sorting queue. When the active command completes, the
  *  commands in this queue are sorted by sector address. The sort is chosen
  *  between increasing or decreasing by minimizing the seek distance between
- *  the sector of the commands just completed and the sector of the first 
- *  command in the list to be sorted. 
+ *  the sector of the commands just completed and the sector of the first
+ *  command in the list to be sorted.
  *  Trivial math assures that the unsorted average seek distance when doing
  *  random seeks over S sectors is S/3.
  *  When (Q-1) requests are uniformly distributed over S sectors, the average
  *  distance between two adjacent requests is S/((Q-1) + 1), so the sorted
  *  average seek distance for (Q-1) random requests over S sectors is S/Q.
  *  The elevator sorting hence divides the seek distance by a factor Q/3.
- *  The above pure geometric remarks are valid in all cases and the 
+ *  The above pure geometric remarks are valid in all cases and the
  *  driver effectively reduces the seek distance by the predicted factor
  *  when there are Q concurrent read i/o operations on the device, but this
  *  does not necessarily results in a noticeable performance improvement:
  *
  *  Note: command reordering inside a batch of queued commands could cause
  *        wrong results only if there is at least one write request and the
- *        intersection (sector-wise) of all requests is not empty. 
+ *        intersection (sector-wise) of all requests is not empty.
  *        When the driver detects a batch including overlapping requests
  *        (a really rare event) strict serial (pid) order is enforced.
  *  ----------------------------------------------------------------------------
  *  the driver sets host->wish_block = TRUE for all ISA boards.
  */
 
+#include <linux/version.h>
+
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 #define MAX_INT_PARAM 10
+
 #if defined(MODULE)
 #include <linux/module.h>
-#include <linux/version.h>
+
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26)
 MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i");
 MODULE_PARM(linked_comm, "i");
@@ -294,6 +312,7 @@ MODULE_PARM(max_queue_depth, "i");
 MODULE_PARM(tag_mode, "i");
 MODULE_AUTHOR("Dario Ballabio");
 #endif
+
 #endif
 
 #include <linux/string.h>
@@ -304,6 +323,11 @@ MODULE_AUTHOR("Dario Ballabio");
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+#include <asm/spinlock.h>
+#endif
+
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -314,9 +338,12 @@ MODULE_AUTHOR("Dario Ballabio");
 #include "eata.h"
 #include <linux/stat.h>
 #include <linux/config.h>
-#include <linux/bios32.h>
 #include <linux/pci.h>
 
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)
+#include <linux/bios32.h>
+#endif
+
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36)
 #include <linux/init.h>
 #else
@@ -338,11 +365,12 @@ struct proc_dir_entry proc_scsi_eata2x = {
 
 #undef  DEBUG_LINKED_COMMANDS
 #undef  DEBUG_DETECT
+#undef  DEBUG_PCI_DETECT
 #undef  DEBUG_INTERRUPT
 #undef  DEBUG_RESET
 
 #define MAX_ISA 4
-#define MAX_VESA 0 
+#define MAX_VESA 0
 #define MAX_EISA 15
 #define MAX_PCI 16
 #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
@@ -482,7 +510,7 @@ struct mssp {
    unchar target_status;       /* SCSI status received after data transfer */
    unchar unused[2];
    ulong inv_res_len;          /* Number of bytes not transferred */
-   Scsi_Cmnd *SCpnt;           /* Address set in cp */
+   struct mscp *cpp;           /* Address set in cp */
    char mess[12];
    };
 
@@ -498,7 +526,7 @@ struct mscp {
            reqsen:1,     /* Transfer Request Sense Data to addr using DMA */
                sg:1,     /* Use Scatter/Gather */
                  :1,
-           interp:1,     /* The controller interprets cp, not the target */ 
+           interp:1,     /* The controller interprets cp, not the target */
              dout:1,     /* Direction of Transfer is Out (Host to Target) */
               din:1;     /* Direction of Transfer is In (Target to Host) */
    unchar sense_len;     /* Request Sense Length */
@@ -518,10 +546,11 @@ struct mscp {
    unchar mess[3];       /* Massage to/from Target */
    unchar cdb[12];       /* Command Descriptor Block */
    ulong  data_len;      /* If sg=0 Data Length, if sg=1 sglist length */
-   Scsi_Cmnd *SCpnt;     /* Address to be returned in sp */
+   struct mscp *cpp;     /* Address to be returned in sp */
    ulong  data_address;  /* If sg=0 Data Address, if sg=1 sglist address */
    ulong  sp_addr;       /* Address where sp is DMA'ed when cp completes */
    ulong  sense_addr;    /* Address where Sense Data is DMA'ed on error */
+   Scsi_Cmnd *SCpnt;
    unsigned int index;   /* cp index */
    struct sg_list *sglist;
    };
@@ -541,7 +570,7 @@ struct hostdata {
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or EISA/PCI */
    unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
-   struct mssp sp[MAX_MAILBOXES];       /* Returned status for this board */
+   struct mssp sp[2];                   /* Returned status for this board */
    };
 
 static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -551,7 +580,7 @@ static char sha[MAX_BOARDS];
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
 
-static unsigned long io_port[] __initdata = { 
+static unsigned long io_port[] __initdata = {
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -566,11 +595,11 @@ static unsigned long io_port[] __initdata = {
 
    /* MAX_EISA ports */
    0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88,
-   0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 
+   0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88,
 
    /* Other (MAX_ISA - 1) ports */
    0x170,  0x230,  0x330,
+
    /* End of list */
    0x0
    };
@@ -583,7 +612,7 @@ static unsigned long io_port[] __initdata = {
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
 #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
-static void eata2x_interrupt_handler(int, void *, struct pt_regs *);
+static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
 static int setup_done = FALSE;
@@ -610,7 +639,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN;
 
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
-   int j, ntag = 0, nuntag = 0, tqd, utqd; 
+   int j, ntag = 0, nuntag = 0, tqd, utqd;
    unsigned long flags;
 
    save_flags(flags);
@@ -715,10 +744,48 @@ static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) {
    return FALSE;
 }
 
+__initfunc (static inline int
+            get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) {
+
+#if defined(CONFIG_PCI)
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+
+   unsigned int addr;
+   struct pci_dev *dev = NULL;
+
+   if (!pci_present()) return FALSE;
+
+   while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) {
+
+      if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;
+
+#if defined(DEBUG_PCI_DETECT)
+      printk("%s: get_pci_irq, bus %d, devfn 0x%x, addr 0x%x, apic_irq %u.\n",
+             driver_name, dev->bus->number, dev->devfn, addr, dev->irq);
+#endif
+
+      if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+             continue;
+
+      if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {
+         *apic_irq = dev->irq;
+         return TRUE;
+         }
+
+      }
+
+#endif /* end new style PCI code */
+
+#endif /* end CONFIG_PCI */
+
+   return FALSE;
+}
+
 __initfunc (static inline int port_detect \
       (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
    unsigned char irq, dma_channel, subversion, i;
-   unsigned char protocol_rev;
+   unsigned char protocol_rev, apic_irq;
    struct eata_info info;
    char *bus_type, dma_name[16], tag_type;
 
@@ -737,14 +804,14 @@ __initfunc (static inline int port_detect \
    if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE;
 
    /* Read the info structure */
-   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) 
+   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0]))
       return FALSE;
 
    /* Check the controller "EATA" signature */
    if (info.sign != EATA_SIGNATURE) return FALSE;
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
-      printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
+      printk("%s: config structure size (%ld bytes) too short, detaching.\n",
              name, DEV2H(info.data_len));
       return FALSE;
       }
@@ -812,8 +879,13 @@ __initfunc (static inline int port_detect \
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
 
+   if (get_pci_irq(port_base, &apic_irq) && (irq != apic_irq)) {
+      printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, apic_irq);
+      irq = apic_irq;
+      }
+
    /* Board detected, allocate its IRQ */
-   if (request_irq(irq, eata2x_interrupt_handler,
+   if (request_irq(irq, do_interrupt_handler,
              SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
              driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
@@ -896,7 +968,7 @@ __initfunc (static inline int port_detect \
 
    /* DPT PM2012 does not allow to detect can_queue correctly */
    if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue  < 2) {
-      printk("%s: detect, wrong n. of Mbox %d, fixed.\n",
+      printk("%s: detect, wrong n. of mbox %d, fixed.\n",
              BN(j), sh[j]->can_queue);
       sh[j]->can_queue = MAX_MAILBOXES;
       }
@@ -924,14 +996,14 @@ __initfunc (static inline int port_detect \
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
-            sh[j]->sg_tablesize * sizeof(struct sg_list), 
+            sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
          printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
          eata2x_release(sh[j]);
          return FALSE;
          }
-      
-   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
@@ -972,7 +1044,7 @@ __initfunc (static inline int port_detect \
 
    if (protocol_rev == 'C')
       printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\
-             "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest, 
+             "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest,
              info.pci, info.eisa, info.raidnum);
 #endif
 
@@ -987,8 +1059,8 @@ __initfunc (void eata2x_setup(char *str, int *ints)) {
 
       if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
 
-      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; 
-   
+      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
+
       io_port[i] = 0;
       setup_done = TRUE;
       }
@@ -1016,9 +1088,37 @@ __initfunc (static void add_pci_ports(void)) {
 
 #if defined(CONFIG_PCI)
 
+   unsigned int addr, k;
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+
+   struct pci_dev *dev = NULL;
+
+   if (!pci_present()) return;
+
+   for (k = 0; k < MAX_PCI; k++) {
+
+      if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break;
+
+      if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;
+
+#if defined(DEBUG_PCI_DETECT)
+      printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n",
+             driver_name, k, dev->bus->number, dev->devfn, addr);
+#endif
+
+      if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+             continue;
+
+      /* Reverse the returned address order */
+      io_port[MAX_INT_PARAM + MAX_PCI - k] =
+             (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
+      }
+
+#else  /* else old style PCI code */
+
    unsigned short i = 0;
    unsigned char bus, devfn;
-   unsigned int addr, k;
 
    if (!pcibios_present()) return;
 
@@ -1030,7 +1130,7 @@ __initfunc (static void add_pci_ports(void)) {
       if (pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &addr)
              != PCIBIOS_SUCCESSFUL) continue;
 
-#if defined(DEBUG_DETECT)
+#if defined(DEBUG_PCI_DETECT)
       printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n",
              driver_name, k, bus, devfn, addr);
 #endif
@@ -1039,10 +1139,13 @@ __initfunc (static void add_pci_ports(void)) {
              continue;
 
       /* Reverse the returned address order */
-      io_port[MAX_INT_PARAM + MAX_PCI - k] = 
+      io_port[MAX_INT_PARAM + MAX_PCI - k] =
              (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
       }
-#endif
+
+#endif /* end old style PCI code */
+
+#endif /* end CONFIG_PCI */
 
    return;
 }
@@ -1075,7 +1178,7 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) {
       if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
       }
 
-   if (j > 0) 
+   if (j > 0)
       printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
    num_boards = j;
@@ -1106,7 +1209,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
-      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 
+      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
       0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
       };
 
@@ -1124,16 +1227,16 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
 
    if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
-      SCpnt->result = DID_OK << 16; 
+      SCpnt->result = DID_OK << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 0;
       }
 
-   /* i is the mailbox number, look for the first free mailbox 
+   /* i is the mailbox number, look for the first free mailbox
       starting from last_cp_used */
    i = HD(j)->last_cp_used + 1;
 
@@ -1150,17 +1253,17 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
-      if (HD(j)->in_reset) 
+      if (HD(j)->in_reset)
          printk("%s: qcomm, already in reset.\n", BN(j));
       else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
-               == SCSI_RESET_SUCCESS) 
+               == SCSI_RESET_SUCCESS)
          panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
-      SCpnt->result = DID_BUS_BUSY << 16; 
+      SCpnt->result = DID_BUS_BUSY << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -1170,13 +1273,12 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
 
    /* Set pointer to status packet structure */
-   spp = &HD(j)->sp[i];
-
-   memset(spp, 0, sizeof(struct mssp));
+   spp = &HD(j)->sp[0];
 
    /* The EATA protocol uses Big Endian format */
    cpp->sp_addr = V2DEV(spp);
 
+   cpp->cpp = cpp;
    SCpnt->scsi_done = done;
    cpp->index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
@@ -1206,11 +1308,11 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    cpp->one = TRUE;
    cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
-   cpp->lun = SCpnt->lun;  
+   cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = V2DEV(SCpnt->sense_buffer); 
+   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
    cpp->sense_len = sizeof SCpnt->sense_buffer;
-   
+
    if (SCpnt->device->tagged_queue) {
 
       if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] ||
@@ -1250,13 +1352,13 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
-      SCpnt->result = DID_ERROR << 16; 
+      SCpnt->result = DID_ERROR << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
              " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
              SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -1282,7 +1384,7 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
-   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", 
+   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
           BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
@@ -1350,7 +1452,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
           BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
@@ -1411,10 +1513,10 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
       if (SCpnt->host_scribble == NULL)
          panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
+      if (*(unsigned int *)SCpnt->host_scribble != i)
          panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
-      if (SCpnt->scsi_done == NULL) 
+      if (SCpnt->scsi_done == NULL)
          panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
@@ -1497,7 +1599,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
    for (i = 0; i < n - 1; i++) {
       k = i;
 
-      for (j = k + 1; j < n; j++) 
+      for (j = k + 1; j < n; j++)
          if (rev) {
             if (sk[j] > sk[k]) k = j;
             }
@@ -1514,7 +1616,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
    return;
    }
 
-static inline void reorder(unsigned int j, unsigned long cursec,
+static inline int reorder(unsigned int j, unsigned long cursec,
                  unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
    Scsi_Cmnd *SCpnt;
    struct mscp *cpp;
@@ -1523,6 +1625,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
    unsigned int input_only = TRUE, overlap = FALSE;
    unsigned long sl[n_ready], pl[n_ready], ll[n_ready];
    unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0;
+   unsigned long ioseek = 0;
 
    static unsigned int flushcount = 0, batchcount = 0, sortcount = 0;
    static unsigned int readycount = 0, ovlcount = 0, inputcount = 0;
@@ -1533,10 +1636,10 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
              " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
              ovlcount, readycount, readysorted, sortcount, revcount,
-             seeknosort / (readycount + 1), 
+             seeknosort / (readycount + 1),
              seeksorted / (readycount + 1));
 
-   if (n_ready <= 1) return;
+   if (n_ready <= 1) return FALSE;
 
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
@@ -1547,12 +1650,13 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector;
 
       sl[n] = SCpnt->request.sector;
+      ioseek += SCpnt->request.nr_sectors;
 
       if (!n) continue;
 
       if (sl[n] < sl[n - 1]) s = FALSE;
       if (sl[n] > sl[n - 1]) r = FALSE;
-   
+
       if (link_statistics) {
          if (sl[n] > sl[n - 1])
             seek += sl[n] - sl[n - 1];
@@ -1568,6 +1672,8 @@ static inline void reorder(unsigned int j, unsigned long cursec,
 
    if (cursec > ((maxsec + minsec) / 2)) rev = TRUE;
 
+   if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE;
+
    if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev);
 
    if (!input_only) for (n = 0; n < n_ready; n++) {
@@ -1575,7 +1681,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
 
       if (!n) continue;
+
       if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
           || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
       }
@@ -1584,9 +1690,9 @@ static inline void reorder(unsigned int j, unsigned long cursec,
 
    if (link_statistics) {
       if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
-      batchcount++; readycount += n_ready, seeknosort += seek / 1024; 
+      batchcount++; readycount += n_ready, seeknosort += seek / 1024;
       if (input_only) inputcount++;
-      if (overlap) { ovlcount++; seeksorted += seek / 1024; }
+      if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
       else seeksorted += (iseek + maxsec - minsec) / 1024;
       if (rev && !r)     {  revcount++; readysorted += n_ready; }
       if (!rev && !s)    { sortcount++; readysorted += n_ready; }
@@ -1601,10 +1707,11 @@ static inline void reorder(unsigned int j, unsigned long cursec,
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
                 SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
                 SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
-                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), 
+                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->din);
          }
 #endif
+   return overlap;
 }
 
 static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
@@ -1626,13 +1733,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
       il[n_ready++] = k;
       }
 
-   reorder(j, cursec, ihdlr, il, n_ready);
-  
+   if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
+
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
 
       if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
-         printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\
+         printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
                 " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
                 SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
          HD(j)->cp_stat[k] = ABORTING;
@@ -1644,196 +1751,201 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
 
 }
 
-static void eata2x_interrupt_handler(int irq, void *shap,
-                                     struct pt_regs *regs) {
+static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, c, status, tstatus, reg;
-   unsigned int n, n_ready, il[MAX_MAILBOXES];
-   struct mssp *spp;
+   unsigned int i, k, c, status, tstatus, reg;
+   struct mssp *dspp, *spp;
    struct mscp *cpp;
 
-   /* Check if the interrupt must be processed by this handler */
-   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
    if (sh[j]->irq != irq)
        panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
-   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
-                        HD(j)->iocount);
+
    /* Check if this board need to be serviced */
    if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return;
 
-   n_ready = 0;
+   HD(j)->iocount++;
 
-   /* Find the mailboxes to be serviced on this board */
-   for (i = 0; i < sh[j]->can_queue; i++) {
-      spp = &HD(j)->sp[i];
-
-      /* Check if this mailbox has completed the operation */
-      if (spp->eoc == FALSE) continue;
+   if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
+                        HD(j)->iocount);
 
-      spp->eoc = FALSE;
-      il[n_ready++] = i;
+   /* Check if this board is still busy */
+   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      reg = inb(sh[j]->io_port + REG_STATUS);
+      printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+      return;
       }
 
+   dspp = &HD(j)->sp[0];
+   spp  = &HD(j)->sp[1];
+
+   /* Make a local copy just before clearing the interrupt indication */
+   memcpy(spp, dspp, sizeof(struct mssp));
+
+   /* Clear the completion flag and cp pointer on the dynamic copy of sp */
+   memset(dspp, 0, sizeof(struct mssp));
+
    /* Read the status register to clear the interrupt indication */
    reg = inb(sh[j]->io_port + REG_STATUS);
 
-   /* Mailbox service loop */
-   for (n = 0; n < n_ready; n++) {
-      i = il[n];
-      spp = &HD(j)->sp[i];
+   /* Reject any sp with supspect data */
+   if (spp->eoc == FALSE) 
+      printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+   if (spp->cpp == NULL) 
+      printk("%s: ihdlr, spp->cpp == NULL,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+   if (spp->eoc == FALSE || spp->cpp == NULL) return;
 
-      if (HD(j)->cp_stat[i] == IGNORE) {
-         HD(j)->cp_stat[i] = FREE;
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == LOCKED) {
-         HD(j)->cp_stat[i] = FREE;
-         printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
-                HD(j)->iocount);
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == FREE) {
-         printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
-                HD(j)->iocount);
-         return;
-         }
-      else if (HD(j)->cp_stat[i] == IN_RESET)
-         printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-      else if (HD(j)->cp_stat[i] != IN_USE) 
-         panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
+   cpp = spp->cpp;
+
+   /* Find the mailbox to be serviced on this board */
+   i = cpp - HD(j)->cp;
+
+   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
+                                     || i >= sh[j]->can_queue)
+      panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
+            cpp, HD(j)->cp);
 
+   if (HD(j)->cp_stat[i] == IGNORE) {
+      HD(j)->cp_stat[i] = FREE;
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == LOCKED) {
       HD(j)->cp_stat[i] = FREE;
-      cpp = &HD(j)->cp[i];
-      SCpnt = spp->SCpnt;
+      printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == FREE) {
+      printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
+             HD(j)->iocount);
+      return;
+      }
+   else if (HD(j)->cp_stat[i] == IN_RESET)
+      printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE)
+      panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n",
+            BN(j), i, HD(j)->cp_stat[i]);
 
-      if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
+   HD(j)->cp_stat[i] = FREE;
+   SCpnt = cpp->SCpnt;
 
-      if (SCpnt != cpp->SCpnt)
-         panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i,
-               SCpnt, cpp->SCpnt);
+   if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-      if (SCpnt->host_scribble == NULL)
-         panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
-               SCpnt->pid, SCpnt);
+   if (SCpnt->host_scribble == NULL)
+      panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
+            SCpnt->pid, SCpnt);
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
-         panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n",
-              BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+   if (*(unsigned int *)SCpnt->host_scribble != i)
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
-      if (linked_comm && SCpnt->device->queue_depth > 2
-                                        && TLDEV(SCpnt->device->type))
+   if (linked_comm && SCpnt->device->queue_depth > 2
+                                     && TLDEV(SCpnt->device->type))
       flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
 
-      tstatus = status_byte(spp->target_status);
-
-      switch (spp->adapter_status) {
-         case ASOK:     /* status OK */
-
-            /* Forces a reset if a disk drive keeps returning BUSY */
-            if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
-               status = DID_ERROR << 16;
-
-            /* If there was a bus reset, redo operation on each target */
-            else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
-                     && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
-               status = DID_BUS_BUSY << 16;
-
-            /* Works around a flaw in scsi.c */
-            else if (tstatus == CHECK_CONDITION
-                     && SCpnt->device->type == TYPE_DISK
-                     && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
-               status = DID_BUS_BUSY << 16;
-
-            else
-               status = DID_OK << 16;
-
-            if (tstatus == GOOD)
-               HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
-
-            if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-               printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                      "target_status 0x%x, sense key 0x%x.\n", BN(j), 
-                      SCpnt->channel, SCpnt->target, SCpnt->lun, 
-                      SCpnt->pid, spp->target_status, 
-                      SCpnt->sense_buffer[2]);
-
-            HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
-
-            if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
-
-            break;
-         case ASST:     /* Selection Time Out */
-         case 0x02:     /* Command Time Out   */
-
-            if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
-               status = DID_ERROR << 16;
-            else {
-               status = DID_TIME_OUT << 16;
-               HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
-               }
-
-            break;
-
-         /* Perform a limited number of internal retries */
-         case 0x03:     /* SCSI Bus Reset Received */
-         case 0x04:     /* Initial Controller Power-up */
-
-            for (c = 0; c <= sh[j]->max_channel; c++) 
-               for (k = 0; k < sh[j]->max_id; k++) 
-                  HD(j)->target_redo[k][c] = TRUE;
-
-            if (SCpnt->device->type != TYPE_TAPE
-                && HD(j)->retries < MAX_INTERNAL_RETRIES) {
-               status = DID_BUS_BUSY << 16;
-               HD(j)->retries++;
-               HD(j)->last_retried_pid = SCpnt->pid;
-               }
-            else 
-               status = DID_ERROR << 16;
-
-            break;
-         case 0x05:     /* Unexpected Bus Phase */
-         case 0x06:     /* Unexpected Bus Free */
-         case 0x07:     /* Bus Parity Error */
-         case 0x08:     /* SCSI Hung */
-         case 0x09:     /* Unexpected Message Reject */
-         case 0x0a:     /* SCSI Bus Reset Stuck */
-         case 0x0b:     /* Auto Request-Sense Failed */
-         case 0x0c:     /* Controller Ram Parity Error */
-         default:
+   tstatus = status_byte(spp->target_status);
+
+   switch (spp->adapter_status) {
+      case ASOK:     /* status OK */
+
+         /* Forces a reset if a disk drive keeps returning BUSY */
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
             status = DID_ERROR << 16;
-            break;
-         }
 
-      SCpnt->result = status | spp->target_status;
-      HD(j)->iocount++;
+         /* If there was a bus reset, redo operation on each target */
+         else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                  && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
+            status = DID_BUS_BUSY << 16;
+
+         /* Works around a flaw in scsi.c */
+         else if (tstatus == CHECK_CONDITION
+                  && SCpnt->device->type == TYPE_DISK
+                  && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+            status = DID_BUS_BUSY << 16;
+
+         else
+            status = DID_OK << 16;
+
+         if (tstatus == GOOD)
+            HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
+
+         if (spp->target_status && SCpnt->device->type == TYPE_DISK)
+            printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j),
+                   SCpnt->channel, SCpnt->target, SCpnt->lun,
+                   SCpnt->pid, spp->target_status,
+                   SCpnt->sense_buffer[2]);
+
+         HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
+
+         if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
+
+         break;
+      case ASST:     /* Selection Time Out */
+      case 0x02:     /* Command Time Out   */
+
+         if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
+            status = DID_ERROR << 16;
+         else {
+            status = DID_TIME_OUT << 16;
+            HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
+            }
+
+         break;
+
+      /* Perform a limited number of internal retries */
+      case 0x03:     /* SCSI Bus Reset Received */
+      case 0x04:     /* Initial Controller Power-up */
+
+         for (c = 0; c <= sh[j]->max_channel; c++)
+            for (k = 0; k < sh[j]->max_id; k++)
+               HD(j)->target_redo[k][c] = TRUE;
+
+         if (SCpnt->device->type != TYPE_TAPE
+             && HD(j)->retries < MAX_INTERNAL_RETRIES) {
+            status = DID_BUS_BUSY << 16;
+            HD(j)->retries++;
+            HD(j)->last_retried_pid = SCpnt->pid;
+            }
+         else
+            status = DID_ERROR << 16;
+
+         break;
+      case 0x05:     /* Unexpected Bus Phase */
+      case 0x06:     /* Unexpected Bus Free */
+      case 0x07:     /* Bus Parity Error */
+      case 0x08:     /* SCSI Hung */
+      case 0x09:     /* Unexpected Message Reject */
+      case 0x0a:     /* SCSI Bus Reset Stuck */
+      case 0x0b:     /* Auto Request-Sense Failed */
+      case 0x0c:     /* Controller Ram Parity Error */
+      default:
+         status = DID_ERROR << 16;
+         break;
+      }
+
+   SCpnt->result = status | spp->target_status;
 
 #if defined (DEBUG_INTERRUPT)
-      if (SCpnt->result || do_trace)
+   if (SCpnt->result || do_trace)
 #else
-      if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-          (spp->adapter_status != ASOK && 
-          spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
-          do_trace || msg_byte(spp->target_status))
+   if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
+       (spp->adapter_status != ASOK &&
+        spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
+        do_trace || msg_byte(spp->target_status))
 #endif
-         printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
-                BN(j), i, spp->adapter_status, spp->target_status,
-                SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
-                reg, HD(j)->iocount);
+      printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
+             " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
+             BN(j), i, spp->adapter_status, spp->target_status,
+             SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+             reg, HD(j)->iocount);
 
-      /* Set the command state to inactive */
-      SCpnt->host_scribble = NULL;
-
-      SCpnt->scsi_done(SCpnt);
+   /* Set the command state to inactive */
+   SCpnt->host_scribble = NULL;
 
-      }   /* Mailbox loop */
-
-   if (n_ready > 1)
-      printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready);
+   SCpnt->scsi_done(SCpnt);
 
    if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
                         HD(j)->iocount);
@@ -1841,6 +1953,26 @@ static void eata2x_interrupt_handler(int irq, void *shap,
    return;
 }
 
+static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
+
+   unsigned int j;
+
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   {
+   unsigned long flags;
+   spin_lock_irqsave(&io_request_lock, flags);
+   ihdlr(irq, j);
+   spin_unlock_irqrestore(&io_request_lock, flags);
+   }
+#else
+   ihdlr(irq, j);
+#endif
+
+}
+
 int eata2x_release(struct Scsi_Host *shpnt) {
    unsigned long flags;
    unsigned int i, j;
@@ -1849,11 +1981,11 @@ int eata2x_release(struct Scsi_Host *shpnt) {
    cli();
 
    for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
-    
+
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   for (i = 0; i < sh[j]->can_queue; i++) 
+   for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
    free_irq(sh[j]->irq, &sha[j]);
index 3322a5eb512e9967b380af1c857ad3b92202f358..2eb04f657493dc941e575e8ed67ee8461686989f 100644 (file)
@@ -5,6 +5,7 @@
 #define _EATA_H
 
 #include <scsi/scsicam.h>
+#include <linux/version.h>
 
 int eata2x_detect(Scsi_Host_Template *);
 int eata2x_release(struct Scsi_Host *);
@@ -12,7 +13,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "4.02.00"
+#define EATA_VERSION "4.20.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
index 0095a6b0759b32211480dc600155b5a2f3085103..6263e22586e2d8b4b0753c08175725390357dbae 100644 (file)
@@ -1,6 +1,21 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
+ *          Reworked interrupt handler.
+ *
+ *      11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
+ *          Major reliability improvement: when a batch with overlapping
+ *          requests is detected, requests are queued one at a time
+ *          eliminating any possible board or drive reordering.
+ *
+ *      10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
+ *          Improved SMP support (if linux version >= 2.1.95).
+ *
+ *       9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94
+ *          Performance improvement: when sequential i/o is detected,
+ *          always use direct sort instead of reverse sort.
+ *
  *       4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
  *          io_port is now unsigned long.
  *
@@ -28,7 +43,7 @@
  *          Fixed data transfer direction for some SCSI opcodes.
  *          Immediate acknowledge to request sense commands.
  *          Linked commands to each disk device are now reordered by elevator
- *          sorting. Rare cases in which reordering of write requests could 
+ *          sorting. Rare cases in which reordering of write requests could
  *          cause wrong results are managed.
  *
  *      18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28
  *      28 Oct 1994 rev. 1.09 for linux 1.1.58  Final BETA release.
  *      16 Jul 1994 rev. 1.00 for linux 1.1.29  Initial ALPHA release.
  *
- *          This driver is a total replacement of the original UltraStor 
+ *          This driver is a total replacement of the original UltraStor
  *          scsi driver, but it supports ONLY the 14F and 34F boards.
  *          It can be configured in the same kernel in which the original
  *          ultrastor driver is configured to allow the original U24F
  *          support.
- * 
+ *
  *          Multiple U14F and/or U34F host adapters are supported.
  *
  *  Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
  *  24F - EISA Bus Master HA with floppy support and WD1003 emulation.
  *  34F - VESA Local-Bus Bus Master HA (no WD1003 emulation).
  *
- *  This code has been tested with up to two U14F boards, using both 
+ *  This code has been tested with up to two U14F boards, using both
  *  firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware
- *  28004-006/38004-005 (BIOS rev. 2.01). 
+ *  28004-006/38004-005 (BIOS rev. 2.01).
  *
- *  The latest firmware is required in order to get reliable operations when 
+ *  The latest firmware is required in order to get reliable operations when
  *  clustering is enabled. ENABLE_CLUSTERING provides a performance increase
  *  up to 50% on sequential access.
  *
  *  have their BIOS disabled, or enabled to an higher address.
  *  Boards are named Ux4F0, Ux4F1..., according to the port address order in
  *  the io_port[] array.
- *  
+ *
  *  The following facts are based on real testing results (not on
  *  documentation) on the above U14F board.
- *  
- *  - The U14F board should be jumpered for bus on time less or equal to 7 
- *    microseconds, while the default is 11 microseconds. This is order to 
- *    get acceptable performance while using floppy drive and hard disk 
- *    together. The jumpering for 7 microseconds is: JP13 pin 15-16, 
+ *
+ *  - The U14F board should be jumpered for bus on time less or equal to 7
+ *    microseconds, while the default is 11 microseconds. This is order to
+ *    get acceptable performance while using floppy drive and hard disk
+ *    together. The jumpering for 7 microseconds is: JP13 pin 15-16,
  *    JP14 pin 7-8 and pin 9-10.
  *    The reduction has a little impact on scsi performance.
- *  
+ *
  *  - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced
  *    from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8).
  *
  *  - If U14F on board firmware is older than 28004-006/38004-005,
- *    the U14F board is unable to provide reliable operations if the scsi 
+ *    the U14F board is unable to provide reliable operations if the scsi
  *    request length exceeds 16Kbyte. When this length is exceeded the
- *    behavior is: 
+ *    behavior is:
  *    - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94;
  *    - adapter_status equal 0 and target_status equal 2 on for all targets
  *      in the next operation following the reset.
  *    Any reset of the scsi bus is going to kill tape operations, since
  *    no retry is allowed for tapes. Bus resets are more likely when the
  *    scsi bus is under heavy load.
- *    Requests using scatter/gather have a maximum length of 16 x 1024 bytes 
+ *    Requests using scatter/gather have a maximum length of 16 x 1024 bytes
  *    when DISABLE_CLUSTERING is in effect, but unscattered requests could be
  *    larger than 16Kbyte.
  *
  *  in the elevator sorting queue. When the active command completes, the
  *  commands in this queue are sorted by sector address. The sort is chosen
  *  between increasing or decreasing by minimizing the seek distance between
- *  the sector of the commands just completed and the sector of the first 
- *  command in the list to be sorted. 
+ *  the sector of the commands just completed and the sector of the first
+ *  command in the list to be sorted.
  *  Trivial math assures that the unsorted average seek distance when doing
  *  random seeks over S sectors is S/3.
  *  When (Q-1) requests are uniformly distributed over S sectors, the average
  *  distance between two adjacent requests is S/((Q-1) + 1), so the sorted
  *  average seek distance for (Q-1) random requests over S sectors is S/Q.
  *  The elevator sorting hence divides the seek distance by a factor Q/3.
- *  The above pure geometric remarks are valid in all cases and the 
+ *  The above pure geometric remarks are valid in all cases and the
  *  driver effectively reduces the seek distance by the predicted factor
  *  when there are Q concurrent read i/o operations on the device, but this
  *  does not necessarily results in a noticeable performance improvement:
  *
  *  Note: command reordering inside a batch of queued commands could cause
  *        wrong results only if there is at least one write request and the
- *        intersection (sector-wise) of all requests is not empty. 
+ *        intersection (sector-wise) of all requests is not empty.
  *        When the driver detects a batch including overlapping requests
  *        (a really rare event) strict serial (pid) order is enforced.
  *  ----------------------------------------------------------------------------
  *  the driver sets host->wish_block = TRUE for all ISA boards.
  */
 
+#include <linux/version.h>
+
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 #define MAX_INT_PARAM 10
+
 #if defined(MODULE)
 #include <linux/module.h>
-#include <linux/version.h>
+
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26)
 MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i");
 MODULE_PARM(linked_comm, "i");
@@ -279,6 +297,7 @@ MODULE_PARM(link_statistics, "i");
 MODULE_PARM(max_queue_depth, "i");
 MODULE_AUTHOR("Dario Ballabio");
 #endif
+
 #endif
 
 #include <linux/string.h>
@@ -289,6 +308,11 @@ MODULE_AUTHOR("Dario Ballabio");
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+#include <asm/spinlock.h>
+#endif
+
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -339,7 +363,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #undef  DEBUG_RESET
 
 #define MAX_ISA 3
-#define MAX_VESA 1 
+#define MAX_VESA 1
 #define MAX_EISA 0
 #define MAX_PCI 0
 #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
@@ -451,7 +475,7 @@ static char sha[MAX_BOARDS];
 /* Initialize num_boards so that ihdlr can work while detect is in progress */
 static unsigned int num_boards = MAX_BOARDS;
 
-static unsigned long io_port[] __initdata = { 
+static unsigned long io_port[] __initdata = {
 
    /* Space for MAX_INT_PARAM ports usable while loading as a module */
    SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,
@@ -483,7 +507,7 @@ static unsigned long io_port[] __initdata = {
 #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
 #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
 
-static void u14_34f_interrupt_handler(int, void *, struct pt_regs *);
+static void do_interrupt_handler(int, void *, struct pt_regs *);
 static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
 static int do_trace = FALSE;
 static int setup_done = FALSE;
@@ -509,7 +533,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN;
 
 static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
    Scsi_Device *dev;
-   int j, ntag = 0, nuntag = 0, tqd, utqd; 
+   int j, ntag = 0, nuntag = 0, tqd, utqd;
    unsigned long flags;
 
    save_flags(flags);
@@ -626,23 +650,23 @@ __initfunc (static inline int port_detect \
    char *bus_type, dma_name[16];
 
    /* Allowed BIOS base addresses (NULL indicates reserved) */
-   void *bios_segment_table[8] = { 
-      NULL, 
+   void *bios_segment_table[8] = {
+      NULL,
       (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000,
       (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000
       };
-   
+
    /* Allowed IRQs */
    unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
-   
+
    /* Allowed DMA channels for ISA (0 indicates reserved) */
    unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
-   
+
    /* Head/sector mappings */
    struct {
       unsigned char heads;
       unsigned char sectors;
-      } mapping_table[4] = { 
+      } mapping_table[4] = {
            { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
            };
 
@@ -683,7 +707,7 @@ __initfunc (static inline int port_detect \
    subversion = (in_byte & 0x0f);
 
    /* Board detected, allocate its IRQ */
-   if (request_irq(irq, u14_34f_interrupt_handler,
+   if (request_irq(irq, do_interrupt_handler,
              SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
              driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
@@ -786,14 +810,14 @@ __initfunc (static inline int port_detect \
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if (! ((&HD(j)->cp[i])->sglist = kmalloc(
-            sh[j]->sg_tablesize * sizeof(struct sg_list), 
+            sh[j]->sg_tablesize * sizeof(struct sg_list),
             (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
          printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
          u14_34f_release(sh[j]);
          return FALSE;
          }
-      
-   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) 
+
+   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
        max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
 
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
@@ -823,8 +847,8 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) {
 
       if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
 
-      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; 
-   
+      for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
+
       io_port[i] = 0;
       setup_done = TRUE;
       }
@@ -873,7 +897,7 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) {
       if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
       }
 
-   if (j > 0) 
+   if (j > 0)
       printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
 
    num_boards = j;
@@ -905,7 +929,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
-      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 
+      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
       0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
       };
 
@@ -923,16 +947,16 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
 
    if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
-      SCpnt->result = DID_OK << 16; 
+      SCpnt->result = DID_OK << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
              BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 0;
       }
 
-   /* i is the mailbox number, look for the first free mailbox 
+   /* i is the mailbox number, look for the first free mailbox
       starting from last_cp_used */
    i = HD(j)->last_cp_used + 1;
 
@@ -949,17 +973,17 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (k == sh[j]->can_queue) {
       printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
 
-      if (HD(j)->in_reset) 
+      if (HD(j)->in_reset)
          printk("%s: qcomm, already in reset.\n", BN(j));
-      else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) 
-               == SCSI_RESET_SUCCESS) 
+      else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
+               == SCSI_RESET_SUCCESS)
          panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
 
-      SCpnt->result = DID_BUS_BUSY << 16; 
+      SCpnt->result = DID_BUS_BUSY << 16;
       SCpnt->host_scribble = NULL;
       printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
       restore_flags(flags);
-      done(SCpnt);    
+      done(SCpnt);
       return 1;
       }
 
@@ -972,7 +996,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
    if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
-                        BN(j), i, SCpnt->channel, SCpnt->target, 
+                        BN(j), i, SCpnt->channel, SCpnt->target,
                         SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
@@ -1125,7 +1149,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
           BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
           reset_flags);
 
@@ -1186,10 +1210,10 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
       if (SCpnt->host_scribble == NULL)
          panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
 
-      if (*(unsigned int *)SCpnt->host_scribble != i) 
+      if (*(unsigned int *)SCpnt->host_scribble != i)
          panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
 
-      if (SCpnt->scsi_done == NULL) 
+      if (SCpnt->scsi_done == NULL)
          panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
 
       if (SCpnt == SCarg) arg_done = TRUE;
@@ -1283,7 +1307,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
    for (i = 0; i < n - 1; i++) {
       k = i;
 
-      for (j = k + 1; j < n; j++) 
+      for (j = k + 1; j < n; j++)
          if (rev) {
             if (sk[j] > sk[k]) k = j;
             }
@@ -1300,7 +1324,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
    return;
    }
 
-static inline void reorder(unsigned int j, unsigned long cursec,
+static inline int reorder(unsigned int j, unsigned long cursec,
                  unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
    Scsi_Cmnd *SCpnt;
    struct mscp *cpp;
@@ -1309,6 +1333,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
    unsigned int input_only = TRUE, overlap = FALSE;
    unsigned long sl[n_ready], pl[n_ready], ll[n_ready];
    unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0;
+   unsigned long ioseek = 0;
 
    static unsigned int flushcount = 0, batchcount = 0, sortcount = 0;
    static unsigned int readycount = 0, ovlcount = 0, inputcount = 0;
@@ -1319,10 +1344,10 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
              " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
              ovlcount, readycount, readysorted, sortcount, revcount,
-             seeknosort / (readycount + 1), 
+             seeknosort / (readycount + 1),
              seeksorted / (readycount + 1));
 
-   if (n_ready <= 1) return;
+   if (n_ready <= 1) return FALSE;
 
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
@@ -1333,12 +1358,13 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector;
 
       sl[n] = SCpnt->request.sector;
+      ioseek += SCpnt->request.nr_sectors;
 
       if (!n) continue;
 
       if (sl[n] < sl[n - 1]) s = FALSE;
       if (sl[n] > sl[n - 1]) r = FALSE;
-   
+
       if (link_statistics) {
          if (sl[n] > sl[n - 1])
             seek += sl[n] - sl[n - 1];
@@ -1354,6 +1380,8 @@ static inline void reorder(unsigned int j, unsigned long cursec,
 
    if (cursec > ((maxsec + minsec) / 2)) rev = TRUE;
 
+   if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE;
+
    if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev);
 
    if (!input_only) for (n = 0; n < n_ready; n++) {
@@ -1361,7 +1389,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
       ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
 
       if (!n) continue;
+
       if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
           || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
       }
@@ -1370,9 +1398,9 @@ static inline void reorder(unsigned int j, unsigned long cursec,
 
    if (link_statistics) {
       if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
-      batchcount++; readycount += n_ready, seeknosort += seek / 1024; 
+      batchcount++; readycount += n_ready, seeknosort += seek / 1024;
       if (input_only) inputcount++;
-      if (overlap) { ovlcount++; seeksorted += seek / 1024; }
+      if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
       else seeksorted += (iseek + maxsec - minsec) / 1024;
       if (rev && !r)     {  revcount++; readysorted += n_ready; }
       if (!rev && !s)    { sortcount++; readysorted += n_ready; }
@@ -1387,10 +1415,11 @@ static inline void reorder(unsigned int j, unsigned long cursec,
                 (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
                 SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
                 SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
-                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), 
+                YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
                 YESNO(overlap), cpp->xdir);
          }
 #endif
+   return overlap;
 }
 
 static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
@@ -1412,13 +1441,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
       il[n_ready++] = k;
       }
 
-   reorder(j, cursec, ihdlr, il, n_ready);
-  
+   if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
+
    for (n = 0; n < n_ready; n++) {
       k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
 
       if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
-         printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\
+         printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
                 " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
                 SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
          HD(j)->cp_stat[k] = ABORTING;
@@ -1429,34 +1458,43 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
       outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
       HD(j)->cp_stat[k] = IN_USE;
       }
+
 }
 
-static void u14_34f_interrupt_handler(int irq, void *shap,
-                                               struct pt_regs *regs) {
+static inline void ihdlr(int irq, unsigned int j) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, c, status, tstatus, reg, ret;
-   struct mscp *spp;
-
-   /* Check if the interrupt must be processed by this handler */
-   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+   unsigned int i, k, c, status, tstatus, reg, ret;
+   struct mscp *spp, *cpp;
 
    if (sh[j]->irq != irq)
        panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
 
+   /* Check if this board need to be serviced */
+   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+
+   HD(j)->iocount++;
+
    if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
                         HD(j)->iocount);
 
-   /* Check if this board need to be serviced */
-   if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
+   /* Check if this board is still busy */
+   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+      outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
+      printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
+             BN(j), irq, reg, HD(j)->iocount);
+      return;
+      }
 
    spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
+   cpp = spp;
 
    /* Clear interrupt pending flag */
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
-   i = spp - HD(j)->cp;
+   /* Find the mailbox to be serviced on this board */
+   i = cpp - HD(j)->cp;
 
-   if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue
+   if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
                                      || i >= sh[j]->can_queue)
       panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
             (void *)ret, HD(j)->cp);
@@ -1478,21 +1516,22 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
       }
    else if (HD(j)->cp_stat[i] == IN_RESET)
       printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
-   else if (HD(j)->cp_stat[i] != IN_USE) 
-      panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i);
+   else if (HD(j)->cp_stat[i] != IN_USE)
+      panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n",
+            BN(j), i, HD(j)->cp_stat[i]);
 
    HD(j)->cp_stat[i] = FREE;
-   SCpnt = spp->SCpnt;
+   SCpnt = cpp->SCpnt;
 
    if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
 
-   if (SCpnt->host_scribble == NULL) 
+   if (SCpnt->host_scribble == NULL)
       panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
             SCpnt->pid, SCpnt);
 
-   if (*(unsigned int *)SCpnt->host_scribble != i) 
-      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", 
-            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq);
+   if (*(unsigned int *)SCpnt->host_scribble != i)
+      panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
+            BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
 
    if (linked_comm && SCpnt->device->queue_depth > 2
                                      && TLDEV(SCpnt->device->type))
@@ -1504,7 +1543,7 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
       case ASOK:     /* status OK */
 
          /* Forces a reset if a disk drive keeps returning BUSY */
-         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) 
+         if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
             status = DID_ERROR << 16;
 
          /* If there was a bus reset, redo operation on each target */
@@ -1526,7 +1565,7 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
 
          if (spp->target_status && SCpnt->device->type == TYPE_DISK)
             printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
-                   "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                   "target_status 0x%x, sense key 0x%x.\n", BN(j),
                    SCpnt->channel, SCpnt->target, SCpnt->lun,
                    SCpnt->pid, spp->target_status,
                    SCpnt->sense_buffer[2]);
@@ -1553,10 +1592,10 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
       case 0x96:     /* Illegal SCSI command */
       case 0xa3:     /* SCSI bus reset error */
 
-         for (c = 0; c <= sh[j]->max_channel; c++) 
-            for (k = 0; k < sh[j]->max_id; k++) 
+         for (c = 0; c <= sh[j]->max_channel; c++)
+            for (k = 0; k < sh[j]->max_id; k++)
                HD(j)->target_redo[k][c] = TRUE;
-   
+
 
       case 0x92:     /* Data over/under-run */
 
@@ -1566,7 +1605,7 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
             HD(j)->retries++;
             HD(j)->last_retried_pid = SCpnt->pid;
             }
-         else 
+         else
             status = DID_ERROR << 16;
 
          break;
@@ -1583,13 +1622,12 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
       }
 
    SCpnt->result = status | spp->target_status;
-   HD(j)->iocount++;
 
 #if defined (DEBUG_INTERRUPT)
-   if (SCpnt->result || do_trace) 
+   if (SCpnt->result || do_trace)
 #else
    if ((spp->adapter_status != ASOK && HD(j)->iocount >  1000) ||
-       (spp->adapter_status != ASOK && 
+       (spp->adapter_status != ASOK &&
         spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
         do_trace || msg_byte(spp->target_status))
 #endif
@@ -1610,6 +1648,26 @@ static void u14_34f_interrupt_handler(int irq, void *shap,
    return;
 }
 
+static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
+
+   unsigned int j;
+
+   /* Check if the interrupt must be processed by this handler */
+   if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
+
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
+   {
+   unsigned long flags;
+   spin_lock_irqsave(&io_request_lock, flags);
+   ihdlr(irq, j);
+   spin_unlock_irqrestore(&io_request_lock, flags);
+   }
+#else
+   ihdlr(irq, j);
+#endif
+
+}
+
 int u14_34f_release(struct Scsi_Host *shpnt) {
    unsigned long flags;
    unsigned int i, j;
@@ -1618,11 +1676,11 @@ int u14_34f_release(struct Scsi_Host *shpnt) {
    cli();
 
    for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
-    
+
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
 
-   for (i = 0; i < sh[j]->can_queue; i++) 
+   for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
 
    free_irq(sh[j]->irq, &sha[j]);
index 7420b6fc60d2d914d1ba3244c686f14a95258ce4..3c5e4a75cf018527f6a71926e78f274f01a7e4b5 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef _U14_34F_H
 #define _U14_34F_H
 
+#include <linux/version.h>
+
 int u14_34f_detect(Scsi_Host_Template *);
 int u14_34f_release(struct Scsi_Host *);
 int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
@@ -11,7 +13,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "4.02.00"
+#define U14_34F_VERSION "4.20.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
diff --git a/include/linux/modversions.h b/include/linux/modversions.h
deleted file mode 100644 (file)
index 1103f93..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifdef MODVERSIONS
-#undef  CONFIG_MODVERSIONS
-#define CONFIG_MODVERSIONS
-#ifndef _set_ver
-#define _set_ver(sym,vers) sym ## _R ## vers
-#endif
-#include <linux/modules/b1capi.ver>
-#include <linux/modules/b1pci.ver>
-#include <linux/modules/capidrv.ver>
-#include <linux/modules/capiutil.ver>
-#include <linux/modules/fatfs_syms.ver>
-#include <linux/modules/firewall.ver>
-#include <linux/modules/isdn_syms.ver>
-#include <linux/modules/ksyms.ver>
-#include <linux/modules/md.ver>
-#include <linux/modules/misc.ver>
-#include <linux/modules/msdosfs_syms.ver>
-#include <linux/modules/netsyms.ver>
-#include <linux/modules/nls.ver>
-#include <linux/modules/p8022.ver>
-#include <linux/modules/p8022tr.ver>
-#include <linux/modules/ppp.ver>
-#include <linux/modules/procfs_syms.ver>
-#include <linux/modules/psnap.ver>
-#include <linux/modules/scsi_syms.ver>
-#include <linux/modules/serial.ver>
-#include <linux/modules/slhc.ver>
-#include <linux/modules/vfatfs_syms.ver>
-#undef  CONFIG_MODVERSIONS
-#endif
index 9770bdc31a8e2151a1e021547c5923f9427254f1..71351f6e3493241522abeafd930ab1f6676b15d9 100644 (file)
@@ -345,7 +345,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        
        if(len>65535)
        {
-               printk("Oversized IP packet from %s.\n", in_ntoa(qp->iph->saddr));
+               NETDEBUG(printk("Oversized IP packet from %s.\n", in_ntoa(qp->iph->saddr)));
                ip_statistics.IpReasmFails++;
                ip_free(qp);
                return NULL;
index 2badb59eefb4679fd74549e489474d488de6e405..b0544a052fe1fcda6725de85bfd1d801eef058d0 100644 (file)
@@ -166,6 +166,10 @@ int raw_get_info(char *buffer, char **start, off_t offset, int length, int dummy
  */
 int afinet_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
+#ifdef CONFIG_SYN_COOKIES
+       extern unsigned int ui_c_send_cookies;
+       static unsigned int ui_c_last_send_cookies = 0;
+#endif 
        /* From  net/socket.c  */
        extern int socket_get_info(char *, char **, off_t, int);
        extern struct proto packet_prot;
@@ -180,6 +184,13 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length, int du
                       raw_prot.inuse, raw_prot.highestinuse);
        len += sprintf(buffer+len,"PAC: inuse %d highest %d\n",
                       packet_prot.inuse, packet_prot.highestinuse);
+#if defined(CONFIG_SYN_COOKIES)
+       len += sprintf(buffer+len,"SYN_COOKIES: count %u since_last_check %u\n",
+               ui_c_send_cookies, (ui_c_send_cookies - ui_c_last_send_cookies));
+
+       ui_c_last_send_cookies = ui_c_send_cookies;
+#endif
        *start = buffer + offset;
        len -= offset;
        if (len > length)
index 170e1cc6e51fe496129ee5b93438526b959c05fa..da984ab8e9a87d780a65dd39ac927218f6c7fdde 100644 (file)
@@ -216,6 +216,7 @@ void add_clearance(__u32 saddr)
  *     (e.g. long delay packet radio links, 1200 baud modems.)
  */
 static __u32 cookie_mtu[8] = { 64, 256, 512, 536, 1024, 1440, 1460, 4312 };
+unsigned int ui_c_send_cookies = 0;
 #endif
 
 extern void tcp_v4_hash(struct sock *sk);
@@ -594,6 +595,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
 #endif
 #ifdef CONFIG_SYN_COOKIES
                        send_cookie = 1;
+                       ui_c_send_cookies++;
 #else
                        /* If we only have RST cookies we should
                         * not drop through to the rest of the response code.
index 747aaef2cb6ecd84637d63dc1e82ee1505f25c49..45005c073f889e661c18e73275978acc9999d187 100644 (file)
@@ -458,9 +458,9 @@ if [ -f $DEFAULTS ]; then
   echo "# Using defaults found in" $DEFAULTS
   echo "#"
   . $DEFAULTS
-  sed -e 's/# \(.*\) is not.*/\1=n/' < $DEFAULTS > /tmp/conf.$$
-  . /tmp/conf.$$
-  rm /tmp/conf.$$
+  sed -e 's/# \(.*\) is not.*/\1=n/' < $DEFAULTS > .tmp.conf.$$
+  . .tmp.conf.$$
+  rm .tmp.conf.$$
 else
   echo "#"
   echo "# No defaults found"