update for HEAD-2003091401
[reactos.git] / drivers / storage / scsiport / scsiport.c
index 524201c..bd80ad1 100644 (file)
 
 #define VERSION "0.0.1"
 
+#include "scsiport_int.h"
 
-/* TYPES *********************************************************************/
-
-/*
- * SCSI_PORT_TIMER_STATES
- *
- * DESCRIPTION
- *     An enumeration containing the states in the timer DFA
- */
-typedef enum _SCSI_PORT_TIMER_STATES
-{
-  IDETimerIdle,
-  IDETimerCmdWait,
-  IDETimerResetWaitForBusyNegate,
-  IDETimerResetWaitForDrdyAssert
-} SCSI_PORT_TIMER_STATES;
-
-
-typedef struct _SCSI_PORT_DEVICE_BASE
-{
-  LIST_ENTRY List;
-
-  PVOID MappedAddress;
-  ULONG NumberOfBytes;
-  SCSI_PHYSICAL_ADDRESS IoAddress;
-  ULONG SystemIoBusNumber;
-} SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE;
-
-
-/*
- * SCSI_PORT_DEVICE_EXTENSION
- *
- * DESCRIPTION
- *     First part of the port objects device extension. The second
- *     part is the miniport-specific device extension.
- */
-
-typedef struct _SCSI_PORT_DEVICE_EXTENSION
-{
-  ULONG Length;
-  ULONG MiniPortExtensionSize;
-  PORT_CONFIGURATION_INFORMATION PortConfig;
-  ULONG PortNumber;
-
-  KSPIN_LOCK IrpLock;
-  KSPIN_LOCK SpinLock;
-  PKINTERRUPT Interrupt;
-  PIRP                   CurrentIrp;
-  ULONG IrpFlags;
-
-  SCSI_PORT_TIMER_STATES TimerState;
-  LONG                   TimerCount;
-
-  BOOLEAN Initializing;
-
-  LIST_ENTRY DeviceBaseListHead;
-
-  ULONG PortBusInfoSize;
-  PSCSI_ADAPTER_BUS_INFO PortBusInfo;
-
-  PIO_SCSI_CAPABILITIES PortCapabilities;
-
-  PDEVICE_OBJECT DeviceObject;
-  PCONTROLLER_OBJECT ControllerObject;
-
-  PHW_STARTIO HwStartIo;
-  PHW_INTERRUPT HwInterrupt;
-
-  PSCSI_REQUEST_BLOCK OriginalSrb;
-  SCSI_REQUEST_BLOCK InternalSrb;
-  SENSE_DATA InternalSenseData;
-
-  UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
-} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
+//#define USE_DEVICE_QUEUES
 
+/* TYPES *********************************************************************/
 
 #define IRP_FLAG_COMPLETE      0x00000001
 #define IRP_FLAG_NEXT          0x00000002
+#define IRP_FLAG_NEXT_LU       0x00000004
 
 
 /* GLOBALS *******************************************************************/
@@ -151,8 +82,24 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
                         IN ULONG PortCount,
                         IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension);
 
+static PSCSI_PORT_LUN_EXTENSION
+SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                        IN UCHAR PathId,
+                        IN UCHAR TargetId,
+                        IN UCHAR Lun);
+
+static PSCSI_PORT_LUN_EXTENSION
+SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                   IN UCHAR PathId,
+                   IN UCHAR TargetId,
+                   IN UCHAR Lun);
+
 static VOID
-ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
+SpiInquirePort (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
+
+static ULONG
+SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                  OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo);
 
 static BOOLEAN STDCALL
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
@@ -173,8 +120,8 @@ ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                            PSCSI_REQUEST_BLOCK OriginalSrb);
 
 static NTSTATUS
-ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
-                      PUNICODE_STRING RegistryPath);
+SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                  PUNICODE_STRING RegistryPath);
 
 
 /* FUNCTIONS *****************************************************************/
@@ -231,6 +178,8 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
  *
  * RETURN VALUE
  *     None.
+ *
+ * @implemented
  */
 
 VOID
@@ -254,6 +203,9 @@ ScsiDebugPrint(IN ULONG DebugPrintLevel,
 }
 
 
+/*
+ * @unimplemented
+ */
 VOID STDCALL
 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
                        IN UCHAR PathId,
@@ -266,6 +218,9 @@ ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
 {
@@ -274,6 +229,9 @@ ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
 }
 
 
+/*
+ * @unimplemented
+ */
 VOID STDCALL
 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
 {
@@ -282,6 +240,9 @@ ScsiPortFlushDma(IN PVOID HwDeviceExtension)
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
                       IN PVOID MappedAddress)
@@ -319,6 +280,9 @@ ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
 ScsiPortGetBusData(IN PVOID DeviceExtension,
                   IN ULONG BusDataType,
@@ -335,6 +299,9 @@ ScsiPortGetBusData(IN PVOID DeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 PVOID STDCALL
 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
@@ -388,28 +355,105 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 PVOID STDCALL
 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
                       IN UCHAR PathId,
                       IN UCHAR TargetId,
                       IN UCHAR Lun)
 {
-  DPRINT("ScsiPortGetLogicalUnit()\n");
-  UNIMPLEMENTED;
+  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PLIST_ENTRY Entry;
+
+  DPRINT("ScsiPortGetLogicalUnit() called\n");
+
+  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                     SCSI_PORT_DEVICE_EXTENSION,
+                                     MiniPortDeviceExtension);
+  if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
+    return NULL;
+
+  Entry = DeviceExtension->LunExtensionListHead.Flink;
+  while (Entry != &DeviceExtension->LunExtensionListHead)
+    {
+      LunExtension = CONTAINING_RECORD(Entry,
+                                      SCSI_PORT_LUN_EXTENSION,
+                                      List);
+      if (LunExtension->PathId == PathId &&
+         LunExtension->TargetId == TargetId &&
+         LunExtension->Lun == Lun)
+       {
+         return (PVOID)&LunExtension->MiniportLunExtension;
+       }
+
+      Entry = Entry->Flink;
+    }
+
+  return NULL;
 }
 
 
+/*
+ * @unimplemented
+ */
 SCSI_PHYSICAL_ADDRESS STDCALL
 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
                           IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
                           IN PVOID VirtualAddress,
                           OUT ULONG *Length)
 {
-  DPRINT("ScsiPortGetPhysicalAddress()\n");
-  UNIMPLEMENTED;
+  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  SCSI_PHYSICAL_ADDRESS PhysicalAddress;
+  ULONG BufferLength = 0;
+  ULONG Offset;
+
+  DPRINT1("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
+         HwDeviceExtension, Srb, VirtualAddress, Length);
+
+  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                     SCSI_PORT_DEVICE_EXTENSION,
+                                     MiniPortDeviceExtension);
+
+  *Length = 0;
+
+  if (Srb == NULL)
+    {
+      if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
+       {
+         PhysicalAddress.QuadPart = 0ULL;
+         return PhysicalAddress;
+       }
+
+      Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
+      if (Offset >= DeviceExtension->CommonBufferLength)
+       {
+         PhysicalAddress.QuadPart = 0ULL;
+         return PhysicalAddress;
+       }
+
+      PhysicalAddress.QuadPart =
+       DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
+      BufferLength = DeviceExtension->CommonBufferLength - Offset;
+    }
+  else
+    {
+      /* FIXME */
+      DPRINT1("Srb != NULL is not implemented yet!\n");
+      UNIMPLEMENTED;
+    }
+
+  *Length = BufferLength;
+
+  return PhysicalAddress;
 }
 
 
+/*
+ * @unimplemented
+ */
 PSCSI_REQUEST_BLOCK STDCALL
 ScsiPortGetSrb(IN PVOID DeviceExtension,
               IN UCHAR PathId,
@@ -422,22 +466,103 @@ ScsiPortGetSrb(IN PVOID DeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 PVOID STDCALL
 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
                             IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
                             IN ULONG NumberOfBytes)
 {
-  DPRINT("ScsiPortGetUncachedExtension()\n");
-  UNIMPLEMENTED;
+  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  DEVICE_DESCRIPTION DeviceDescription;
+
+  DPRINT1("ScsiPortGetUncachedExtension(%p %p %lu)\n",
+         HwDeviceExtension, ConfigInfo, NumberOfBytes);
+
+  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                     SCSI_PORT_DEVICE_EXTENSION,
+                                     MiniPortDeviceExtension);
+
+  /* Check for allocated common DMA buffer */
+  if (DeviceExtension->VirtualAddress != NULL)
+    {
+      DPRINT1("The HBA has already got a common DMA buffer!\n");
+      return NULL;
+    }
+
+  /* Check for DMA adapter object */
+  if (DeviceExtension->AdapterObject == NULL)
+    {
+      /* Initialize DMA adapter description */
+      RtlZeroMemory(&DeviceDescription,
+                   sizeof(DEVICE_DESCRIPTION));
+      DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+      DeviceDescription.Master = ConfigInfo->Master;
+      DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
+      DeviceDescription.DemandMode = ConfigInfo->DemandMode;
+      DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
+      DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
+      DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
+      DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
+      DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
+      DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
+      DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
+      DeviceDescription.DmaPort = ConfigInfo->DmaPort;
+
+      /* Get a DMA adapter object */
+      DeviceExtension->AdapterObject = HalGetAdapter(&DeviceDescription,
+                                                    &DeviceExtension->MapRegisterCount);
+      if (DeviceExtension->AdapterObject == NULL)
+       {
+         DPRINT1("HalGetAdapter() failed\n");
+         return NULL;
+       }
+    }
+
+  /* Allocate a common DMA buffer */
+  DeviceExtension->CommonBufferLength = NumberOfBytes;
+  DeviceExtension->VirtualAddress =
+    HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
+                           DeviceExtension->CommonBufferLength,
+                           &DeviceExtension->PhysicalAddress,
+                           FALSE);
+  if (DeviceExtension->VirtualAddress == NULL)
+    {
+      DPRINT1("HalAllocateCommonBuffer() failed!\n");
+      DeviceExtension->CommonBufferLength = 0;
+      return NULL;
+    }
+
+  return DeviceExtension->VirtualAddress;
 }
 
 
+/*
+ * @implemented
+ */
 PVOID STDCALL
 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
                          IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
 {
-  DPRINT("ScsiPortGetVirtualAddress()\n");
-  UNIMPLEMENTED;
+  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  ULONG Offset;
+
+  DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
+        HwDeviceExtension, PhysicalAddress.QuadPart);
+
+  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                     SCSI_PORT_DEVICE_EXTENSION,
+                                     MiniPortDeviceExtension);
+
+  if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
+    return NULL;
+
+  Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
+  if (Offset >= DeviceExtension->CommonBufferLength)
+    return NULL;
+
+  return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
 }
 
 
@@ -466,6 +591,8 @@ ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
  *
  * RETURN VALUE
  *     Status.
+ *
+ * @implemented
  */
 
 ULONG STDCALL
@@ -498,10 +625,10 @@ ScsiPortInitialize(IN PVOID Argument1,
     return(STATUS_INVALID_PARAMETER);
 
   DriverObject->DriverStartIo = ScsiPortStartIo;
-  DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
-  DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
-  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
-  DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
+  DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)ScsiPortCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)ScsiPortCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)ScsiPortDeviceControl;
+  DriverObject->MajorFunction[IRP_MJ_SCSI] = (PDRIVER_DISPATCH)ScsiPortDispatchScsi;
 
 
   SystemConfig = IoGetConfigurationInformation();
@@ -514,6 +641,7 @@ ScsiPortInitialize(IN PVOID Argument1,
                ExtensionSize);
   PseudoDeviceExtension->Length = ExtensionSize;
   PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
+  PseudoDeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
   PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
   PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
 
@@ -550,6 +678,12 @@ ScsiPortInitialize(IN PVOID Argument1,
 //      RtlZeroMemory(AccessRanges,
 //                 sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
 
+      PseudoDeviceExtension->AdapterObject = NULL;
+      PseudoDeviceExtension->MapRegisterCount = 0;
+      PseudoDeviceExtension->PhysicalAddress.QuadPart = 0ULL;
+      PseudoDeviceExtension->VirtualAddress = NULL;
+      PseudoDeviceExtension->CommonBufferLength = 0;
+
       RtlZeroMemory(PseudoDeviceExtension->MiniPortDeviceExtension,
                    PseudoDeviceExtension->MiniPortExtensionSize);
 
@@ -581,9 +715,12 @@ ScsiPortInitialize(IN PVOID Argument1,
              return(Status);
            }
 
+         /* Get inquiry data */
+         SpiInquirePort (RealDeviceExtension);
+
          /* Build the registry device map */
-         ScsiPortBuildDeviceMap(RealDeviceExtension,
-                                (PUNICODE_STRING)Argument2);
+         SpiBuildDeviceMap (RealDeviceExtension,
+                            (PUNICODE_STRING)Argument2);
 
          /* Update the configuration info */
          SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed;
@@ -614,6 +751,9 @@ ScsiPortInitialize(IN PVOID Argument1,
 }
 
 
+/*
+ * @unimplemented
+ */
 VOID STDCALL
 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb,
@@ -625,6 +765,9 @@ ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
 }
 
 
+/*
+ * @unimplemented
+ */
 VOID STDCALL
 ScsiPortLogError(IN PVOID HwDeviceExtension,
                 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
@@ -647,6 +790,9 @@ ScsiPortLogError(IN PVOID HwDeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 ScsiPortMoveMemory(OUT PVOID Destination,
                   IN PVOID Source,
@@ -658,12 +804,16 @@ ScsiPortMoveMemory(OUT PVOID Destination,
 }
 
 
+/*
+ * @implemented
+ */
 VOID
 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
                     IN PVOID HwDeviceExtension,
                     ...)
 {
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  va_list ap;
 
   DPRINT("ScsiPortNotification() called\n");
 
@@ -678,11 +828,19 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
   if (DeviceExtension->Initializing == TRUE)
     return;
 
+  va_start(ap, HwDeviceExtension);
+
   switch (NotificationType)
     {
       case RequestComplete:
-       DPRINT("Notify: RequestComplete\n");
-       DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
+       {
+         PSCSI_REQUEST_BLOCK Srb;
+
+         Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
+
+         DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
+         DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
+       }
        break;
 
       case NextRequest:
@@ -690,12 +848,42 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
        DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
        break;
 
+      case NextLuRequest:
+       {
+         UCHAR PathId;
+         UCHAR TargetId;
+         UCHAR Lun;
+
+         PathId = (UCHAR) va_arg (ap, int);
+         TargetId = (UCHAR) va_arg (ap, int);
+         Lun = (UCHAR) va_arg (ap, int);
+
+         DPRINT1 ("Notify: NextLuRequest(PathId %u  TargetId %u  Lun %u)\n",
+                  PathId, TargetId, Lun);
+         /* FIXME: Implement it! */
+
+//       DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
+
+       }
+       break;
+
+      case ResetDetected:
+       DPRINT1("Notify: ResetDetected\n");
+       /* FIXME: ??? */
+       break;
+
       default:
+       DPRINT1 ("Unsupported notification %lu\n", NotificationType);
        break;
     }
+
+  va_end(ap);
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
                           IN ULONG BusDataType,
@@ -715,6 +903,9 @@ ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
 }
 
 
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
@@ -791,6 +982,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp)
 {
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
   PIO_STACK_LOCATION Stack;
   PSCSI_REQUEST_BLOCK Srb;
   NTSTATUS Status = STATUS_SUCCESS;
@@ -819,10 +1011,52 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
   DPRINT("Srb->Function: %lu\n", Srb->Function);
   DPRINT("PathId: %lu  TargetId: %lu  Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
 
+  LunExtension = SpiGetLunExtension(DeviceExtension,
+                                   Srb->PathId,
+                                   Srb->TargetId,
+                                   Srb->Lun);
+  if (LunExtension == NULL)
+    {
+      Status = STATUS_NO_SUCH_DEVICE;
+
+      Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+      Irp->IoStatus.Status = Status;
+      Irp->IoStatus.Information = 0;
+
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+      return(Status);
+    }
+
   switch (Srb->Function)
     {
       case SRB_FUNCTION_EXECUTE_SCSI:
-       IoStartPacket(DeviceObject, Irp, NULL, NULL);
+      case SRB_FUNCTION_IO_CONTROL:
+#ifdef USE_DEVICE_QUEUES
+       if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
+         {
+           IoStartPacket (DeviceObject, Irp, NULL, NULL);
+         }
+       else
+         {
+           KIRQL oldIrql;
+
+           KeRaiseIrql (DISPATCH_LEVEL,
+                        &oldIrql);
+
+           if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
+                                          &Irp->Tail.Overlay.DeviceQueueEntry,
+                                          Srb->QueueSortKey))
+             {
+               Srb->SrbStatus = SRB_STATUS_SUCCESS;
+               IoStartPacket (DeviceObject, Irp, NULL, NULL);
+             }
+
+           KeLowerIrql (oldIrql);
+         }
+#else
+        IoStartPacket (DeviceObject, Irp, NULL, NULL);
+#endif
        return(STATUS_PENDING);
 
       case SRB_FUNCTION_SHUTDOWN:
@@ -835,89 +1069,32 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
        break;
 
       case SRB_FUNCTION_CLAIM_DEVICE:
-       {
-         PSCSI_ADAPTER_BUS_INFO AdapterInfo;
-         PSCSI_INQUIRY_DATA UnitInfo;
-         PINQUIRYDATA InquiryData;
-
-         DPRINT("  SRB_FUNCTION_CLAIM_DEVICE\n");
-         DPRINT("PathId: %lu  TargetId: %lu  Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
-
-         Srb->DataBuffer = NULL;
-
-         if (DeviceExtension->PortBusInfo != NULL)
-           {
-             AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
-
-             if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
-               break;
-
-             UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
-               AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
-
-             while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
-               {
-                 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
-
-                 if ((UnitInfo->TargetId == Srb->TargetId) &&
-                     (UnitInfo->Lun == Srb->Lun) &&
-                     (UnitInfo->DeviceClaimed == FALSE))
-                   {
-                     UnitInfo->DeviceClaimed = TRUE;
-                     DPRINT("Claimed device!\n");
-
-                     /* FIXME: Hack!!!!! */
-                     Srb->DataBuffer = DeviceObject;
+       DPRINT("  SRB_FUNCTION_CLAIM_DEVICE\n");
 
-                     break;
-                   }
-
-                 if (UnitInfo->NextInquiryDataOffset == 0)
-                   break;
-
-                 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
-               }
-           }
-       }
+       /* Reference device object and keep the pointer */
+       ObReferenceObject(DeviceObject);
+       LunExtension->DeviceObject = DeviceObject;
+       LunExtension->DeviceClaimed = TRUE;
+       Srb->DataBuffer = DeviceObject;
        break;
 
       case SRB_FUNCTION_RELEASE_DEVICE:
        {
-         PSCSI_ADAPTER_BUS_INFO AdapterInfo;
-         PSCSI_INQUIRY_DATA UnitInfo;
-         PINQUIRYDATA InquiryData;
+         PSCSI_PORT_LUN_EXTENSION LunExtension;
 
          DPRINT("  SRB_FUNCTION_RELEASE_DEVICE\n");
          DPRINT("PathId: %lu  TargetId: %lu  Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
 
-         if (DeviceExtension->PortBusInfo != NULL)
+         LunExtension = SpiGetLunExtension(DeviceExtension,
+                                           Srb->PathId,
+                                           Srb->TargetId,
+                                           Srb->Lun);
+         if (LunExtension != NULL)
            {
-             AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
-
-             if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
-               break;
-
-             UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
-               AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
-
-             while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
-               {
-                 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
-
-                 if ((UnitInfo->TargetId == Srb->TargetId) &&
-                     (UnitInfo->Lun == Srb->Lun) &&
-                     (UnitInfo->DeviceClaimed == TRUE))
-                   {
-                     UnitInfo->DeviceClaimed = FALSE;
-                     DPRINT("Released device!\n");
-                     break;
-                   }
-
-                 if (UnitInfo->NextInquiryDataOffset == 0)
-                   break;
-
-                 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
-               }
+             /* Dereference device object */
+             ObDereferenceObject(LunExtension->DeviceObject);
+             LunExtension->DeviceObject = NULL;
+             LunExtension->DeviceClaimed = FALSE;
            }
        }
        break;
@@ -972,6 +1149,16 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
 
   switch (Stack->Parameters.DeviceIoControl.IoControlCode)
     {
+      case IOCTL_SCSI_GET_DUMP_POINTERS:
+       {
+         PDUMP_POINTERS DumpPointers;
+         DPRINT("  IOCTL_SCSI_GET_DUMP_POINTERS\n");
+         DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
+         DumpPointers->DeviceObject = DeviceObject;
+         
+         Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
+       }
+       break;
 
       case IOCTL_SCSI_GET_CAPABILITIES:
        {
@@ -989,12 +1176,10 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
          DPRINT("  IOCTL_SCSI_GET_INQUIRY_DATA\n");
 
          /* Copy inquiry data to the port device extension */
-         memcpy(Irp->AssociatedIrp.SystemBuffer,
-                DeviceExtension->PortBusInfo,
-                DeviceExtension->PortBusInfoSize);
-
-         DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize);
-         Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize;
+         Irp->IoStatus.Information =
+           SpiGetInquiryData(DeviceExtension,
+                             Irp->AssociatedIrp.SystemBuffer);
+         DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
        }
        break;
 
@@ -1015,79 +1200,88 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp)
 {
   PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
   PIO_STACK_LOCATION IrpStack;
-  KIRQL OldIrql;
+  PSCSI_REQUEST_BLOCK Srb;
+  KIRQL oldIrql;
+  BOOLEAN Result;
 
   DPRINT("ScsiPortStartIo() called!\n");
 
   DeviceExtension = DeviceObject->DeviceExtension;
   IrpStack = IoGetCurrentIrpStackLocation(Irp);
 
-  // FIXME: implement the supported functions
+  DPRINT("DeviceExtension %p\n", DeviceExtension);
 
-  switch (IrpStack->MajorFunction)
+  if (IrpStack->MajorFunction != IRP_MJ_SCSI)
     {
-      case IRP_MJ_SCSI:
-       {
-         BOOLEAN Result;
-         PSCSI_REQUEST_BLOCK Srb;
-         KIRQL oldIrql;
+      DPRINT("No IRP_MJ_SCSI!\n");
+      Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+      Irp->IoStatus.Information = 0;
+      IoCompleteRequest (Irp,
+                        IO_NO_INCREMENT);
+      IoStartNextPacket (DeviceObject,
+                        FALSE);
+      return;
+    }
 
-         DPRINT("IRP_MJ_SCSI\n");
+  Srb = IrpStack->Parameters.Scsi.Srb;
 
-         Srb = IrpStack->Parameters.Scsi.Srb;
+  LunExtension = SpiGetLunExtension(DeviceExtension,
+                                   Srb->PathId,
+                                   Srb->TargetId,
+                                   Srb->Lun);
+  if (LunExtension == NULL)
+    {
+      DPRINT("No IRP_MJ_SCSI!\n");
+      Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
+      Irp->IoStatus.Information = 0;
+      IoCompleteRequest (Irp,
+                        IO_NO_INCREMENT);
+      IoStartNextPacket (DeviceObject,
+                        FALSE);
+      return;
+    }
 
-         DPRINT("DeviceExtension %p\n", DeviceExtension);
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = Srb->DataTransferLength;
 
-         Irp->IoStatus.Status = STATUS_SUCCESS;
-         Irp->IoStatus.Information = Srb->DataTransferLength;
+  DeviceExtension->CurrentIrp = Irp;
 
-         DeviceExtension->CurrentIrp = Irp;
+  if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
+                             ScsiPortStartPacket,
+                             DeviceExtension))
+    {
+      DPRINT("Synchronization failed!\n");
 
-         if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
-                                     ScsiPortStartPacket,
-                                     DeviceExtension))
-           {
-               DPRINT("Synchronization failed!\n");
-
-               Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-               Irp->IoStatus.Information = 0;
-               IoCompleteRequest(Irp,
-                                 IO_NO_INCREMENT);
-               IoStartNextPacket(DeviceObject,
-                                 FALSE);
-           }
-         KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
-         if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
-           {
-               DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
-               IoCompleteRequest(Irp,
-                                 IO_NO_INCREMENT);
-           }
+      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+      Irp->IoStatus.Information = 0;
+      IoCompleteRequest(Irp,
+                       IO_NO_INCREMENT);
+      IoStartNextPacket(DeviceObject,
+                       FALSE);
+    }
 
-         if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
-           {
-               DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
-               KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
-               IoStartNextPacket(DeviceObject,
-                                 FALSE);
-           }
-         else
-           {
-               KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
-           }
-       }
-       break;
+  KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
+  if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
+    {
+      DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
+      IoCompleteRequest(Irp,
+                       IO_NO_INCREMENT);
+    }
 
-      default:
-       Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-       Irp->IoStatus.Information = 0;
-       IoCompleteRequest(Irp,
-                         IO_NO_INCREMENT);
-       IoStartNextPacket(DeviceObject,
-                         FALSE);
-       break;
+  if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
+    {
+      DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
+      KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+      IoStartNextPacket(DeviceObject,
+                       FALSE);
+    }
+  else
+    {
+      KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
     }
+
   DPRINT("ScsiPortStartIo() done\n");
 }
 
@@ -1250,6 +1444,7 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
     {
       DbgPrint("Could not Connect Interrupt %d\n",
               PortDeviceExtension->PortConfig.BusInterruptVector);
+      IoDeleteDevice(PortDeviceObject);
       return(Status);
     }
 
@@ -1282,13 +1477,10 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
     PortDeviceExtension->PortConfig.AdapterScansDown;
   PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
 
-  /* Initialize inquiry data */
-  PortDeviceExtension->PortBusInfoSize = 0;
-  PortDeviceExtension->PortBusInfo = NULL;
+  /* Initialize LUN-Extension list */
+  InitializeListHead(&PortDeviceExtension->LunExtensionListHead);
 
   DPRINT("DeviceExtension %p\n", PortDeviceExtension);
-  ScsiPortInquire(PortDeviceExtension);
-
 
   /* FIXME: Copy more configuration data? */
 
@@ -1311,98 +1503,212 @@ ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
 }
 
 
+static PSCSI_PORT_LUN_EXTENSION
+SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                        IN UCHAR PathId,
+                        IN UCHAR TargetId,
+                        IN UCHAR Lun)
+{
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  ULONG LunExtensionSize;
+
+  DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
+        DeviceExtension, PathId, TargetId, Lun);
+
+  LunExtensionSize =
+    sizeof(SCSI_PORT_LUN_EXTENSION) + DeviceExtension->LunExtensionSize;
+  DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
+
+  LunExtension = ExAllocatePool(NonPagedPool,
+                               LunExtensionSize);
+  if (LunExtension == NULL)
+    {
+      return NULL;
+    }
+
+  RtlZeroMemory(LunExtension,
+               LunExtensionSize);
+
+  InsertTailList(&DeviceExtension->LunExtensionListHead,
+                &LunExtension->List);
+
+  LunExtension->PathId = PathId;
+  LunExtension->TargetId = TargetId;
+  LunExtension->Lun = Lun;
+
+  KeInitializeDeviceQueue (&LunExtension->DeviceQueue);
+
+  return LunExtension;
+}
+
+
+static PSCSI_PORT_LUN_EXTENSION
+SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                   IN UCHAR PathId,
+                   IN UCHAR TargetId,
+                   IN UCHAR Lun)
+{
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PLIST_ENTRY Entry;
+
+  DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
+        DeviceExtension, PathId, TargetId, Lun);
+
+  if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
+    return NULL;
+
+  Entry = DeviceExtension->LunExtensionListHead.Flink;
+  while (Entry != &DeviceExtension->LunExtensionListHead)
+    {
+      LunExtension = CONTAINING_RECORD(Entry,
+                                      SCSI_PORT_LUN_EXTENSION,
+                                      List);
+      if (LunExtension->PathId == PathId &&
+         LunExtension->TargetId == TargetId &&
+         LunExtension->Lun == Lun)
+       {
+         return LunExtension;
+       }
+
+      Entry = Entry->Flink;
+    }
+
+  return NULL;
+}
+
+
 static VOID
-ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
+SpiInquirePort(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 {
-  PSCSI_ADAPTER_BUS_INFO AdapterInfo;
-  PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
   SCSI_REQUEST_BLOCK Srb;
   ULONG Bus;
   ULONG Target;
-  ULONG UnitCount;
-  ULONG DataSize;
+  ULONG Lun;
   BOOLEAN Result;
 
-  DPRINT("ScsiPortInquire() called\n");
+  DPRINT("SpiInquirePort() called\n");
 
   DeviceExtension->Initializing = TRUE;
 
-  /* Copy inquiry data to the port device extension */
-  AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096);
-  RtlZeroMemory(AdapterInfo, 4096);
-  AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
-
-  UnitInfo = (PSCSI_INQUIRY_DATA)
-       ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
-        (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
-
   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 = 256;
   Srb.Cdb[0] = SCSIOP_INQUIRY;
 
-  for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++)
+  for (Bus = 0; Bus < DeviceExtension->PortConfig.NumberOfBuses; Bus++)
     {
       Srb.PathId = Bus;
 
-      AdapterInfo->BusData[Bus].InitiatorBusId =
-       DeviceExtension->PortConfig.InitiatorBusId[Bus];
-      AdapterInfo->BusData[Bus].InquiryDataOffset =
-       (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
-
-      PrevUnit = NULL;
-      UnitCount = 0;
-
       for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
        {
          Srb.TargetId = Target;
-         Srb.Lun = 0;
-         Srb.SrbStatus = SRB_STATUS_SUCCESS;
-
-         Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
-                                             &Srb);
-         DPRINT("Result: %s  Srb.SrbStatus %lx\n", (Result)?"True":"False", Srb.SrbStatus);
 
-         if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
+         for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
            {
-             UnitInfo->PathId = Bus;
-             UnitInfo->TargetId = Target;
-             UnitInfo->Lun = 0;
-             UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
-             memcpy(&UnitInfo->InquiryData,
-                    Srb.DataBuffer,
-                    INQUIRYDATABUFFERSIZE);
-             if (PrevUnit != NULL)
-               PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
-             PrevUnit = UnitInfo;
-             UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
-             UnitCount++;
+             Srb.Lun = Lun;
+             Srb.SrbStatus = SRB_STATUS_SUCCESS;
+
+             Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
+                                                 &Srb);
+             DPRINT("Result %s  Srb.SrbStatus %lx\n", (Result) ? "TRUE" : "FALSE", Srb.SrbStatus);
+
+             if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
+               {
+                 LunExtension = SpiAllocateLunExtension(DeviceExtension,
+                                                        Bus,
+                                                        Target,
+                                                        Lun);
+                 if (LunExtension != NULL)
+                   {
+                     /* Copy inquiry data */
+                     memcpy(&LunExtension->InquiryData,
+                            Srb.DataBuffer,
+                            sizeof(INQUIRYDATA));
+                   }
+               }
            }
        }
-      DPRINT("UnitCount: %lu\n", UnitCount);
-      AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
-      if (UnitCount == 0)
-       AdapterInfo->BusData[Bus].InquiryDataOffset = 0;
     }
-  DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
 
   ExFreePool(Srb.DataBuffer);
 
   DeviceExtension->Initializing = FALSE;
 
-  /* copy inquiry data to the port driver's device extension */
-  DeviceExtension->PortBusInfoSize = DataSize;
-  DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool,
-                                               DataSize);
-  RtlCopyMemory(DeviceExtension->PortBusInfo,
-               AdapterInfo,
-               DataSize);
+  DPRINT("SpiInquirePort() done\n");
+}
+
+
+static ULONG
+SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo)
+{
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
+  PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
+  ULONG Bus;
+  ULONG Target;
+  ULONG Lun;
+  ULONG UnitCount;
+
+  DPRINT("SpiGetInquiryData() called\n");
+
+  /* Copy inquiry data to the port device extension */
+  AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
+
+  UnitInfo = (PSCSI_INQUIRY_DATA)
+       ((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
+        (sizeof(SCSI_BUS_DATA) * (AdapterBusInfo->NumberOfBuses - 1)));
+
+  for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
+    {
+      AdapterBusInfo->BusData[Bus].InitiatorBusId =
+       DeviceExtension->PortConfig.InitiatorBusId[Bus];
+      AdapterBusInfo->BusData[Bus].InquiryDataOffset =
+       (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
+
+      PrevUnit = NULL;
+      UnitCount = 0;
+
+      for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
+       {
+         for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
+           {
+             LunExtension = SpiGetLunExtension(DeviceExtension,
+                                               Bus,
+                                               Target,
+                                               Lun);
+             if (LunExtension != NULL)
+               {
+                 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
+                        Bus, Target, Lun);
+
+                 UnitInfo->PathId = Bus;
+                 UnitInfo->TargetId = Target;
+                 UnitInfo->Lun = Lun;
+                 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
+                 memcpy(&UnitInfo->InquiryData,
+                        &LunExtension->InquiryData,
+                        INQUIRYDATABUFFERSIZE);
+                 if (PrevUnit != NULL)
+                   PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
+                 PrevUnit = UnitInfo;
+                 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
+                 UnitCount++;
+               }
+           }
+       }
+      DPRINT("UnitCount: %lu\n", UnitCount);
+      AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
+      if (UnitCount == 0)
+       AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
+    }
 
-  ExFreePool(AdapterInfo);
+  DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
 
-  DPRINT("ScsiPortInquire() done\n");
+  return (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
 }
 
 
@@ -1457,93 +1763,93 @@ ScsiPortDpcForIsr(IN PKDPC Dpc,
   KIRQL oldIrql;
 
   DPRINT("ScsiPortDpcForIsr(Dpc %p  DpcDeviceObject %p  DpcIrp %p  DpcContext %p)\n",
-         Dpc, DpcDeviceObject, DpcIrp, DpcContext);
+        Dpc, DpcDeviceObject, DpcIrp, DpcContext);
 
   DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
 
   KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
   if (DeviceExtension->IrpFlags)
-  {
-  IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
-  Srb = IrpStack->Parameters.Scsi.Srb;
-
-  if (DeviceExtension->OriginalSrb != NULL)
     {
-      DPRINT("Got sense data!\n");
-
-      DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
-      DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
-      DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
-      DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
+      IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
+      Srb = IrpStack->Parameters.Scsi.Srb;
 
-      /* Copy sense data */
-      if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
+      if (DeviceExtension->OriginalSrb != NULL)
        {
-         RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
-                       &DeviceExtension->InternalSenseData,
-                       sizeof(SENSE_DATA));
-         DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
-       }
+         DPRINT("Got sense data!\n");
 
-      /* Clear current sense data */
-      RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
+         DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
+         DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
+         DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
+         DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
 
-      IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
-      DeviceExtension->OriginalSrb = NULL;
-    }
-  else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
-          (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
-    {
-      DPRINT("SCSIOP_REQUEST_SENSE required!\n");
+         /* Copy sense data */
+         if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
+           {
+             RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
+                           &DeviceExtension->InternalSenseData,
+                           sizeof(SENSE_DATA));
+             DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+           }
 
-      DeviceExtension->OriginalSrb = Srb;
-      IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
-                                                                 Srb);
-      KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
-      if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
-                                 ScsiPortStartPacket,
-                                 DeviceExtension))
-       {
-         DPRINT("Synchronization failed!\n");
+         /* Clear current sense data */
+         RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
 
-         DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-         DpcIrp->IoStatus.Information = 0;
-         IoCompleteRequest(DpcIrp,
-                           IO_NO_INCREMENT);
-         IoStartNextPacket(DpcDeviceObject,
-                           FALSE);
+         IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
+         DeviceExtension->OriginalSrb = NULL;
        }
+      else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
+              (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
+       {
+         DPRINT("SCSIOP_REQUEST_SENSE required!\n");
 
-      return;
-    }
+         DeviceExtension->OriginalSrb = Srb;
+         IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
+                                                                     Srb);
+         KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+         if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
+                                     ScsiPortStartPacket,
+                                     DeviceExtension))
+           {
+             DPRINT1("Synchronization failed!\n");
+
+             DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+             DpcIrp->IoStatus.Information = 0;
+             IoCompleteRequest(DpcIrp,
+                               IO_NO_INCREMENT);
+             IoStartNextPacket(DpcDeviceObject,
+                               FALSE);
+           }
 
-  DeviceExtension->CurrentIrp = NULL;
+         return;
+       }
 
+      DeviceExtension->CurrentIrp = NULL;
 
-//  DpcIrp->IoStatus.Information = 0;
-//  DpcIrp->IoStatus.Status = STATUS_SUCCESS;
+//      DpcIrp->IoStatus.Information = 0;
+//      DpcIrp->IoStatus.Status = STATUS_SUCCESS;
 
-  if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
-    {
-      DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
-      IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
-    }
+      if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
+       {
+         DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
+         IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
+       }
 
-  if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
-    {
-      DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
-      KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
-      IoStartNextPacket(DpcDeviceObject, FALSE);
+      if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
+       {
+         DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
+         KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+         IoStartNextPacket(DpcDeviceObject, FALSE);
+       }
+      else
+       {
+         KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+       }
     }
-    else
+  else
     {
       KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
     }
-  }
-  else
-  {
-    KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
-  }
+
   DPRINT("ScsiPortDpcForIsr() done\n");
 }
 
@@ -1608,7 +1914,7 @@ ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 
 /**********************************************************************
  * NAME                                                        INTERNAL
- *     ScsiPortBuildDeviceMap
+ *     SpiBuildDeviceMap
  *
  * DESCRIPTION
  *     Builds the registry device map of all device which are attached
@@ -1630,31 +1936,31 @@ ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
  */
 
 static NTSTATUS
-ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
-                      PUNICODE_STRING RegistryPath)
+SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                  PUNICODE_STRING RegistryPath)
 {
+  PSCSI_PORT_LUN_EXTENSION LunExtension;
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING KeyName;
   UNICODE_STRING ValueName;
   WCHAR NameBuffer[64];
   ULONG Disposition;
   HANDLE ScsiKey;
-  HANDLE ScsiPortKey;
-  HANDLE ScsiBusKey;
-  HANDLE ScsiInitiatorKey;
-  HANDLE ScsiTargetKey;
-  HANDLE ScsiLunKey;
+  HANDLE ScsiPortKey = NULL;
+  HANDLE ScsiBusKey = NULL;
+  HANDLE ScsiInitiatorKey = NULL;
+  HANDLE ScsiTargetKey = NULL;
+  HANDLE ScsiLunKey = NULL;
   ULONG BusNumber;
-  UCHAR CurrentTarget;
-  PSCSI_ADAPTER_BUS_INFO AdapterInfo;
-  PSCSI_INQUIRY_DATA UnitInfo;
-  PINQUIRYDATA InquiryData;
+  ULONG Target;
+  ULONG CurrentTarget;
+  ULONG Lun;
   PWCHAR DriverName;
   ULONG UlongData;
   PWCHAR TypeName;
   NTSTATUS Status;
 
-  DPRINT("ScsiPortBuildDeviceMap() called\n");
+  DPRINT("SpiBuildDeviceMap() called\n");
 
   if (DeviceExtension == NULL || RegistryPath == NULL)
     {
@@ -1811,8 +2117,7 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
       if (!NT_SUCCESS(Status))
        {
          DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
-         ZwClose(ScsiPortKey);
-         return(Status);
+         goto ByeBye;
        }
 
       /* Create 'Initiator Id X' key */
@@ -1838,50 +2143,78 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
       if (!NT_SUCCESS(Status))
        {
          DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
-         ZwClose(ScsiBusKey);
-         ZwClose(ScsiPortKey);
-         return(Status);
+         goto ByeBye;
        }
 
       /* FIXME: Are there any initiator values (??) */
 
       ZwClose(ScsiInitiatorKey);
+      ScsiInitiatorKey = NULL;
 
 
       /* Enumerate targets */
-      CurrentTarget = (UCHAR)-1;
+      CurrentTarget = (ULONG)-1;
       ScsiTargetKey = NULL;
-      AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
-      if (AdapterInfo->BusData[BusNumber].NumberOfLogicalUnits != 0)
+      for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
        {
-         UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
-           AdapterInfo->BusData[BusNumber].InquiryDataOffset);
-
-         while (AdapterInfo->BusData[BusNumber].InquiryDataOffset)
+         for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
            {
-             if (UnitInfo->TargetId != CurrentTarget)
+             LunExtension = SpiGetLunExtension(DeviceExtension,
+                                               BusNumber,
+                                               Target,
+                                               Lun);
+             if (LunExtension != NULL)
                {
-                 /* Close old target key */
-                 if (ScsiTargetKey != NULL)
+                 if (Target != CurrentTarget)
                    {
-                     ZwClose(ScsiTargetKey);
-                     ScsiTargetKey = NULL;
+                     /* Close old target key */
+                     if (ScsiTargetKey != NULL)
+                       {
+                         ZwClose(ScsiTargetKey);
+                         ScsiTargetKey = NULL;
+                       }
+
+                     /* Create 'Target Id X' key */
+                     DPRINT("      Target Id %lu\n", Target);
+                     swprintf(NameBuffer,
+                              L"Target Id %lu",
+                              Target);
+                     RtlInitUnicodeString(&KeyName,
+                                          NameBuffer);
+                     InitializeObjectAttributes(&ObjectAttributes,
+                                                &KeyName,
+                                                0,
+                                                ScsiBusKey,
+                                                NULL);
+                     Status = ZwCreateKey(&ScsiTargetKey,
+                                          KEY_ALL_ACCESS,
+                                          &ObjectAttributes,
+                                          0,
+                                          NULL,
+                                          REG_OPTION_VOLATILE,
+                                          &Disposition);
+                     if (!NT_SUCCESS(Status))
+                       {
+                         DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
+                         goto ByeBye;
+                       }
+
+                     CurrentTarget = Target;
                    }
 
-                 /* Create 'Target Id X' key */
-                 DPRINT("      Target Id %u\n",
-                        UnitInfo->TargetId);
+                 /* Create 'Logical Unit Id X' key */
+                 DPRINT("        Logical Unit Id %lu\n", Lun);
                  swprintf(NameBuffer,
-                          L"Target Id %u",
-                          UnitInfo->TargetId);
+                          L"Logical Unit Id %lu",
+                          Lun);
                  RtlInitUnicodeString(&KeyName,
                                       NameBuffer);
                  InitializeObjectAttributes(&ObjectAttributes,
                                             &KeyName,
                                             0,
-                                            ScsiBusKey,
+                                            ScsiTargetKey,
                                             NULL);
-                 Status = ZwCreateKey(&ScsiTargetKey,
+                 Status = ZwCreateKey(&ScsiLunKey,
                                       KEY_ALL_ACCESS,
                                       &ObjectAttributes,
                                       0,
@@ -1891,132 +2224,82 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                  if (!NT_SUCCESS(Status))
                    {
                      DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
-                     ZwClose(ScsiBusKey);
-                     ZwClose(ScsiPortKey);
-                     return(Status);
+                     goto ByeBye;
                    }
 
-                 CurrentTarget = UnitInfo->TargetId;
-               }
-
-             /* Create 'Logical Unit Id X' key */
-             DPRINT("        Logical Unit Id %u\n",
-                    UnitInfo->Lun);
-             swprintf(NameBuffer,
-                      L"Logical Unit Id %u",
-                      UnitInfo->Lun);
-             RtlInitUnicodeString(&KeyName,
-                                  NameBuffer);
-             InitializeObjectAttributes(&ObjectAttributes,
-                                        &KeyName,
+                 /* Set 'Identifier' (REG_SZ) value */
+                 swprintf(NameBuffer,
+                          L"%.8S%.16S%.4S",
+                          LunExtension->InquiryData.VendorId,
+                          LunExtension->InquiryData.ProductId,
+                          LunExtension->InquiryData.ProductRevisionLevel);
+                 DPRINT("          Identifier = '%S'\n", NameBuffer);
+                 RtlInitUnicodeString(&ValueName,
+                                      L"Identifier");
+                 Status = ZwSetValueKey(ScsiLunKey,
+                                        &ValueName,
                                         0,
-                                        ScsiTargetKey,
-                                        NULL);
-             Status = ZwCreateKey(&ScsiLunKey,
-                                  KEY_ALL_ACCESS,
-                                  &ObjectAttributes,
-                                  0,
-                                  NULL,
-                                  REG_OPTION_VOLATILE,
-                                  &Disposition);
-             if (!NT_SUCCESS(Status))
-               {
-                 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
-                 ZwClose(ScsiTargetKey);
-                 ZwClose(ScsiBusKey);
-                 ZwClose(ScsiPortKey);
-                 return(Status);
-               }
+                                        REG_SZ,
+                                        NameBuffer,
+                                        (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
+                 if (!NT_SUCCESS(Status))
+                   {
+                     DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
+                     goto ByeBye;
+                   }
 
-             /* Set values for logical unit */
-             InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
-
-             /* Set 'Identifier' (REG_SZ) value */
-             swprintf(NameBuffer,
-                      L"%.8S%.16S%.4S",
-                      InquiryData->VendorId,
-                      InquiryData->ProductId,
-                      InquiryData->ProductRevisionLevel);
-             DPRINT("          Identifier = '%S'\n",
-                    NameBuffer);
-             RtlInitUnicodeString(&ValueName,
-                                  L"Identifier");
-             Status = ZwSetValueKey(ScsiLunKey,
-                                    &ValueName,
-                                    0,
-                                    REG_SZ,
-                                    NameBuffer,
-                                    (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
-             if (!NT_SUCCESS(Status))
-               {
-                 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
-                 ZwClose(ScsiLunKey);
-                 ZwClose(ScsiTargetKey);
-                 ZwClose(ScsiBusKey);
-                 ZwClose(ScsiPortKey);
-                 return(Status);
-               }
+                 /* Set 'Type' (REG_SZ) value */
+                 switch (LunExtension->InquiryData.DeviceType)
+                   {
+                     case 0:
+                       TypeName = L"DiskPeripheral";
+                       break;
+                     case 1:
+                       TypeName = L"TapePeripheral";
+                       break;
+                     case 2:
+                       TypeName = L"PrinterPeripheral";
+                       break;
+                     case 4:
+                       TypeName = L"WormPeripheral";
+                       break;
+                     case 5:
+                       TypeName = L"CdRomPeripheral";
+                       break;
+                     case 6:
+                       TypeName = L"ScannerPeripheral";
+                       break;
+                     case 7:
+                       TypeName = L"OpticalDiskPeripheral";
+                       break;
+                     case 8:
+                       TypeName = L"MediumChangerPeripheral";
+                       break;
+                     case 9:
+                       TypeName = L"CommunicationPeripheral";
+                       break;
+                     default:
+                       TypeName = L"OtherPeripheral";
+                       break;
+                   }
+                 DPRINT("          Type = '%S'\n", TypeName);
+                 RtlInitUnicodeString(&ValueName,
+                                      L"Type");
+                 Status = ZwSetValueKey(ScsiLunKey,
+                                        &ValueName,
+                                        0,
+                                        REG_SZ,
+                                        TypeName,
+                                        (wcslen(TypeName) + 1) * sizeof(WCHAR));
+                 if (!NT_SUCCESS(Status))
+                   {
+                     DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
+                     goto ByeBye;
+                   }
 
-             /* Set 'Type' (REG_SZ) value */
-             switch (InquiryData->DeviceType)
-               {
-                 case 0:
-                   TypeName = L"DiskPeripheral";
-                   break;
-                 case 1:
-                   TypeName = L"TapePeripheral";
-                   break;
-                 case 2:
-                   TypeName = L"PrinterPeripheral";
-                   break;
-                 case 4:
-                   TypeName = L"WormPeripheral";
-                   break;
-                 case 5:
-                   TypeName = L"CdRomPeripheral";
-                   break;
-                 case 6:
-                   TypeName = L"ScannerPeripheral";
-                   break;
-                 case 7:
-                   TypeName = L"OpticalDiskPeripheral";
-                   break;
-                 case 8:
-                   TypeName = L"MediumChangerPeripheral";
-                   break;
-                 case 9:
-                   TypeName = L"CommunicationPeripheral";
-                   break;
-                 default:
-                   TypeName = L"OtherPeripheral";
-                   break;
-               }
-             DPRINT("          Type = '%S'\n", TypeName);
-             RtlInitUnicodeString(&ValueName,
-                                  L"Type");
-             Status = ZwSetValueKey(ScsiLunKey,
-                                    &ValueName,
-                                    0,
-                                    REG_SZ,
-                                    TypeName,
-                                    (wcslen(TypeName) + 1) * sizeof(WCHAR));
-             if (!NT_SUCCESS(Status))
-               {
-                 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
                  ZwClose(ScsiLunKey);
-                 ZwClose(ScsiTargetKey);
-                 ZwClose(ScsiBusKey);
-                 ZwClose(ScsiPortKey);
-                 return(Status);
+                 ScsiLunKey = NULL;
                }
-
-             ZwClose(ScsiLunKey);
-
-             if (UnitInfo->NextInquiryDataOffset == 0)
-               break;
-
-             UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
-               UnitInfo->NextInquiryDataOffset);
            }
 
          /* Close old target key */
@@ -2027,14 +2310,29 @@ ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
            }
        }
 
-       ZwClose(ScsiBusKey);
-     }
+      ZwClose(ScsiBusKey);
+      ScsiBusKey = NULL;
+    }
 
-  ZwClose(ScsiPortKey);
+ByeBye:
+  if (ScsiLunKey != NULL)
+    ZwClose (ScsiLunKey);
 
-  DPRINT("ScsiPortBuildDeviceMap() done\n");
+  if (ScsiInitiatorKey != NULL)
+    ZwClose (ScsiInitiatorKey);
 
-  return(Status);
+  if (ScsiTargetKey != NULL)
+    ZwClose (ScsiTargetKey);
+
+  if (ScsiBusKey != NULL)
+    ZwClose (ScsiBusKey);
+
+  if (ScsiPortKey != NULL)
+    ZwClose (ScsiPortKey);
+
+  DPRINT("SpiBuildDeviceMap() done\n");
+
+  return Status;
 }
 
 /* EOF */