Return an error instead of STATUS_SUCCESS for functions which are not implemented...
[reactos.git] / reactos / drivers / storage / scsiport / scsiport.c
index 74ae5bd..e37fa9e 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: scsiport.c,v 1.54 2004/04/16 13:39:46 ekohl Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
 #include <ddk/srb.h>
 #include <ddk/scsi.h>
 #include <ddk/ntddscsi.h>
-#include <rosrtl/string.h>
+#include <ddk/ntddstor.h>
+#include <stdio.h>
 
 #define NDEBUG
 #include <debug.h>
 
-
-#define VERSION "0.0.1"
-
 #include "scsiport_int.h"
 
 /* TYPES *********************************************************************/
 #define IRP_FLAG_NEXT          0x00000002
 #define IRP_FLAG_NEXT_LU       0x00000004
 
-#define MAX_SRB_EXTENSIONS     32
-
 /* GLOBALS *******************************************************************/
 
+static ULONG InternalDebugLevel = 0;
+
 static VOID
-SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 
+SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                   PIRP NextIrp);
 
-static VOID 
+static VOID
 SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
           PIRP Irp);
 
@@ -99,7 +97,9 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 
 static NTSTATUS
 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
-               IN OUT PSCSI_REQUEST_BLOCK Srb);
+               IN OUT PSCSI_REQUEST_BLOCK Srb,
+               IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+               IN OUT PKEVENT Event);
 
 static VOID
 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
@@ -113,10 +113,10 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
            IN PVOID ServiceContext);
 
 static VOID STDCALL
-ScsiPortDpcForIsr(IN PKDPC Dpc,
-                 IN PDEVICE_OBJECT DpcDeviceObject,
-                 IN PIRP DpcIrp,
-                 IN PVOID DpcContext);
+ScsiPortDpc(IN PKDPC Dpc,
+           IN PDEVICE_OBJECT DpcDeviceObject,
+           IN PIRP DpcIrp,
+           IN PVOID DpcContext);
 
 static VOID STDCALL
 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
@@ -204,10 +204,8 @@ ScsiDebugPrint(IN ULONG DebugPrintLevel,
   char Buffer[256];
   va_list ap;
 
-#if 0
-  if (DebugPrintLevel > InternalDebugLevel)
+  if (DebugPrintLevel >= InternalDebugLevel)
     return;
-#endif
 
   va_start(ap, DebugMessage);
   vsprintf(Buffer, DebugMessage, ap);
@@ -227,14 +225,56 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
                        IN UCHAR Lun,
                        IN UCHAR SrbStatus)
 {
-  DPRINT("ScsiPortCompleteRequest()\n");
-  UNIMPLEMENTED;
+  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PLIST_ENTRY Entry;
+  PIRP Irp;
+  PSCSI_REQUEST_BLOCK Srb;
+
+  DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
+         HwDeviceExtension, PathId, TargetId, Lun, SrbStatus);
+
+  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                     SCSI_PORT_DEVICE_EXTENSION,
+                                     MiniPortDeviceExtension);
+
+  Entry = DeviceExtension->LunExtensionListHead.Flink;
+  while (Entry != &DeviceExtension->LunExtensionListHead)
+    {
+      LunExtension = CONTAINING_RECORD(Entry,
+                                      SCSI_PORT_LUN_EXTENSION,
+                                      List);
+
+
+
+      if (PathId == (UCHAR)SP_UNTAGGED ||
+         (PathId == LunExtension->PathId && TargetId == (UCHAR)SP_UNTAGGED) ||
+          (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == (UCHAR)SP_UNTAGGED) ||
+          (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == LunExtension->Lun))
+        {
+         Irp = LunExtension->NextIrp;
+         while (Irp)
+           {
+             Srb = (PSCSI_REQUEST_BLOCK)Irp->Tail.Overlay.DriverContext[3];
+             if (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
+               {
+                 Srb->SrbStatus = SrbStatus;
+                 ScsiPortNotification(RequestComplete,
+                                      HwDeviceExtension,
+                                      Srb);
+               }
+              Irp = Irp->Tail.Overlay.DriverContext[1];
+           }
+       }
+      Entry = Entry->Flink;
+    }
 }
 
 
 /*
  * @implemented
  */
+#undef ScsiPortConvertPhysicalAddressToUlong
 ULONG STDCALL
 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
 {
@@ -346,7 +386,7 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
 
   MappedAddress = MmMapIoSpace(TranslatedAddress,
                               NumberOfBytes,
-                              FALSE);
+                              MmNonCached);
 
   DeviceBase = ExAllocatePool(NonPagedPool,
                              sizeof(SCSI_PORT_DEVICE_BASE));
@@ -433,73 +473,83 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
                                      SCSI_PORT_DEVICE_EXTENSION,
                                      MiniPortDeviceExtension);
 
-  *Length = 0;
-
+  if (Length != NULL)
+    {
+      *Length = 0;
+    }
   if (Srb == NULL)
     {
-      if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
-       {
-         PhysicalAddress.QuadPart = 0ULL;
-         return PhysicalAddress;
+      EndAddress = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + DeviceExtension->CommonBufferLength);
+      if (VirtualAddress >= DeviceExtension->VirtualAddress && VirtualAddress < EndAddress)
+        {
+         Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
+         PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
+          BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
        }
-
-      Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
-      if (Offset >= DeviceExtension->CommonBufferLength)
-       {
-         PhysicalAddress.QuadPart = 0ULL;
-         return PhysicalAddress;
+      else
+        {
+         /*
+          * The given virtual address is not within the range
+          * of the drivers uncached extension or srb extension.
+          */
+         /*
+          * FIXME:
+          *   Check if the address is a sense info buffer of an active srb.
+          */
+         PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
+         if (PhysicalAddress.QuadPart == 0LL)
+           {
+             CHECKPOINT;
+             return PhysicalAddress;
+           }
+         BufferLength = PAGE_SIZE - PhysicalAddress.u.LowPart % PAGE_SIZE;
        }
-
-      PhysicalAddress.QuadPart =
-       DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
-      BufferLength = DeviceExtension->CommonBufferLength - Offset;
     }
   else
     {
-      EndAddress = Srb->DataBuffer + Srb->DataTransferLength;
+      EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
       if (VirtualAddress == NULL)
        {
          VirtualAddress = Srb->DataBuffer;
        }
       else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
        {
-         PhysicalAddress.QuadPart = 0LL;
-         return PhysicalAddress;
+         EndAddress = (PVOID)((ULONG_PTR)Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength);
+         if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
+           {
+             PhysicalAddress.QuadPart = 0LL;
+             CHECKPOINT;
+             return PhysicalAddress;
+           }
        }
 
       PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
       if (PhysicalAddress.QuadPart == 0LL)
        {
+         CHECKPOINT;
          return PhysicalAddress;
        }
 
-      Offset = (ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1);
-#if 1
-      /* 
-       * FIXME:
-       *   MmGetPhysicalAddress doesn't return the offset within the page.
-       *   We must set the correct offset.
-       */
-      PhysicalAddress.u.LowPart = (PhysicalAddress.u.LowPart & ~(PAGE_SIZE - 1)) + Offset;
-#endif
-      BufferLength += PAGE_SIZE - Offset;
-      while (VirtualAddress + BufferLength < EndAddress)
+      BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
+      while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
        {
-         NextPhysicalAddress = MmGetPhysicalAddress(VirtualAddress + BufferLength);
-         if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
+         NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
+         if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
            {
              break;
            }
          BufferLength += PAGE_SIZE;
        }
-      if (VirtualAddress + BufferLength >= EndAddress)
+      if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
        {
-         BufferLength = EndAddress - VirtualAddress;
+         BufferLength = (ULONG)((ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress);
        }
     }
-
-  *Length = BufferLength;
-
+  if (Length != NULL)
+    {
+      *Length = BufferLength;
+    }
+  DPRINT("Address %I64x, Length %d\n", PhysicalAddress.QuadPart, BufferLength);
   return PhysicalAddress;
 }
 
@@ -508,7 +558,7 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
  * @unimplemented
  */
 PSCSI_REQUEST_BLOCK STDCALL
-ScsiPortGetSrb(IN PVOID DeviceExtension,
+ScsiPortGetSrb(IN PVOID HwDeviceExtension,
               IN UCHAR PathId,
               IN UCHAR TargetId,
               IN UCHAR Lun,
@@ -573,16 +623,36 @@ ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
          return NULL;
        }
     }
+  if (DeviceExtension->SrbExtensionSize > 0)
+    {
+      PVOID Buffer;
+      DeviceExtension->CurrentSrbExtensions = 0;
+      if (DeviceExtension->PortConfig->MultipleRequestPerLu)
+        {
+          DeviceExtension->MaxSrbExtensions = 1024;
+       }
+      else
+        {
+         DeviceExtension->MaxSrbExtensions = 32;
+       }
+      Buffer = ExAllocatePool(NonPagedPool, ROUND_UP(DeviceExtension->MaxSrbExtensions / 8, sizeof(ULONG)));
+      if (Buffer == NULL)
+        {
+          KEBUGCHECK(0);
+          return NULL;
+        }
+      RtlInitializeBitMap(&DeviceExtension->SrbExtensionAllocMap, Buffer, DeviceExtension->MaxSrbExtensions);
+      RtlClearAllBits(&DeviceExtension->SrbExtensionAllocMap);
+    }
 
   /* Allocate a common DMA buffer */
   DeviceExtension->CommonBufferLength =
-    NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * MAX_SRB_EXTENSIONS);
+    NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions);
   DeviceExtension->VirtualAddress =
     HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
                            DeviceExtension->CommonBufferLength,
                            &DeviceExtension->PhysicalAddress,
                            FALSE);
-  DeviceExtension->VirtualAddressMap = 0;
   if (DeviceExtension->VirtualAddress == NULL)
     {
       DPRINT1("HalAllocateCommonBuffer() failed!\n");
@@ -591,7 +661,7 @@ ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
     }
 
   return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
-                 PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * MAX_SRB_EXTENSIONS));
+                 PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions));
 }
 
 
@@ -686,7 +756,33 @@ ScsiPortInitialize(IN PVOID Argument1,
 
 
   DPRINT ("ScsiPortInitialize() called!\n");
-
+#if 0
+  DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData->HwInitializationDataSize);
+  DPRINT1("AdapterInterfaceType:     %d\n", HwInitializationData->AdapterInterfaceType);
+  DPRINT1("HwInitialize:             %x\n", HwInitializationData->HwInitialize);
+  DPRINT1("HwStartIo:                %x\n", HwInitializationData->HwStartIo);
+  DPRINT1("HwInterrupt:              %x\n", HwInitializationData->HwInterrupt);
+  DPRINT1("HwFindAdapter:            %x\n", HwInitializationData->HwFindAdapter);
+  DPRINT1("HwResetBus:               %x\n", HwInitializationData->HwResetBus);
+  DPRINT1("HwDmaStarted:             %x\n", HwInitializationData->HwDmaStarted);
+  DPRINT1("HwAdapterState:           %x\n", HwInitializationData->HwAdapterState);
+  DPRINT1("DeviceExtensionSize:      %d\n", HwInitializationData->DeviceExtensionSize);
+  DPRINT1("SpecificLuExtensionSize:  %d\n", HwInitializationData->SpecificLuExtensionSize);
+  DPRINT1("SrbExtensionSize:         %d\n", HwInitializationData->SrbExtensionSize);
+  DPRINT1("NumberOfAccessRanges:     %d\n", HwInitializationData->NumberOfAccessRanges);
+  DPRINT1("Reserved:                 %x\n", HwInitializationData->Reserved);
+  DPRINT1("MapBuffers:               %d\n", HwInitializationData->MapBuffers);
+  DPRINT1("NeedPhysicalAddresses:    %d\n", HwInitializationData->NeedPhysicalAddresses);
+  DPRINT1("TaggedQueueing:           %d\n", HwInitializationData->TaggedQueueing);
+  DPRINT1("AutoRequestSense:         %d\n", HwInitializationData->AutoRequestSense);
+  DPRINT1("MultipleRequestPerLu:     %d\n", HwInitializationData->MultipleRequestPerLu);
+  DPRINT1("ReceiveEvent:             %d\n", HwInitializationData->ReceiveEvent);
+  DPRINT1("VendorIdLength:           %d\n", HwInitializationData->VendorIdLength);
+  DPRINT1("VendorId:                 %x\n", HwInitializationData->VendorId);
+  DPRINT1("ReservedUshort:           %d\n", HwInitializationData->ReservedUshort);
+  DPRINT1("DeviceIdLength:           %d\n", HwInitializationData->DeviceIdLength);
+  DPRINT1("DeviceId:                 %x\n", HwInitializationData->DeviceId);
+#endif
   if ((HwInitializationData->HwInitialize == NULL) ||
       (HwInitializationData->HwStartIo == NULL) ||
       (HwInitializationData->HwInterrupt == NULL) ||
@@ -704,7 +800,7 @@ ScsiPortInitialize(IN PVOID Argument1,
 
   DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
     HwInitializationData->DeviceExtensionSize;
-  PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) + 
+  PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
     HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
 
 
@@ -758,20 +854,18 @@ ScsiPortInitialize(IN PVOID Argument1,
       DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
       DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
 
-#if 0
       DeviceExtension->AdapterObject = NULL;
       DeviceExtension->MapRegisterCount = 0;
       DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
       DeviceExtension->VirtualAddress = NULL;
       DeviceExtension->CommonBufferLength = 0;
-#endif
 
       /* Initialize the device base list */
       InitializeListHead (&DeviceExtension->DeviceBaseListHead);
 
       /* Initialize the irp lists */
       InitializeListHead (&DeviceExtension->PendingIrpListHead);
-      InitializeListHead (&DeviceExtension->ActiveIrpListHead);
+      DeviceExtension->NextIrp = NULL;
       DeviceExtension->PendingIrpCount = 0;
       DeviceExtension->ActiveIrpCount = 0;
 
@@ -779,12 +873,11 @@ ScsiPortInitialize(IN PVOID Argument1,
       InitializeListHead (&DeviceExtension->LunExtensionListHead);
 
       /* Initialize the spin lock in the controller extension */
-      KeInitializeSpinLock (&DeviceExtension->IrpLock);
-      KeInitializeSpinLock (&DeviceExtension->SpinLock);
+      KeInitializeSpinLock (&DeviceExtension->Lock);
 
       /* Initialize the DPC object */
       IoInitializeDpcRequest (PortDeviceObject,
-                             ScsiPortDpcForIsr);
+                             ScsiPortDpc);
 
       /* Initialize the device timer */
       DeviceExtension->TimerState = IDETimerIdle;
@@ -814,40 +907,38 @@ ScsiPortInitialize(IN PVOID Argument1,
       PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
       PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
       PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
-//  PortConfig->DmaWidth =
-//  PortConfig->DmaSpeed =
-//  PortConfig->AlignmentMask =
+      PortConfig->DmaWidth = 0;
+      PortConfig->DmaSpeed = Compatible;
+      PortConfig->AlignmentMask = 0;
       PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
-//  PortConfig->NumberOfBuses =
+      PortConfig->NumberOfBuses = 0;
 
       for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
        PortConfig->InitiatorBusId[i] = 255;
 
-//  PortConfig->ScatterGather =
-//  PortConfig->Master =
-//  PortConfig->CachesData =
-//  PortConfig->AdapterScansDown =
+      PortConfig->ScatterGather = FALSE;
+      PortConfig->Master = FALSE;
+      PortConfig->CachesData = FALSE;
+      PortConfig->AdapterScansDown = FALSE;
       PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
       PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
-//  PortConfig->Dma32BitAddresses =
-//  PortConfig->DemandMode =
+      PortConfig->Dma32BitAddresses = FALSE;
+      PortConfig->DemandMode = FALSE;
       PortConfig->MapBuffers = HwInitializationData->MapBuffers;
       PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
-      PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing;
+      PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
       PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
       PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
       PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
-//  PortConfig->RealModeInitialized =
-//  PortConfig->BufferAccessScsiPortControlled =
+      PortConfig->RealModeInitialized = FALSE;
+      PortConfig->BufferAccessScsiPortControlled = FALSE;
       PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
-//  PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
+//      PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
 
-    PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
-    PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
+      PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
+      PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
 
-      PortConfig->SlotNumber = SlotNumber.u.AsULONG;
-
-      PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
+      PortConfig->AccessRanges = (ACCESS_RANGE(*)[])(PortConfig + 1);
 
       /* Search for matching PCI device */
       if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
@@ -889,6 +980,51 @@ ScsiPortInitialize(IN PVOID Argument1,
        {
          DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
 
+#if 0
+         DPRINT1("SystemIoBusNumber:               %x\n", PortConfig->SystemIoBusNumber);
+         DPRINT1("AdapterInterfaceType:            %x\n", PortConfig->AdapterInterfaceType);
+         DPRINT1("BusInterruptLevel:               %x\n", PortConfig->BusInterruptLevel);
+         DPRINT1("BusInterruptVector:              %x\n", PortConfig->BusInterruptVector);
+         DPRINT1("InterruptMode:                   %x\n", PortConfig->InterruptMode);
+         DPRINT1("MaximumTransferLength:           %x\n", PortConfig->MaximumTransferLength);
+         DPRINT1("NumberOfPhysicalBreaks:          %x\n", PortConfig->NumberOfPhysicalBreaks);
+         DPRINT1("DmaChannel:                      %x\n", PortConfig->DmaChannel);
+         DPRINT1("DmaPort:                         %d\n", PortConfig->DmaPort);
+         DPRINT1("DmaWidth:                        %d\n", PortConfig->DmaWidth);
+         DPRINT1("DmaSpeed:                        %d\n", PortConfig->DmaSpeed);
+         DPRINT1("AlignmentMask:                   %d\n", PortConfig->AlignmentMask);
+         DPRINT1("NumberOfAccessRanges:            %d\n", PortConfig->NumberOfAccessRanges);
+         DPRINT1("NumberOfBuses:                   %d\n", PortConfig->NumberOfBuses);
+         DPRINT1("ScatterGather:                   %d\n", PortConfig->ScatterGather);
+         DPRINT1("Master:                          %d\n", PortConfig->Master);
+         DPRINT1("CachesData:                      %d\n", PortConfig->CachesData);
+         DPRINT1("AdapterScansDown:                %d\n", PortConfig->AdapterScansDown);
+         DPRINT1("AtdiskPrimaryClaimed:            %d\n", PortConfig->AtdiskPrimaryClaimed);
+         DPRINT1("AtdiskSecondaryClaimed:          %d\n", PortConfig->AtdiskSecondaryClaimed);
+         DPRINT1("Dma32BitAddresses:               %d\n", PortConfig->Dma32BitAddresses);
+         DPRINT1("DemandMode:                      %d\n", PortConfig->DemandMode);
+         DPRINT1("MapBuffers:                      %d\n", PortConfig->MapBuffers);
+         DPRINT1("NeedPhysicalAddresses:           %d\n", PortConfig->NeedPhysicalAddresses);
+         DPRINT1("TaggedQueuing:                   %d\n", PortConfig->TaggedQueuing);
+         DPRINT1("AutoRequestSense:                %d\n", PortConfig->AutoRequestSense);
+         DPRINT1("MultipleRequestPerLu:            %d\n", PortConfig->MultipleRequestPerLu);
+         DPRINT1("ReceiveEvent:                    %d\n", PortConfig->ReceiveEvent);
+         DPRINT1("RealModeInitialized:             %d\n", PortConfig->RealModeInitialized);
+         DPRINT1("BufferAccessScsiPortControlled:  %d\n", PortConfig->BufferAccessScsiPortControlled);
+         DPRINT1("MaximumNumberOfTargets:          %d\n", PortConfig->MaximumNumberOfTargets);
+         DPRINT1("SlotNumber:                      %d\n", PortConfig->SlotNumber);
+         DPRINT1("BusInterruptLevel2:              %x\n", PortConfig->BusInterruptLevel2);
+         DPRINT1("BusInterruptVector2:             %x\n", PortConfig->BusInterruptVector2);
+         DPRINT1("InterruptMode2:                  %x\n", PortConfig->InterruptMode2);
+         DPRINT1("DmaChannel2:                     %d\n", PortConfig->DmaChannel2);
+         DPRINT1("DmaPort2:                        %d\n", PortConfig->DmaPort2);
+         DPRINT1("DmaWidth2:                       %d\n", PortConfig->DmaWidth2);
+         DPRINT1("DmaSpeed2:                       %d\n", PortConfig->DmaSpeed2);
+         DPRINT1("DeviceExtensionSize:             %d\n", PortConfig->DeviceExtensionSize);
+         DPRINT1("SpecificLuExtensionSize:         %d\n", PortConfig->SpecificLuExtensionSize);
+         DPRINT1("SrbExtensionSize:                %d\n", PortConfig->SrbExtensionSize);
+
+#endif
 
           if (DeviceExtension->VirtualAddress == NULL && DeviceExtension->SrbExtensionSize)
            {
@@ -896,17 +1032,17 @@ ScsiPortInitialize(IN PVOID Argument1,
                                           PortConfig,
                                           0);
            }
-             
+
          /* Register an interrupt handler for this device */
          MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
                                            PortConfig->SystemIoBusNumber,
                                            PortConfig->BusInterruptLevel,
 #if 1
-/* 
+/*
  * FIXME:
- *   Something is wrong in our interrupt conecting code. 
+ *   Something is wrong in our interrupt conecting code.
  *   The promise Ultra100TX driver returns 0 for BusInterruptVector
- *   and a nonzero value for BusInterruptLevel. The driver does only 
+ *   and a nonzero value for BusInterruptLevel. The driver does only
  *   work with this fix.
  */
                                            PortConfig->BusInterruptLevel,
@@ -916,12 +1052,12 @@ ScsiPortInitialize(IN PVOID Argument1,
                                            &Dirql,
                                            &Affinity);
          DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
-                 PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber, 
-                 PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector); 
+                 PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
+                 PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector);
          Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
                                      ScsiPortIsr,
                                      DeviceExtension,
-                                     &DeviceExtension->SpinLock,
+                                     NULL,
                                      MappedIrq,
                                      Dirql,
                                      Dirql,
@@ -955,8 +1091,19 @@ ScsiPortInitialize(IN PVOID Argument1,
 
          PortCapabilities = DeviceExtension->PortCapabilities;
          PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
-         PortCapabilities->MaximumTransferLength =
-           PortConfig->MaximumTransferLength;
+          if (PortConfig->ScatterGather == FALSE ||
+             PortConfig->NumberOfPhysicalBreaks >= (0x100000000LL >> PAGE_SHIFT) ||
+             PortConfig->MaximumTransferLength < PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE)
+           {
+             PortCapabilities->MaximumTransferLength =
+               PortConfig->MaximumTransferLength;
+           }
+         else
+           {
+             PortCapabilities->MaximumTransferLength =
+               PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE;
+           }
+
          PortCapabilities->MaximumPhysicalPages =
            PortCapabilities->MaximumTransferLength / PAGE_SIZE;
          PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
@@ -1075,6 +1222,8 @@ ScsiPortLogError(IN PVOID HwDeviceExtension,
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
 
   DPRINT1("ScsiPortLogError() called\n");
+  DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
+          Srb, PathId, TargetId, Lun, ErrorCode, UniqueId);
 
   DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
                                      SCSI_PORT_DEVICE_EXTENSION,
@@ -1129,16 +1278,14 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
          Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
 
          DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
-         DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
+         DeviceExtension->Flags |= IRP_FLAG_COMPLETE;
          Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
-         InterlockedIncrement((PLONG)&DeviceExtension->CompleteRequestCount);
        }
        break;
 
       case NextRequest:
        DPRINT("Notify: NextRequest\n");
-       DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
-       InterlockedIncrement((PLONG)&DeviceExtension->NextRequestCount);
+       DeviceExtension->Flags |= IRP_FLAG_NEXT;
        break;
 
       case NextLuRequest:
@@ -1161,9 +1308,8 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
                                            Lun);
          if (LunExtension)
            {
-             DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
-             InterlockedIncrement((PLONG)&LunExtension->NextLuRequestCount);
-             InterlockedIncrement((PLONG)&DeviceExtension->NextLuRequestCount);
+             DeviceExtension->Flags |= IRP_FLAG_NEXT_LU;
+             LunExtension->Flags |= IRP_FLAG_NEXT_LU;
            }
        }
        break;
@@ -1177,6 +1323,16 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
        DPRINT1 ("Unsupported notification %lu\n", NotificationType);
        break;
     }
+  if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
+    {
+      IoRequestDpc(DeviceExtension->DeviceObject,
+                   NULL,
+                  DeviceExtension);
+    }
+  else
+    {
+      SpiProcessRequests(DeviceExtension, NULL);
+    }
 
   va_end(ap);
 }
@@ -1303,9 +1459,9 @@ SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
 
                  for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
                    {
-                     PortConfig->AccessRanges[i].RangeStart.QuadPart =
+                     (*PortConfig->AccessRanges)[i].RangeStart.QuadPart =
                        PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
-                     if (PortConfig->AccessRanges[i].RangeStart.QuadPart != 0)
+                     if ((*PortConfig->AccessRanges)[i].RangeStart.QuadPart != 0)
                        {
                          RangeLength = (ULONG)-1;
                          HalSetBusDataByOffset (PCIConfiguration,
@@ -1330,9 +1486,9 @@ SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
                                                 sizeof(ULONG));
                          if (RangeLength != 0)
                            {
-                             PortConfig->AccessRanges[i].RangeLength =
+                             (*PortConfig->AccessRanges)[i].RangeLength =
                                -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
-                             PortConfig->AccessRanges[i].RangeInMemory =
+                             (*PortConfig->AccessRanges)[i].RangeInMemory =
                                !(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
 
                              DPRINT("RangeStart 0x%lX  RangeLength 0x%lX  RangeInMemory %s\n",
@@ -1345,7 +1501,11 @@ SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
                }
 
              NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
-             NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
+             NextSlotNumber->u.bits.FunctionNumber = FunctionNumber;
+
+              PortConfig->SlotNumber = NextSlotNumber->u.AsULONG;
+
+             NextSlotNumber->u.bits.FunctionNumber += 1;
 
              return TRUE;
            }
@@ -1551,10 +1711,10 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
 {
   PIO_STACK_LOCATION Stack;
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status = STATUS_SUCCESS;
 
   DPRINT("ScsiPortDeviceControl()\n");
 
-  Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0;
 
 
@@ -1569,7 +1729,7 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
          DPRINT("  IOCTL_SCSI_GET_DUMP_POINTERS\n");
          DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
          DumpPointers->DeviceObject = DeviceObject;
-         
+
          Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
        }
        break;
@@ -1596,59 +1756,75 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
          DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
        }
        break;
+      
+      case IOCTL_SCSI_PASS_THROUGH:
+        DPRINT("  IOCTL_SCSI_PASS_THROUGH\n");
+        Status = STATUS_NOT_IMPLEMENTED;
+        break;
+
+      case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+        DPRINT("  IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
+        Status = STATUS_NOT_IMPLEMENTED;
+        break;
+
+      case IOCTL_SCSI_MINIPORT:
+        DPRINT1("  IOCTL_SCSI_MINIPORT\n");
+        DPRINT1("  Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
+        DPRINT1("  ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
+        Status = STATUS_INVALID_DEVICE_REQUEST;
+        break;
 
       default:
        DPRINT1("  unknown ioctl code: 0x%lX\n",
               Stack->Parameters.DeviceIoControl.IoControlCode);
+        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
     }
 
+  Irp->IoStatus.Status = Status;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-  return(STATUS_SUCCESS);
+  return Status;
 }
 
-static VOID 
+static VOID
 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                        PSCSI_REQUEST_BLOCK Srb)
 {
-  ULONG i;
-  ULONG mask;
+  ULONG index;
 
   DPRINT("SpiAllocateSrbExtension\n");
 
-  DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n", 
+  DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
          DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
 
+  Srb->SrbExtension = NULL;
   if (DeviceExtension->VirtualAddress != NULL &&
       DeviceExtension->SrbExtensionSize > 0)
     {
-      for (i = 0, mask = 1; i < MAX_SRB_EXTENSIONS; i++, mask <<= 1)
+      index = RtlFindClearBitsAndSet(&DeviceExtension->SrbExtensionAllocMap, 1, 0);
+      if (index != 0xffffffff)
         {
-         if (!(DeviceExtension->VirtualAddressMap & mask))
-           {
-             DeviceExtension->VirtualAddressMap |= mask;
-             Srb->SrbExtension = DeviceExtension->VirtualAddress + i * DeviceExtension->SrbExtensionSize;
-              DPRINT("%x\n", Srb->SrbExtension);
-             return;
-           }
+         DeviceExtension->CurrentSrbExtensions++;
+          Srb->SrbExtension = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + index * DeviceExtension->SrbExtensionSize);
        }
     }
-  Srb->SrbExtension = NULL;
+  DPRINT("%x\n", Srb->SrbExtension);
 }
 
 static VOID
 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                    PSCSI_REQUEST_BLOCK Srb)
 {
-  ULONG i;
+  ULONG index;
 
   if (DeviceExtension->VirtualAddress != NULL &&
       DeviceExtension->SrbExtensionSize > 0 &&
       Srb->SrbExtension != NULL)
     {
-      i = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
-      DeviceExtension->VirtualAddressMap &= ~(1 << i);
+      index = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
+      RtlClearBits(&DeviceExtension->SrbExtensionAllocMap, index, 1);
+      DeviceExtension->CurrentSrbExtensions--;
     }
   Srb->SrbExtension = NULL;
 }
@@ -1662,8 +1838,8 @@ ScsiPortStartPacket(IN OUT PVOID Context)
   PIRP Irp;
   PIO_STACK_LOCATION IrpStack;
 
-  DPRINT("ScsiPortStartPacket() called\n");
-  
+  DPRINT("ScsiPortStartPacket(Context %x) called\n", Context);
+
   Srb = (PSCSI_REQUEST_BLOCK)Context;
   Irp = (PIRP)Srb->OriginalRequest;
   IrpStack = IoGetCurrentIrpStackLocation(Irp);
@@ -1710,6 +1886,8 @@ SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
   LunExtension->PendingIrpCount = 0;
   LunExtension->ActiveIrpCount = 0;
 
+  LunExtension->NextIrp = NULL;
+
   return LunExtension;
 }
 
@@ -1772,20 +1950,16 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 
 static NTSTATUS
 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
-               IN OUT PSCSI_REQUEST_BLOCK Srb)
+               IN OUT PSCSI_REQUEST_BLOCK Srb,
+               IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+               IN OUT PKEVENT Event)
 {
-  IO_STATUS_BLOCK IoStatusBlock;
   PIO_STACK_LOCATION IrpStack;
-  PKEVENT Event;
   PIRP Irp;
   NTSTATUS Status;
 
   DPRINT ("SpiSendInquiry() called\n");
 
-  Event = ExAllocatePool (NonPagedPool,
-                         sizeof(KEVENT));
-  if (Event == NULL)
-    return STATUS_INSUFFICIENT_RESOURCES;
 
   KeInitializeEvent (Event,
                     NotificationEvent,
@@ -1799,11 +1973,10 @@ SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
                                       Srb->DataTransferLength,
                                       TRUE,
                                       Event,
-                                      &IoStatusBlock);
+                                      IoStatusBlock);
   if (Irp == NULL)
     {
       DPRINT("IoBuildDeviceIoControlRequest() failed\n");
-      ExFreePool (Event);
       return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -1815,101 +1988,160 @@ SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
   /* Call the driver */
   Status = IoCallDriver (DeviceObject,
                         Irp);
-  if (Status == STATUS_PENDING)
-    {
-      KeWaitForSingleObject (Event,
-                            Suspended,
-                            KernelMode,
-                            FALSE,
-                            NULL);
-      Status = IoStatusBlock.Status;
-    }
-
-  ExFreePool (Event);
 
   return Status;
 }
 
-
 static VOID
 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 {
-  PSCSI_PORT_LUN_EXTENSION LunExtension;
-  SCSI_REQUEST_BLOCK Srb;
+  PSCSI_REQUEST_BLOCK Srb;
   PCDB Cdb;
   ULONG Bus;
   ULONG Target;
-  ULONG Lun;
-  NTSTATUS Status;
+  PSCSI_PORT_SCAN_ADAPTER ScanDataArray;
+  PSCSI_PORT_SCAN_ADAPTER ScanData;
+  ULONG i;
+  ULONG MaxCount;
+  ULONG WaitCount;
+  ULONG ActiveCount;
+  PVOID* EventArray;
+  PKWAIT_BLOCK WaitBlockArray;
 
   DPRINT ("SpiScanAdapter() called\n");
 
-  RtlZeroMemory(&Srb,
-               sizeof(SCSI_REQUEST_BLOCK));
-  Srb.SrbFlags = SRB_FLAGS_DATA_IN;
-  Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
-  Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-  Srb.DataTransferLength = 255; //256;
-  Srb.CdbLength = 6;
+  MaxCount = DeviceExtension->PortConfig->NumberOfBuses *
+               DeviceExtension->PortConfig->MaximumNumberOfTargets;
 
-  Cdb = (PCDB) &Srb.Cdb;
-
-  Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
-  Cdb->CDB6INQUIRY.AllocationLength = 255;
+  ScanDataArray = ExAllocatePool(NonPagedPool, MaxCount * (sizeof(SCSI_PORT_SCAN_ADAPTER) + sizeof(PVOID) + sizeof(KWAIT_BLOCK)));
+  if (ScanDataArray == NULL)
+    {
+      return;
+    }
+  EventArray = (PVOID*)((PUCHAR)ScanDataArray + MaxCount * sizeof(SCSI_PORT_SCAN_ADAPTER));
+  WaitBlockArray = (PKWAIT_BLOCK)((PUCHAR)EventArray + MaxCount * sizeof(PVOID));
 
   for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
     {
-      Srb.PathId = Bus;
-
       for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
        {
-         Srb.TargetId = Target;
-
-         for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
-           {
-             Srb.Lun = Lun;
-             Srb.SrbStatus = SRB_STATUS_SUCCESS;
-
-             Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
-
-             RtlZeroMemory(Srb.DataBuffer, 256);
-
-             LunExtension = SpiAllocateLunExtension (DeviceExtension,
-                                                     Bus,
-                                                     Target,
-                                                     Lun);
-             if (LunExtension == NULL)
-               {
-                 DPRINT("Failed to allocate the LUN extension!\n");
-                 ExFreePool(Srb.DataBuffer);
-                 return;
+         ScanData = &ScanDataArray[Bus * DeviceExtension->PortConfig->MaximumNumberOfTargets + Target];
+         ScanData->Bus = Bus;
+         ScanData->Target = Target;
+         ScanData->Lun = 0;
+         ScanData->Active = FALSE;
+       }
+    }
+  do
+    {
+      ActiveCount = 0;
+      WaitCount = 0;
+      for (i = 0; i < MaxCount; i++)
+        {
+          ScanData = &ScanDataArray[i];
+         Srb = &ScanData->Srb;
+          if (ScanData->Active)
+            {
+             if (ScanData->Status == STATUS_PENDING &&
+                 0 == KeReadStateEvent(&ScanData->Event))
+               {
+                 ActiveCount++;
+                 continue;
                }
-
-             Status = SpiSendInquiry (DeviceExtension->DeviceObject,
-                                      &Srb);
-             DPRINT ("Target %lu  Lun %lu", Target, Lun);
-             DPRINT ("Status %lx  Srb.SrbStatus %x\n", Status, Srb.SrbStatus);
-             DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA)Srb.DataBuffer)->DeviceTypeQualifier);
-
-             if (NT_SUCCESS(Status) &&
-                 (Srb.SrbStatus == SRB_STATUS_SUCCESS ||
-                  Srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) &&
-                 ((PINQUIRYDATA)Srb.DataBuffer)->DeviceTypeQualifier == 0)
+             else
+               {
+                  ScanData->Status = ScanData->IoStatusBlock.Status;
+               }
+             ScanData->Active = FALSE;
+             DPRINT ("Target %lu  Lun %lu\n", ScanData->Target, ScanData->Lun);
+             DPRINT ("Status %lx  Srb.SrbStatus %x\n", ScanData->Status, Srb->SrbStatus);
+             DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier);
+
+             if (NT_SUCCESS(ScanData->Status) &&
+                 (Srb->SrbStatus == SRB_STATUS_SUCCESS ||
+                  (Srb->SrbStatus == SRB_STATUS_DATA_OVERRUN &&
+                  /*
+                   * FIXME:
+                   *   The NT 4.0 driver from an inic950 based scsi controller
+                   *   returns only 4 byte of inquiry data, but the device name
+                   *   is visible on NT 4.0. We must implement an other way
+                   *   to get the complete inquiry data.
+                   */
+                   Srb->DataTransferLength >= /*INQUIRYDATABUFFERSIZE*/4)) &&
+                 ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier == 0)
                {
                  /* Copy inquiry data */
-                 RtlCopyMemory (&LunExtension->InquiryData,
-                                Srb.DataBuffer,
-                                sizeof(INQUIRYDATA));
+                 RtlCopyMemory (&ScanData->LunExtension->InquiryData,
+                                Srb->DataBuffer,
+                                min(sizeof(INQUIRYDATA), Srb->DataTransferLength));
+                 ScanData->Lun++;
                }
              else
                {
-                 SpiRemoveLunExtension (LunExtension);
+                 SpiRemoveLunExtension (ScanData->LunExtension);
+                 ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
                }
            }
+          if (ScanData->Lun >= SCSI_MAXIMUM_LOGICAL_UNITS)
+            {
+             continue;
+           }
+          RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+          Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+          Srb->DataBuffer = ScanData->DataBuffer;
+          Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+          Srb->DataTransferLength = 255; //256;
+          Srb->CdbLength = 6;
+          Srb->Lun = ScanData->Lun;
+          Srb->PathId = ScanData->Bus;
+          Srb->TargetId = ScanData->Target;
+          Srb->SrbStatus = SRB_STATUS_SUCCESS;
+         Srb->TimeOutValue = 2;
+          Cdb = (PCDB) &Srb->Cdb;
+
+          Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+          Cdb->CDB6INQUIRY.AllocationLength = 255;
+          Cdb->CDB6INQUIRY.LogicalUnitNumber = ScanData->Lun;
+
+          RtlZeroMemory(Srb->DataBuffer, 256);
+
+          ScanData->LunExtension = SpiAllocateLunExtension (DeviceExtension,
+                                                           ScanData->Bus,
+                                                           ScanData->Target,
+                                                           ScanData->Lun);
+          if (ScanData->LunExtension == NULL)
+           {
+             DPRINT1("Failed to allocate the LUN extension!\n");
+             ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
+             continue;
+           }
+          ScanData->Status = SpiSendInquiry (DeviceExtension->DeviceObject,
+                                            Srb,
+                                            &ScanData->IoStatusBlock,
+                                            &ScanData->Event);
+         ScanData->Active = TRUE;
+         ActiveCount++;
+         if (ScanData->Status == STATUS_PENDING)
+           {
+              EventArray[WaitCount] = &ScanData->Event;
+              WaitCount++;
+            }
+       }
+      if (WaitCount > 0 && WaitCount == ActiveCount)
+        {
+          KeWaitForMultipleObjects(WaitCount,
+                                   EventArray,
+                                  WaitAny,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL,
+                                  WaitBlockArray);
        }
     }
+  while (ActiveCount > 0);
 
-  ExFreePool(Srb.DataBuffer);
+  ExFreePool(ScanDataArray);
 
   DPRINT ("SpiScanAdapter() done\n");
 }
@@ -1957,7 +2189,7 @@ SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                {
                  DPRINT("(Bus %lu Target %lu Lun %lu)\n",
                         Bus, Target, Lun);
-
+          RtlZeroMemory(UnitInfo, sizeof(*UnitInfo));
                  UnitInfo->PathId = Bus;
                  UnitInfo->TargetId = Target;
                  UnitInfo->Lun = Lun;
@@ -1995,30 +2227,16 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
            IN PVOID ServiceContext)
 {
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  BOOLEAN Result;
 
   DPRINT("ScsiPortIsr() called!\n");
 
   DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
 
-  Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
-  if (Result == FALSE)
-    {
-      return(FALSE);
-    }
-
-  if (DeviceExtension->IrpFlags)
-    {
-      IoRequestDpc(DeviceExtension->DeviceObject,
-                   NULL,
-                  DeviceExtension);
-    }
-
-  return(TRUE);
+  return DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
 }
 
 
-//    ScsiPortDpcForIsr
+//    ScsiPortDpc
 //  DESCRIPTION:
 //
 //  RUN LEVEL:
@@ -2030,21 +2248,21 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
 //    IN PVOID          DpcContext
 //
 static VOID STDCALL
-ScsiPortDpcForIsr(IN PKDPC Dpc,
-                 IN PDEVICE_OBJECT DpcDeviceObject,
-                 IN PIRP DpcIrp,
-                 IN PVOID DpcContext)
+ScsiPortDpc(IN PKDPC Dpc,
+           IN PDEVICE_OBJECT DpcDeviceObject,
+           IN PIRP DpcIrp,
+           IN PVOID DpcContext)
 {
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
 
-  DPRINT("ScsiPortDpcForIsr(Dpc %p  DpcDeviceObject %p  DpcIrp %p  DpcContext %p)\n",
+  DPRINT("ScsiPortDpc(Dpc %p  DpcDeviceObject %p  DpcIrp %p  DpcContext %p)\n",
         Dpc, DpcDeviceObject, DpcIrp, DpcContext);
 
   DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
 
   SpiProcessRequests(DeviceExtension, NULL);
 
-  DPRINT("ScsiPortDpcForIsr() done\n");
+  DPRINT("ScsiPortDpc() done\n");
 }
 
 
@@ -2071,14 +2289,19 @@ static PSCSI_REQUEST_BLOCK
 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
 {
   PSCSI_REQUEST_BLOCK Srb;
+  ULONG Length;
   PCDB Cdb;
 
-  Srb = ExAllocatePoolWithTag(NonPagedPool, 
-                       sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA),
-                      TAG('S', 'S', 'r', 'b'));
+  Length = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA) + 32;
+  Srb = ExAllocatePoolWithTag(NonPagedPool,
+                              Length,
+                             TAG('S', 'S', 'r', 'b'));
+  if (Srb == NULL)
+    {
+      return NULL;
+    }
 
-  RtlZeroMemory(Srb,
-               sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA));
+  RtlZeroMemory(Srb, Length);
 
   Srb->PathId = OriginalSrb->PathId;
   Srb->TargetId = OriginalSrb->TargetId;
@@ -2090,7 +2313,12 @@ ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
   Srb->TimeOutValue = 4;
 
   Srb->CdbLength = 6;
-  Srb->DataBuffer = Srb + 1;
+  /* The DataBuffer must be located in contiguous physical memory if
+   * the miniport driver uses dma for the sense info. The size of
+   * the sense data is 18 byte. If the buffer starts at a 32 byte
+   * boundary than is the buffer always in one memory page.
+   */
+  Srb->DataBuffer = (PVOID)ROUND_UP((ULONG_PTR)(Srb + 1), 32);
   Srb->DataTransferLength = sizeof(SENSE_DATA);
 
   Cdb = (PCDB)Srb->Cdb;
@@ -2129,7 +2357,8 @@ SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 {
   PSCSI_PORT_LUN_EXTENSION LunExtension;
   OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING KeyName;
+  UNICODE_STRING KeyName =
+    RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
   UNICODE_STRING ValueName;
   WCHAR NameBuffer[64];
   ULONG Disposition;
@@ -2157,8 +2386,6 @@ SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     }
 
   /* Open or create the 'Scsi' subkey */
-  RtlRosInitUnicodeStringFromLiteral(&KeyName,
-                                 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
   InitializeObjectAttributes(&ObjectAttributes,
                             &KeyName,
                             OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
@@ -2263,7 +2490,7 @@ SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     }
 
   /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
-  UlongData = ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig->AccessRanges[0].RangeStart);
+  UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart);
   DPRINT("  IOAddress = %lx\n", UlongData);
   RtlInitUnicodeString(&ValueName,
                       L"IOAddress");
@@ -2524,7 +2751,64 @@ ByeBye:
 }
 
 static VOID
-SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 
+SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                  PIRP Irp,
+                  PIRP PrevIrp)
+{
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PIRP CurrentIrp;
+  LunExtension = Irp->Tail.Overlay.DriverContext[2];
+  InterlockedDecrement((PLONG)&LunExtension->ActiveIrpCount);
+  InterlockedDecrement((PLONG)&DeviceExtension->ActiveIrpCount);
+  if (PrevIrp)
+    {
+      InterlockedExchangePointer(&PrevIrp->Tail.Overlay.DriverContext[0],
+                                Irp->Tail.Overlay.DriverContext[0]);
+    }
+  else
+    {
+      InterlockedExchangePointer(&DeviceExtension->NextIrp,
+                                Irp->Tail.Overlay.DriverContext[0]);
+    }
+  if (LunExtension->NextIrp == Irp)
+    {
+      InterlockedExchangePointer(&LunExtension->NextIrp,
+                                Irp->Tail.Overlay.DriverContext[1]);
+      return;
+    }
+  else
+    {
+      CurrentIrp = LunExtension->NextIrp;
+      while (CurrentIrp)
+        {
+         if (CurrentIrp->Tail.Overlay.DriverContext[1] == Irp)
+           {
+             InterlockedExchangePointer(&CurrentIrp->Tail.Overlay.DriverContext[1],
+                                        Irp->Tail.Overlay.DriverContext[1]);
+             return;
+           }
+          CurrentIrp = CurrentIrp->Tail.Overlay.DriverContext[1];
+       }
+      KEBUGCHECK(0);
+    }
+}
+
+static VOID
+SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+               PIRP Irp)
+{
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PSCSI_REQUEST_BLOCK Srb;
+  LunExtension = Irp->Tail.Overlay.DriverContext[2];
+  Srb = Irp->Tail.Overlay.DriverContext[3];
+  Irp->Tail.Overlay.DriverContext[0] = (PVOID)DeviceExtension->NextIrp;
+  InterlockedExchangePointer(&DeviceExtension->NextIrp, Irp);
+  Irp->Tail.Overlay.DriverContext[1] = (PVOID)LunExtension->NextIrp;
+  InterlockedExchangePointer(&LunExtension->NextIrp, Irp);
+}
+
+static VOID
+SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                   IN PIRP NextIrp)
 {
   /*
@@ -2541,10 +2825,11 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
    *   Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
    *   Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
    *   IoStack->Parameters.Scsi.Srb -> original Srb
-   *   
+   *
    * Irp is within the active irp list or while other processing:
    *   Srb->OriginalRequest -> Irp
-   *   Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
+   *   Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
+   *   Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
    *   Irp->Tail.Overlay.DriverContext[2] -> LunExtension
    *   Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
    *   IoStack->Parameters.Scsi.Srb -> original Srb
@@ -2558,21 +2843,27 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
   LIST_ENTRY CompleteIrpListHead;
   PSCSI_REQUEST_BLOCK Srb;
   PSCSI_REQUEST_BLOCK OriginalSrb;
+  PIRP PrevIrp;
 
   DPRINT("SpiProcessRequests() called\n");
 
   InitializeListHead(&NextIrpListHead);
   InitializeListHead(&CompleteIrpListHead);
 
-  KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
+  KeAcquireSpinLock(&DeviceExtension->Lock, &oldIrql);
 
   if (NextIrp)
     {
       Srb = NextIrp->Tail.Overlay.DriverContext[3];
+      /*
+       * FIXME:
+       *   Is this the right place to set this flag ?
+       */
       NextIrp->Tail.Overlay.DriverContext[2] = (PVOID)Srb->QueueSortKey;
+      LunExtension = Srb->OriginalRequest;
 
       ListEntry = DeviceExtension->PendingIrpListHead.Flink;
-      while (ListEntry != DeviceExtension->PendingIrpListHead.Flink)
+      while (ListEntry != &DeviceExtension->PendingIrpListHead)
         {
           Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
           if ((ULONG)Irp->Tail.Overlay.DriverContext[2] > Srb->QueueSortKey)
@@ -2582,36 +2873,57 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
           ListEntry = ListEntry->Flink;
        }
       InsertTailList(ListEntry, (PLIST_ENTRY)&NextIrp->Tail.Overlay.DriverContext[0]);
+      DeviceExtension->PendingIrpCount++;
+      LunExtension->PendingIrpCount++;
     }
 
-  while (DeviceExtension->CompleteRequestCount ||
-         ((DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->ActiveIrpCount < MAX_SRB_EXTENSIONS) && !IsListEmpty(&DeviceExtension->PendingIrpListHead) &&
-         (DeviceExtension->NextRequestCount || DeviceExtension->NextLuRequestCount || IsListEmpty(&DeviceExtension->ActiveIrpListHead))))
+  while (DeviceExtension->Flags & IRP_FLAG_COMPLETE ||
+         (((DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions) &&
+         DeviceExtension->PendingIrpCount > 0 &&
+         (DeviceExtension->Flags & (IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU) || DeviceExtension->NextIrp == NULL))))
     {
-      DPRINT("CompleteRequestCount %d, NextRequestCount %d, NextLuRequestCount %d, PendingIrpList is %s, ActiveIrpList is %s\n", 
-            DeviceExtension->CompleteRequestCount, 
-            DeviceExtension->NextRequestCount,
-            DeviceExtension->NextLuRequestCount, 
-            IsListEmpty(&DeviceExtension->PendingIrpListHead) ? "EMPTY" : "NOT empty", 
-            IsListEmpty(&DeviceExtension->ActiveIrpListHead) ? "EMPTY" : "NOT empty");
-
-      if (DeviceExtension->CompleteRequestCount > 0)
+      DPRINT ("RequestComplete %d, NextRequest %d, NextLuRequest %d, PendingIrpCount %d, ActiveIrpCount %d\n",
+             DeviceExtension->Flags & IRP_FLAG_COMPLETE ? 1 : 0,
+             DeviceExtension->Flags & IRP_FLAG_NEXT ? 1 : 0,
+             DeviceExtension->Flags & IRP_FLAG_NEXT_LU ? 1 : 0,
+             DeviceExtension->PendingIrpCount,
+             DeviceExtension->ActiveIrpCount);
+
+
+      if (DeviceExtension->Flags & IRP_FLAG_COMPLETE)
         {
-         DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
-         ListEntry = DeviceExtension->ActiveIrpListHead.Flink;
-         while (ListEntry != &DeviceExtension->ActiveIrpListHead)
+         DeviceExtension->Flags &= ~IRP_FLAG_COMPLETE;
+         PrevIrp = NULL;
+         Irp = DeviceExtension->NextIrp;
+         while (Irp)
            {
-              Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
-             ListEntry = ListEntry->Flink;
+             NextIrp = (PIRP)Irp->Tail.Overlay.DriverContext[0];
              Srb = Irp->Tail.Overlay.DriverContext[3];
               if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
                {
                   BOOLEAN CompleteThisRequest;
-                 InterlockedDecrement((PLONG)&DeviceExtension->CompleteRequestCount);
                   LunExtension = Irp->Tail.Overlay.DriverContext[2];
                  IrpStack = IoGetCurrentIrpStackLocation(Irp);
                  OriginalSrb = IrpStack->Parameters.Scsi.Srb;
 
+                 if (Srb->SrbStatus == SRB_STATUS_BUSY)
+                   {
+                      CompleteThisRequest = FALSE;
+                     Irp->Tail.Overlay.DriverContext[3] = Srb;
+
+                     SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
+                      SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
+
+                      Srb->OriginalRequest = LunExtension;
+                      Irp->Tail.Overlay.DriverContext[2] = 0;
+
+                     InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+                     DeviceExtension->PendingIrpCount++;
+                     LunExtension->PendingIrpCount++;
+                     Irp = NextIrp;
+                     continue;
+                   }
+
                   if (OriginalSrb != Srb)
                    {
                      SENSE_DATA* SenseInfoBuffer;
@@ -2624,20 +2936,21 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                      DPRINT("ErrorCode: %x\n", SenseInfoBuffer->ErrorCode);
                      DPRINT("SenseKey: %x\n", SenseInfoBuffer->SenseKey);
                      DPRINT("SenseCode: %x\n", SenseInfoBuffer->AdditionalSenseCode);
-             
+
                      /* Copy sense data */
-                     if (OriginalSrb->SenseInfoBufferLength != 0)
-                       {
-                         RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
-                                       SenseInfoBuffer,
-                                       sizeof(SENSE_DATA));
-                         OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
-                       }
+                      RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
+                                   SenseInfoBuffer,
+                                   sizeof(SENSE_DATA));
+                     OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+                      OriginalSrb->SrbExtension = Srb->SrbExtension;
                      ExFreePool(Srb);
                      CompleteThisRequest = TRUE;
                    }
-                 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
-                          (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
+                 else if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS &&
+                          Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION &&
+                          Srb->SenseInfoBuffer != NULL &&
+                          Srb->SenseInfoBufferLength >= sizeof(SENSE_DATA) &&
+                          !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
                    {
                      DPRINT("SCSIOP_REQUEST_SENSE required!\n");
 
@@ -2647,10 +2960,8 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                        {
                          CompleteThisRequest = FALSE;
                          Irp->Tail.Overlay.DriverContext[3] = Srb;
-                          RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
-                         SpiFreeSrbExtension(DeviceExtension, Srb);
-                         LunExtension->ActiveIrpCount--;
-                         DeviceExtension->ActiveIrpCount--;
+                         SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
+                         SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
 
                           Srb->OriginalRequest = LunExtension;
                           Irp->Tail.Overlay.DriverContext[2] = 0;
@@ -2658,6 +2969,8 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                          InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
                          DeviceExtension->PendingIrpCount++;
                          LunExtension->PendingIrpCount++;
+                         Irp = NextIrp;
+                         continue;
                        }
                      else
                        {
@@ -2671,20 +2984,36 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                    }
                  if (CompleteThisRequest)
                    {
-                      RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+                     SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
                      InsertHeadList(&CompleteIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
                       SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
-                     LunExtension->ActiveIrpCount--;
-                      DeviceExtension->ActiveIrpCount--;
                    }
-               }            
+                 else
+                   {
+                     PrevIrp = Irp;
+                   }
+                 Irp = NextIrp;
+                 continue;
+               }
+             PrevIrp = Irp;
+             Irp = NextIrp;
            }
        }
-      if (DeviceExtension->NextLuRequestCount ||
-         DeviceExtension->NextRequestCount)
+      if (!IsListEmpty(&CompleteIrpListHead))
+        {
+          KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
+         while (!IsListEmpty(&CompleteIrpListHead))
+           {
+             ListEntry = RemoveTailList(&CompleteIrpListHead);
+             Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+             IoCompleteRequest(Irp, IO_NO_INCREMENT);
+           }
+         KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
+        }
+      if (DeviceExtension->Flags & (IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU) &&
+          (DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions))
         {
          BOOLEAN StartThisRequest;
-         DeviceExtension->IrpFlags &= ~(IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU);
          ListEntry = DeviceExtension->PendingIrpListHead.Flink;
          while (ListEntry != &DeviceExtension->PendingIrpListHead)
            {
@@ -2693,21 +3022,21 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
              Srb = Irp->Tail.Overlay.DriverContext[3];
              LunExtension = Srb->OriginalRequest;
              if (DeviceExtension->SrbExtensionSize > 0 &&
-                 DeviceExtension->ActiveIrpCount >= MAX_SRB_EXTENSIONS)
+                 DeviceExtension->CurrentSrbExtensions >= DeviceExtension->MaxSrbExtensions)
                {
                  break;
                }
-             if (LunExtension->NextLuRequestCount > 0)
+             if (LunExtension->Flags & IRP_FLAG_NEXT_LU)
                 {
                  StartThisRequest = TRUE;
-                 InterlockedDecrement((PLONG)&LunExtension->NextLuRequestCount);
-                 InterlockedDecrement((PLONG)&DeviceExtension->NextLuRequestCount);
+                 LunExtension->Flags &= ~IRP_FLAG_NEXT_LU;
+                  DeviceExtension->Flags &= ~IRP_FLAG_NEXT_LU;
                }
-             else if (DeviceExtension->NextRequestCount > 0 &&
+             else if (DeviceExtension->Flags & IRP_FLAG_NEXT &&
                       LunExtension->ActiveIrpCount == 0)
                {
-                 InterlockedDecrement((PLONG)&DeviceExtension->NextRequestCount);
                  StartThisRequest = TRUE;
+                  DeviceExtension->Flags &= ~IRP_FLAG_NEXT;
                }
              else
                {
@@ -2717,15 +3046,16 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                {
                  LunExtension->PendingIrpCount--;
                  DeviceExtension->PendingIrpCount--;
-                  RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+                 Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
                   LunExtension->ActiveIrpCount++;
                   DeviceExtension->ActiveIrpCount++;
-                 SpiAllocateSrbExtension(DeviceExtension, Srb);
 
+                  RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
                  Irp->Tail.Overlay.DriverContext[2] = LunExtension;
                  Srb->OriginalRequest = Irp;
+                 SpiAllocateSrbExtension(DeviceExtension, Srb);
 
-                  InsertHeadList(&NextIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);             
+                  InsertHeadList(&NextIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
                }
            }
        }
@@ -2736,54 +3066,40 @@ SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
            {
              ListEntry = RemoveTailList(&NextIrpListHead);
              Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
-              InsertHeadList(&DeviceExtension->ActiveIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);              
-             KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
+             KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
 
              // Start this Irp
              SpiStartIo(DeviceExtension, Irp);
-             KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
+             KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
            }
        }
 
       if (!IsListEmpty(&DeviceExtension->PendingIrpListHead) &&
-          IsListEmpty(&DeviceExtension->ActiveIrpListHead) &&
-          (DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->ActiveIrpCount < MAX_SRB_EXTENSIONS))
+         DeviceExtension->NextIrp == NULL &&
+         (DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions))
         {
          ListEntry = RemoveHeadList(&DeviceExtension->PendingIrpListHead);
           Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
           Srb = Irp->Tail.Overlay.DriverContext[3];
          LunExtension = Srb->OriginalRequest;
+         Irp->Tail.Overlay.DriverContext[2] = LunExtension;
+         Srb->OriginalRequest = Irp;
 
          LunExtension->PendingIrpCount--;
          DeviceExtension->PendingIrpCount--;
-          InsertHeadList(&DeviceExtension->ActiveIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);                  
-          LunExtension->ActiveIrpCount++;
+          Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
+         LunExtension->ActiveIrpCount++;
           DeviceExtension->ActiveIrpCount++;
-         SpiAllocateSrbExtension(DeviceExtension, Srb);
-
-         Irp->Tail.Overlay.DriverContext[2] = LunExtension;
-         Srb->OriginalRequest = Irp;
 
-         KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
+         SpiAllocateSrbExtension(DeviceExtension, Srb);
+          KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
 
-          // Start this irp
+          /* Start this irp */
           SpiStartIo(DeviceExtension, Irp);
-         KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
-       }
-
-      if (!IsListEmpty(&CompleteIrpListHead))
-       {
-         KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
-         while (!IsListEmpty(&CompleteIrpListHead))
-           {
-             ListEntry = RemoveTailList(&CompleteIrpListHead);
-             Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
-             IoCompleteRequest(Irp, IO_NO_INCREMENT);
-           }
-         KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
-       }
+         KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
+        }
      }
-   KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+   KeReleaseSpinLock(&DeviceExtension->Lock, oldIrql);
 
    DPRINT("SpiProcessRequests() done\n");
  }
@@ -2794,7 +3110,6 @@ SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 {
   PSCSI_PORT_LUN_EXTENSION LunExtension;
   PSCSI_REQUEST_BLOCK Srb;
-  PIO_STACK_LOCATION IrpStack;
 
   DPRINT("SpiStartIo() called!\n");
 
@@ -2803,36 +3118,20 @@ SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
   Srb = Irp->Tail.Overlay.DriverContext[3];
   LunExtension = Irp->Tail.Overlay.DriverContext[2];
 
-  Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
   Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = Srb->DataTransferLength;
 
+  SpiAddActiveIrp(DeviceExtension, Irp);
+
   if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
                              ScsiPortStartPacket,
                               Srb))
     {
       DPRINT1("Synchronization failed!\n");
-
-      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-      Irp->IoStatus.Information = 0;
-
-      KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
-
-      RemoveEntryList((PLIST_ENTRY)Irp->Tail.Overlay.DriverContext[0]);
-      LunExtension = Irp->Tail.Overlay.DriverContext[2];
-      LunExtension->ActiveIrpCount--;
-      SpiFreeSrbExtension(DeviceExtension, Srb);
-      IrpStack = IoGetCurrentIrpStackLocation(Irp);
-      if (IrpStack->Parameters.Scsi.Srb != Srb)
-        {
-         ExFreePool(Srb);
-       }
-      DeviceExtension->ActiveIrpCount--;
-
-      KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
-      
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
+      DPRINT1("Irp %x, Srb->Function %02x, Srb->Cdb[0] %02x, Srb->SrbStatus %02x\n", Irp, Srb->Function, Srb->Cdb[0], Srb->SrbStatus);
+      ScsiPortNotification(RequestComplete,
+                          &DeviceExtension->MiniPortDeviceExtension,
+                          Srb);
     }
 
   DPRINT("SpiStartIo() done\n");