Sync to trunk head(r38096)
[reactos.git] / reactos / drivers / storage / scsiport / scsiport.c
index 5a3ccfd..7485c13 100644 (file)
@@ -16,8 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Storage Stack
  * FILE:            drivers/storage/scsiport/scsiport.c
 
 #include "scsiport_int.h"
 
-#ifdef _MSC_VER
-  #define STDCALL
-  #define DDKAPI
-#endif
-
 ULONG InternalDebugLevel = 0x00;
 
 /* TYPES *********************************************************************/
@@ -64,27 +58,31 @@ SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
                     IN ULONG BusNumber,
                     IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
                    IN PIRP Irp);
 
 static DRIVER_DISPATCH ScsiPortDispatchScsi;
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp);
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
                      IN PIRP Irp);
 
 static DRIVER_STARTIO ScsiPortStartIo;
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp);
 
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortStartPacket(IN OUT PVOID Context);
 
+IO_ALLOCATION_ACTION
+NTAPI
+SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp,
+                  PVOID MapRegisterBase, PVOID Context);
 
 static PSCSI_PORT_LUN_EXTENSION
 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
@@ -95,6 +93,11 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                    IN UCHAR TargetId,
                    IN UCHAR Lun);
 
+static PSCSI_REQUEST_BLOCK_INFO
+SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                         PSCSI_PORT_LUN_EXTENSION LunExtension,
+                         PSCSI_REQUEST_BLOCK Srb);
+
 static NTSTATUS
 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
                IN PSCSI_LUN_INFO LunInfo);
@@ -107,27 +110,33 @@ SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                   IN PIRP Irp);
 
 static PSCSI_REQUEST_BLOCK_INFO
-SpiGetSrbData(IN PVOID DeviceExtension,
+SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
               IN UCHAR PathId,
               IN UCHAR TargetId,
               IN UCHAR Lun,
               IN UCHAR QueueTag);
 
-static KSERVICE_ROUTINE ScsiPortIsr;
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
            IN PVOID ServiceContext);
 
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortDpcForIsr(IN PKDPC Dpc,
                  IN PDEVICE_OBJECT DpcDeviceObject,
                  IN PIRP DpcIrp,
                  IN PVOID DpcContext);
 
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
                PVOID Context);
 
+IO_ALLOCATION_ACTION
+NTAPI
+ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
+                               IN PIRP Irp,
+                               IN PVOID MapRegisterBase,
+                               IN PVOID Context);
+
 static NTSTATUS
 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                   PUNICODE_STRING RegistryPath);
@@ -140,22 +149,22 @@ SpiSendRequestSense(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                     IN PSCSI_REQUEST_BLOCK Srb);
 
 static IO_COMPLETION_ROUTINE SpiCompletionRoutine;
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
                      PIRP Irp,
                      PVOID Context);
 
 static VOID
-STDCALL
+NTAPI
 SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                            IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
                            OUT PBOOLEAN NeedToCallStartIo);
 
-VOID STDCALL
+VOID NTAPI
 SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                          IN PSCSI_PORT_LUN_EXTENSION LunExtension);
 
-VOID STDCALL
+VOID NTAPI
 SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
                     IN PVOID DeviceObject,
                     IN PVOID SystemArgument1,
@@ -168,7 +177,7 @@ SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                     PPORT_CONFIGURATION_INFORMATION ConfigInfo,
                     BOOLEAN FirstCall);
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 SpQueryDeviceCallout(IN PVOID  Context,
                      IN PUNICODE_STRING  PathName,
                      IN INTERFACE_TYPE  BusType,
@@ -232,7 +241,7 @@ SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCa
  *     Status.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
 {
@@ -285,25 +294,120 @@ ScsiDebugPrint(IN ULONG DebugPrintLevel,
     DbgPrint(Buffer);
 }
 
+/* An internal helper function for ScsiPortCompleteRequest */
+VOID
+NTAPI
+SpiCompleteRequest(IN PVOID HwDeviceExtension,
+                   IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
+                   IN UCHAR SrbStatus)
+{
+    PSCSI_REQUEST_BLOCK Srb;
+
+    /* Get current SRB */
+    Srb = SrbInfo->Srb;
+
+    /* Return if there is no SRB or it is not active */
+    if (!Srb || !(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) return;
+
+    /* Set status */
+    Srb->SrbStatus = SrbStatus;
+
+    /* Set data transfered to 0 */
+    Srb->DataTransferLength = 0;
+
+    /* Notify */
+    ScsiPortNotification(RequestComplete,
+                         HwDeviceExtension,
+                         Srb);
+}
 
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
-                       IN UCHAR PathId,
-                       IN UCHAR TargetId,
-                       IN UCHAR Lun,
-                       IN UCHAR SrbStatus)
+                        IN UCHAR PathId,
+                        IN UCHAR TargetId,
+                        IN UCHAR Lun,
+                        IN UCHAR SrbStatus)
 {
-  DPRINT("ScsiPortCompleteRequest()\n");
-  UNIMPLEMENTED;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PSCSI_PORT_LUN_EXTENSION LunExtension;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+    PLIST_ENTRY ListEntry;
+    ULONG BusNumber;
+    ULONG Target;
+
+    DPRINT("ScsiPortCompleteRequest() called\n");
+
+    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                        SCSI_PORT_DEVICE_EXTENSION,
+                                        MiniPortDeviceExtension);
+
+    /* Go through all buses */
+    for (BusNumber = 0; BusNumber < 8; BusNumber++)
+    {
+        /* Go through all targets */
+        for (Target = 0; Target < DeviceExtension->MaxTargedIds; Target++)
+        {
+            /* Get logical unit list head */
+            LunExtension = DeviceExtension->LunExtensionList[Target % 8];
+
+            /* Go through all logical units */
+            while (LunExtension)
+            {
+                /* Now match what caller asked with what we are at now */
+                if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
+                    (TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
+                    (Lun == SP_UNTAGGED || Lun == LunExtension->Lun))
+                {
+                    /* Yes, that's what caller asked for. Complete abort requests */
+                    if (LunExtension->CompletedAbortRequests)
+                    {
+                        /* TODO: Save SrbStatus in this request */
+                        DPRINT1("Completing abort request without setting SrbStatus!\n");
+
+                        /* Issue a notification request */
+                        ScsiPortNotification(RequestComplete,
+                                             HwDeviceExtension,
+                                             LunExtension->CompletedAbortRequests);
+                    }
+
+                    /* Complete the request using our helper */
+                    SpiCompleteRequest(HwDeviceExtension,
+                                       &LunExtension->SrbInfo,
+                                       SrbStatus);
+
+                    /* Go through the queue and complete everything there too */
+                    ListEntry = LunExtension->SrbInfo.Requests.Flink;
+                    while (ListEntry != &LunExtension->SrbInfo.Requests)
+                    {
+                        /* Get the actual SRB info entry */
+                        SrbInfo = CONTAINING_RECORD(ListEntry,
+                                                    SCSI_REQUEST_BLOCK_INFO,
+                                                    Requests);
+
+                        /* Complete it */
+                        SpiCompleteRequest(HwDeviceExtension,
+                                           SrbInfo,
+                                           SrbStatus);
+
+                        /* Advance to the next request in queue */
+                        ListEntry = SrbInfo->Requests.Flink;
+                    }
+                }
+
+                /* Advance to the next one */
+                LunExtension = LunExtension->Next;
+            }
+        }
+    }
 }
 
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
 {
   DPRINT("ScsiPortFlushDma()\n");
@@ -314,7 +418,7 @@ ScsiPortFlushDma(IN PVOID HwDeviceExtension)
 /*
  * @implemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
                       IN PVOID MappedAddress)
 {
@@ -327,7 +431,6 @@ ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
                                         SCSI_PORT_DEVICE_EXTENSION,
                                         MiniPortDeviceExtension);
 
-
     /* Initialize our pointers */
     NextMa = DeviceExtension->MappedAddressList;
     LastMa = NextMa;
@@ -367,7 +470,7 @@ ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
 /*
  * @implemented
  */
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortGetBusData(IN PVOID DeviceExtension,
                   IN ULONG BusDataType,
                   IN ULONG SystemIoBusNumber,
@@ -375,18 +478,49 @@ ScsiPortGetBusData(IN PVOID DeviceExtension,
                   IN PVOID Buffer,
                   IN ULONG Length)
 {
-  return(HalGetBusData(BusDataType,
-                      SystemIoBusNumber,
-                      SlotNumber,
-                      Buffer,
-                      Length));
+    DPRINT("ScsiPortGetBusData()\n");
+
+    if (Length)
+    {
+        /* If Length is non-zero, just forward the call to
+        HalGetBusData() function */
+        return HalGetBusData(BusDataType,
+                             SystemIoBusNumber,
+                             SlotNumber,
+                             Buffer,
+                             Length);
+    }
+
+    /* We have a more complex case here */
+    UNIMPLEMENTED;
+    return 0;
 }
 
+/*
+ * @implemented
+ */
+ULONG NTAPI
+ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
+                           IN ULONG BusDataType,
+                           IN ULONG SystemIoBusNumber,
+                           IN ULONG SlotNumber,
+                           IN PVOID Buffer,
+                           IN ULONG Offset,
+                           IN ULONG Length)
+{
+    DPRINT("ScsiPortSetBusDataByOffset()\n");
+    return HalSetBusDataByOffset(BusDataType,
+                                 SystemIoBusNumber,
+                                 SlotNumber,
+                                 Buffer,
+                                 Offset,
+                                 Length);
+}
 
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
                      IN ULONG SystemIoBusNumber,
@@ -418,7 +552,7 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
 
     /* i/o space */
     if (AddressSpace != 0)
-        return((PVOID)TranslatedAddress.u.LowPart);
+        return((PVOID)(ULONG_PTR)TranslatedAddress.QuadPart);
 
     MappedAddress = MmMapIoSpace(TranslatedAddress,
                                  NumberOfBytes,
@@ -443,9 +577,9 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
 }
 
 /*
- * @implemented
+ * @unimplemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
                       IN UCHAR PathId,
                       IN UCHAR TargetId,
@@ -486,103 +620,75 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-SCSI_PHYSICAL_ADDRESS STDCALL
+SCSI_PHYSICAL_ADDRESS NTAPI
 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
-                          IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
-                          IN PVOID VirtualAddress,
-                          OUT ULONG *Length)
+                           IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
+                           IN PVOID VirtualAddress,
+                           OUT ULONG *Length)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  SCSI_PHYSICAL_ADDRESS PhysicalAddress;
-  SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
-  ULONG BufferLength = 0;
-  ULONG Offset;
-  PVOID EndAddress;
-
-  DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
-        HwDeviceExtension, Srb, VirtualAddress, Length);
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    SCSI_PHYSICAL_ADDRESS PhysicalAddress;
+    ULONG BufferLength = 0;
+    ULONG Offset;
+    PSCSI_SG_ADDRESS SGList;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
 
-  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
-                                     SCSI_PORT_DEVICE_EXTENSION,
-                                     MiniPortDeviceExtension);
+    DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
+        HwDeviceExtension, Srb, VirtualAddress, Length);
 
-  *Length = 0;
+    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                        SCSI_PORT_DEVICE_EXTENSION,
+                                        MiniPortDeviceExtension);
 
-  if (Srb == NULL)
+    if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
     {
-      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;
-       }
+        /* Simply look it up in the allocated common buffer */
+        Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
 
-      PhysicalAddress.QuadPart =
-       DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
-      BufferLength = DeviceExtension->CommonBufferLength - Offset;
+        BufferLength = DeviceExtension->CommonBufferLength - Offset;
+        PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
     }
-  else
+    else if (DeviceExtension->MapRegisters)
     {
-      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;
-       }
-
-      PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
-      if (PhysicalAddress.QuadPart == 0LL)
-       {
-         return PhysicalAddress;
-       }
+        /* Scatter-gather list must be used */
+        SrbInfo = SpiGetSrbData(DeviceExtension,
+                               Srb->PathId,
+                               Srb->TargetId,
+                               Srb->Lun,
+                               Srb->QueueTag);
+
+        SGList = SrbInfo->ScatterGather;
+
+        /* Find needed item in the SG list */
+        Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer;
+        while (Offset >= SGList->Length)
+        {
+            Offset -= SGList->Length;
+            SGList++;
+        }
 
-      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 ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
-       {
-         NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
-         if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
-           {
-             break;
-           }
-         BufferLength += PAGE_SIZE;
-       }
-      if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
-       {
-         BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
-       }
+        /* We're done, store length and physical address */
+        BufferLength = SGList->Length - Offset;
+        PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset;
+    }
+    else
+    {
+        /* Nothing */
+        *Length = 0;
+        PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
     }
 
-  *Length = BufferLength;
-
-  return PhysicalAddress;
+    *Length = BufferLength;
+    return PhysicalAddress;
 }
 
 
 /*
  * @unimplemented
  */
-PSCSI_REQUEST_BLOCK STDCALL
+PSCSI_REQUEST_BLOCK NTAPI
 ScsiPortGetSrb(IN PVOID DeviceExtension,
               IN UCHAR PathId,
               IN UCHAR TargetId,
@@ -598,7 +704,7 @@ ScsiPortGetSrb(IN PVOID DeviceExtension,
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
                             IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
                             IN ULONG NumberOfBytes)
@@ -717,7 +823,7 @@ SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCa
     if (!DeviceExtension->AdapterObject)
     {
         /* From nonpaged pool if there is no DMA */
-        CommonBuffer = ExAllocatePool(NonPagedPool, CommonBufferLength);
+        CommonBuffer = ExAllocatePoolWithTag(NonPagedPool, CommonBufferLength, TAG_SCSIPORT);
     }
     else
     {
@@ -780,28 +886,29 @@ SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCa
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
-                         IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
+                          IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  ULONG Offset;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    ULONG Offset;
 
-  DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
-        HwDeviceExtension, PhysicalAddress.QuadPart);
+    DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
+        HwDeviceExtension, PhysicalAddress.QuadPart);
 
-  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
-                                     SCSI_PORT_DEVICE_EXTENSION,
-                                     MiniPortDeviceExtension);
+    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+                                        SCSI_PORT_DEVICE_EXTENSION,
+                                        MiniPortDeviceExtension);
 
-  if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
-    return NULL;
+    if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
+        return NULL;
 
-  Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
-  if (Offset >= DeviceExtension->CommonBufferLength)
-    return NULL;
+    Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
+
+    if (Offset >= DeviceExtension->CommonBufferLength)
+        return NULL;
 
-  return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
+    return (PVOID)((ULONG_PTR)DeviceExtension->SrbExtensionBuffer + Offset);
 }
 
 static VOID
@@ -824,7 +931,7 @@ SpiInitOpenKeys(PCONFIGURATION_INFO ConfigInfo, PUNICODE_STRING RegistryPath)
 
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
+        DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
         ConfigInfo->ServiceKey = NULL;
     }
 
@@ -853,18 +960,21 @@ SpiInitOpenKeys(PCONFIGURATION_INFO ConfigInfo, PUNICODE_STRING RegistryPath)
         }
     }
 
-    /* Open the Device key */
-    RtlInitUnicodeString(&KeyName, L"Device");
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               ConfigInfo->ServiceKey,
-                               NULL);
+    if (ConfigInfo->ServiceKey != NULL)
+    {
+        /* Open the Device key */
+        RtlInitUnicodeString(&KeyName, L"Device");
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &KeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   ConfigInfo->ServiceKey,
+                                   NULL);
 
-    /* We don't check for failure here - not needed */
-    ZwOpenKey(&ConfigInfo->DeviceKey,
-              KEY_READ,
-              &ObjectAttributes);
+        /* We don't check for failure here - not needed */
+        ZwOpenKey(&ConfigInfo->DeviceKey,
+                  KEY_READ,
+                  &ObjectAttributes);
+    }
 }
 
 
@@ -897,7 +1007,7 @@ SpiInitOpenKeys(PCONFIGURATION_INFO ConfigInfo, PUNICODE_STRING RegistryPath)
  * @implemented
  */
 
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortInitialize(IN PVOID Argument1,
                   IN PVOID Argument2,
                   IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
@@ -1077,7 +1187,10 @@ CreatePortConfig:
                                      FirstConfigCall);
 
         if (!NT_SUCCESS(Status))
+        {
+            DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status);
             break;
+        }
 
         /* Allocate and initialize port configuration info */
         PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
@@ -1110,8 +1223,8 @@ CreatePortConfig:
             PortConfig->AccessRanges = (PVOID)(PortConfig+1);
 
             /* Align to LONGLONG */
-            PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) + 7);
-            PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) & ~7);
+            PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7);
+            PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7);
 
             /* Copy the data */
             RtlCopyMemory(PortConfig->AccessRanges,
@@ -1586,7 +1699,7 @@ CreatePortConfig:
     if (ConfigInfo.Parameter != NULL)
         ExFreePool(ConfigInfo.Parameter);
 
-    DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %b!\n",
+    DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n",
         Status, DeviceFound);
 
     return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
@@ -1620,7 +1733,7 @@ SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 
             LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
 
-            while (!LunInfo)
+            while (LunInfo)
             {
                 /* Free current, but save pointer to the next one */
                 Ptr = LunInfo->Next;
@@ -1652,7 +1765,7 @@ SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 
     /* Free common buffer (if it exists) */
     if (DeviceExtension->SrbExtensionBuffer != NULL &&
-        DeviceExtension->CommonBufferSize != 0)
+        DeviceExtension->CommonBufferLength != 0)
     {
             if (!DeviceExtension->AdapterObject)
             {
@@ -1660,13 +1773,11 @@ SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
             }
             else
             {
-#if 0
                 HalFreeCommonBuffer(DeviceExtension->AdapterObject,
-                                    DeviceExtension->CommonBufferSize,
-                                    DeviceExtension->PhysicalCommonBuffer,
+                                    DeviceExtension->CommonBufferLength,
+                                    DeviceExtension->PhysicalAddress,
                                     DeviceExtension->SrbExtensionBuffer,
                                     FALSE);
-#endif
             }
     }
 
@@ -1691,12 +1802,10 @@ SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
     IoDeleteDevice(DeviceExtension->DeviceObject);
 }
 
-
-
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb,
                      IN PVOID LogicalAddress,
@@ -1706,11 +1815,10 @@ ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
   UNIMPLEMENTED;
 }
 
-
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortLogError(IN PVOID HwDeviceExtension,
                 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
                 IN UCHAR PathId,
@@ -1731,11 +1839,10 @@ ScsiPortLogError(IN PVOID HwDeviceExtension,
   DPRINT("ScsiPortLogError() done\n");
 }
 
-
 /*
  * @implemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortMoveMemory(OUT PVOID Destination,
                   IN PVOID Source,
                   IN ULONG Length)
@@ -1827,72 +1934,68 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
         DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
         break;
 
-      case NextLuRequest:
-       {
-         UCHAR PathId;
-         UCHAR TargetId;
-         UCHAR Lun;
+    case NextLuRequest:
+        {
+            UCHAR PathId;
+            UCHAR TargetId;
+            UCHAR Lun;
+            PSCSI_PORT_LUN_EXTENSION LunExtension;
 
-         PathId = (UCHAR) va_arg (ap, int);
-         TargetId = (UCHAR) va_arg (ap, int);
-         Lun = (UCHAR) va_arg (ap, int);
+            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! */
-          ASSERT(FALSE);
+            DPRINT("Notify: NextLuRequest(PathId %u  TargetId %u  Lun %u)\n",
+                PathId, TargetId, Lun);
 
-//       DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
-//       DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
+            /* Mark it in the flags field */
+            DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
 
-         /* Hack! */
-//       DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
-       }
-       break;
+            /* Get the LUN extension */
+            LunExtension = SpiGetLunExtension(DeviceExtension,
+                                              PathId,
+                                              TargetId,
+                                              Lun);
+
+            /* If returned LunExtension is NULL, break out */
+            if (!LunExtension) break;
+
+            /* This request should not be processed if */
+            if ((LunExtension->ReadyLun) ||
+                (LunExtension->SrbInfo.Srb))
+            {
+                /* Nothing to do here */
+                break;
+            }
+
+            /* Add this LUN to the list */
+            LunExtension->ReadyLun = DeviceExtension->InterruptData.ReadyLun;
+            DeviceExtension->InterruptData.ReadyLun = LunExtension;
+          }
+          break;
 
       case ResetDetected:
-       DPRINT1("Notify: ResetDetected\n");
-       /* FIXME: ??? */
-       break;
+          DPRINT("Notify: ResetDetected\n");
+          /* Add RESET flags */
+          DeviceExtension->InterruptData.Flags |=
+                SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED;
+          break;
 
       default:
        DPRINT1 ("Unsupported notification %lu\n", NotificationType);
        break;
     }
 
-  va_end(ap);
+    va_end(ap);
 
     /* Request a DPC after we're done with the interrupt */
     DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED;
 }
 
-
 /*
  * @implemented
  */
-ULONG STDCALL
-ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
-                          IN ULONG BusDataType,
-                          IN ULONG SystemIoBusNumber,
-                          IN ULONG SlotNumber,
-                          IN PVOID Buffer,
-                          IN ULONG Offset,
-                          IN ULONG Length)
-{
-  DPRINT("ScsiPortSetBusDataByOffset()\n");
-  return(HalSetBusDataByOffset(BusDataType,
-                              SystemIoBusNumber,
-                              SlotNumber,
-                              Buffer,
-                              Offset,
-                              Length));
-}
-
-
-/*
- * @implemented
- */
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
                      IN ULONG SystemIoBusNumber,
@@ -2290,7 +2393,7 @@ SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
  *     Status.
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
                    IN PIRP Irp)
 {
@@ -2402,7 +2505,7 @@ SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
  *     NTSTATUS
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp)
 {
@@ -2643,7 +2746,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
  *     NTSTATUS
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
                      IN PIRP Irp)
 {
@@ -2666,7 +2769,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;
@@ -2717,7 +2820,7 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
 }
 
 
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp)
 {
@@ -2727,6 +2830,7 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
     PSCSI_REQUEST_BLOCK Srb;
     PSCSI_REQUEST_BLOCK_INFO SrbInfo;
     LONG CounterResult;
+    NTSTATUS Status;
 
     DPRINT("ScsiPortStartIo() called!\n");
 
@@ -2749,9 +2853,21 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
     if (DeviceExtension->NeedSrbDataAlloc ||
         DeviceExtension->NeedSrbExtensionAlloc)
     {
-        /* TODO: Implement */
-        ASSERT(FALSE);
-        SrbInfo = NULL;
+        /* Allocate them */
+        SrbInfo = SpiAllocateSrbStructures(DeviceExtension,
+                                           LunExtension,
+                                           Srb);
+
+        /* Couldn't alloc one or both data structures, return */
+        if (SrbInfo == NULL)
+        {
+            /* We have to call IoStartNextPacket, because this request
+               was not started */
+            if (LunExtension->Flags & LUNEX_REQUEST_PENDING)
+                IoStartNextPacket(DeviceObject, FALSE);
+
+            return;
+        }
     }
     else
     {
@@ -2787,7 +2903,7 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
         // Store the MDL virtual address in SrbInfo structure
         SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress);
 
-        if (DeviceExtension->MapBuffers && Irp->MdlAddress)
+        if (DeviceExtension->MapBuffers)
         {
             /* Calculate offset within DataBuffer */
             SrbInfo->DataOffset = MmGetSystemAddressForMdl(Irp->MdlAddress);
@@ -2806,7 +2922,6 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
 
         if (DeviceExtension->MapRegisters)
         {
-#if 0
             /* Calculate number of needed map registers */
             SrbInfo->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
                     Srb->DataBuffer,
@@ -2837,9 +2952,6 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
 
             /* Control goes to SpiAdapterControl */
             return;
-#else
-            ASSERT(FALSE);
-#endif
         }
     }
 
@@ -2850,23 +2962,17 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
         DeviceExtension->AdapterObject != NULL &&
         !DeviceExtension->MapRegisters)
     {
-#if 0
         IoAllocateAdapterChannel(
             DeviceExtension->AdapterObject,
             DeviceObject,
             DeviceExtension->PortCapabilities.MaximumPhysicalPages,
-            ScsiPortAllocationRoutine,
+            ScsiPortAllocateAdapterChannel,
             LunExtension
             );
 
         return;
-#else
-        /* TODO: DMA is not implemented yet */
-        ASSERT(FALSE);
-#endif
     }
 
-
     KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
 
     if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
@@ -2881,14 +2987,18 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
 
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
+    else
+    {
+        /* Release the spinlock only */
+        KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+    }
 
-    KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
 
     DPRINT("ScsiPortStartIo() done\n");
 }
 
 
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortStartPacket(IN OUT PVOID Context)
 {
     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
@@ -2896,6 +3006,7 @@ ScsiPortStartPacket(IN OUT PVOID Context)
     PSCSI_REQUEST_BLOCK Srb;
     PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
     PSCSI_PORT_LUN_EXTENSION LunExtension;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
     BOOLEAN Result;
     BOOLEAN StartTimer;
 
@@ -2945,8 +3056,6 @@ ScsiPortStartPacket(IN OUT PVOID Context)
         /* Is this an abort request? */
         if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
         {
-            PSCSI_REQUEST_BLOCK_INFO SrbInfo;
-
             /* Get pointer to SRB info structure */
             SrbInfo = SpiGetSrbData(DeviceExtension,
                                     Srb->PathId,
@@ -3019,8 +3128,13 @@ ScsiPortStartPacket(IN OUT PVOID Context)
         /* If it's tagged - special thing */
         if (Srb->QueueTag != SP_UNTAGGED)
         {
-            /* TODO: Support tagged requests */
-            ASSERT(FALSE);
+            SrbInfo = &DeviceExtension->SrbInfo[Srb->QueueTag - 1];
+
+            /* Chek for consistency */
+            ASSERT(SrbInfo->Requests.Blink == NULL);
+
+            /* Insert it into the list of requests */
+            InsertTailList(&LunExtension->SrbInfo.Requests, &SrbInfo->Requests);
         }
     }
 
@@ -3038,6 +3152,90 @@ ScsiPortStartPacket(IN OUT PVOID Context)
     return Result;
 }
 
+IO_ALLOCATION_ACTION
+NTAPI
+SpiAdapterControl(PDEVICE_OBJECT DeviceObject,
+                  PIRP Irp,
+                  PVOID MapRegisterBase,
+                  PVOID Context)
+{
+    PSCSI_REQUEST_BLOCK Srb;
+    PSCSI_SG_ADDRESS ScatterGatherList;
+    KIRQL CurrentIrql;
+    PIO_STACK_LOCATION IrpStack;
+    ULONG TotalLength = 0;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PUCHAR DataVA;
+    BOOLEAN WriteToDevice;
+
+    /* Get pointers to SrbInfo and DeviceExtension */
+    SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context;
+    DeviceExtension = DeviceObject->DeviceExtension;
+
+    /* Get pointer to SRB */
+    IrpStack = IoGetCurrentIrpStackLocation(Irp);
+    Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
+
+    /* Depending on the map registers number, we allocate
+       either from NonPagedPool, or from our static list */
+    if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST)
+    {
+        SrbInfo->ScatterGather = ExAllocatePoolWithTag(
+            NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS), TAG_SCSIPORT);
+
+        if (SrbInfo->ScatterGather == NULL)
+            ASSERT(FALSE);
+
+        Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL;
+    }
+    else
+    {
+        SrbInfo->ScatterGather = SrbInfo->ScatterGatherList;
+    }
+
+    /* Use chosen SG list source */
+    ScatterGatherList = SrbInfo->ScatterGather;
+
+    /* Save map registers base */
+    SrbInfo->BaseOfMapRegister = MapRegisterBase;
+
+    /* Determine WriteToDevice flag */
+    WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
+
+    /* Get virtual address of the data buffer */
+    DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) +
+                ((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset);
+
+    /* Build the actual SG list */
+    while (TotalLength < Srb->DataTransferLength)
+    {
+        if (!ScatterGatherList)
+            break;
+
+        ScatterGatherList->Length = Srb->DataTransferLength - TotalLength;
+        ScatterGatherList->PhysicalAddress = IoMapTransfer(NULL,
+                                                           Irp->MdlAddress,
+                                                           MapRegisterBase,
+                                                           DataVA + TotalLength,
+                                                           &ScatterGatherList->Length,
+                                                           WriteToDevice);
+
+        TotalLength += ScatterGatherList->Length;
+        ScatterGatherList++;
+    }
+
+    /* Schedule an active request */
+    InterlockedIncrement(&DeviceExtension->ActiveRequestCounter );
+    KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql);
+    KeSynchronizeExecution(DeviceExtension->Interrupt,
+                           ScsiPortStartPacket,
+                           DeviceObject);
+    KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql);
+
+    return DeallocateObjectKeepRegisters;
+}
+
 static PSCSI_PORT_LUN_EXTENSION
 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 {
@@ -3113,6 +3311,155 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     return NULL;
 }
 
+static PSCSI_REQUEST_BLOCK_INFO
+SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+                         PSCSI_PORT_LUN_EXTENSION LunExtension,
+                         PSCSI_REQUEST_BLOCK Srb)
+{
+    PCHAR SrbExtension;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+
+    /* Spinlock must be held while this function executes */
+    KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
+
+    /* Allocate SRB data structure */
+    if (DeviceExtension->NeedSrbDataAlloc)
+    {
+        /* Treat the abort request in a special way */
+        if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
+        {
+            SrbInfo = SpiGetSrbData(DeviceExtension,
+                                    Srb->PathId,
+                                    Srb->TargetId,
+                                    Srb->Lun,
+                                    Srb->QueueTag);
+        }
+        else if (Srb->SrbFlags &
+                 (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
+                 !(Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT)
+                 )
+        {
+            /* Do not process tagged commands if need request sense is set */
+            if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE)
+            {
+                ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
+
+                LunExtension->PendingRequest = Srb->OriginalRequest;
+                LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
+
+                /* Relese the spinlock and return */
+                KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+                return NULL;
+            }
+
+            ASSERT(LunExtension->SrbInfo.Srb == NULL);
+            SrbInfo = DeviceExtension->FreeSrbInfo;
+
+            if (SrbInfo == NULL)
+            {
+                /* No SRB structures left in the list. We have to leave
+                   and wait while we are called again */
+
+                DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
+                KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+                return NULL;
+            }
+
+            DeviceExtension->FreeSrbInfo = (PSCSI_REQUEST_BLOCK_INFO)SrbInfo->Requests.Flink;
+
+            /* QueueTag must never be 0, so +1 to it */
+            Srb->QueueTag = (UCHAR)(SrbInfo - DeviceExtension->SrbInfo) + 1;
+        }
+        else
+        {
+            /* Usual untagged command */
+            if (
+                (!IsListEmpty(&LunExtension->SrbInfo.Requests) ||
+                LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) &&
+                !(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
+                )
+            {
+                /* Mark it as pending and leave */
+                ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
+                LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
+                LunExtension->PendingRequest = Srb->OriginalRequest;
+
+                KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+                return(NULL);
+            }
+
+            Srb->QueueTag = SP_UNTAGGED;
+            SrbInfo = &LunExtension->SrbInfo;
+        }
+    }
+    else
+    {
+        Srb->QueueTag = SP_UNTAGGED;
+        SrbInfo = &LunExtension->SrbInfo;
+    }
+
+    /* Allocate SRB extension structure */
+    if (DeviceExtension->NeedSrbExtensionAlloc)
+    {
+        /* Check the list of free extensions */
+        SrbExtension = DeviceExtension->FreeSrbExtensions;
+
+        /* If no free extensions... */
+        if (SrbExtension == NULL)
+        {
+            /* Free SRB data */
+            if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND &&
+                Srb->QueueTag != SP_UNTAGGED)
+            {
+                SrbInfo->Requests.Blink = NULL;
+                SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo;
+                DeviceExtension->FreeSrbInfo = SrbInfo;
+            }
+
+            /* Return, in order to be called again later */
+            DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
+            KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+            return NULL;
+        }
+
+        /* Remove that free SRB extension from the list (since
+           we're going to use it) */
+        DeviceExtension->FreeSrbExtensions = *((PVOID *)SrbExtension);
+
+        /* Spinlock can be released now */
+        KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+
+        Srb->SrbExtension = SrbExtension;
+
+        if (Srb->SenseInfoBuffer != NULL &&
+            DeviceExtension->SupportsAutoSense)
+        {
+            /* Store pointer to the SenseInfo buffer */
+            SrbInfo->SaveSenseRequest = Srb->SenseInfoBuffer;
+
+            /* Does data fit the buffer? */
+            if (Srb->SenseInfoBufferLength > sizeof(SENSE_DATA))
+            {
+                /* No, disabling autosense at all */
+                Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
+            }
+            else
+            {
+                /* Yes, update the buffer pointer */
+                Srb->SenseInfoBuffer = SrbExtension + DeviceExtension->SrbExtensionSize;
+            }
+        }
+    }
+    else
+    {
+        /* Cleanup... */
+        Srb->SrbExtension = NULL;
+        KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+    }
+
+    return SrbInfo;
+}
+
 
 static NTSTATUS
 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
@@ -3428,7 +3775,7 @@ SpiScanAdapter(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
             /* Scan all logical units */
             for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
             {
-                if (!LunExtension)
+                if ((!LunExtension) || (!LunInfo))
                     break;
 
                 /* Add extension to the list */
@@ -3462,7 +3809,7 @@ SpiScanAdapter(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
                     /* Check if this device is unsupported */
                     if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
                     {
-                        DeviceExtension->LunExtensionList[Hint] = 
+                        DeviceExtension->LunExtensionList[Hint] =
                             DeviceExtension->LunExtensionList[Hint]->Next;
 
                         continue;
@@ -3506,7 +3853,7 @@ SpiScanAdapter(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
                 else
                 {
                     /* Remove this LUN from the list */
-                    DeviceExtension->LunExtensionList[Hint] = 
+                    DeviceExtension->LunExtensionList[Hint] =
                         DeviceExtension->LunExtensionList[Hint]->Next;
 
                     /* Decide whether we are continuing or not */
@@ -3570,7 +3917,7 @@ SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     /* Calculate data size */
     Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) *
         sizeof(SCSI_BUS_DATA);
-    
+
     Length += InquiryDataSize * LunCount;
 
     /* Check, if all data is going to fit into provided buffer */
@@ -3650,7 +3997,7 @@ SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 }
 
 static PSCSI_REQUEST_BLOCK_INFO
-SpiGetSrbData(IN PVOID DeviceExtension,
+SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
               IN UCHAR PathId,
               IN UCHAR TargetId,
               IN UCHAR Lun,
@@ -3675,9 +4022,11 @@ SpiGetSrbData(IN PVOID DeviceExtension,
     }
     else
     {
-        /* TODO: Implement when we have it */
-        ASSERT(FALSE);
-        return NULL;
+        /* Make sure the tag is valid, if it is - return the data */
+        if (QueueTag > DeviceExtension->SrbDataCount || QueueTag < 1)
+            return NULL;
+        else
+            return &DeviceExtension->SrbInfo[QueueTag -1];
     }
 }
 
@@ -3714,6 +4063,12 @@ SpiSendRequestSense(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                            TRUE,
                            TRUE);
 
+    if (!Srb)
+    {
+        DPRINT("SpiSendRequestSense() failed, Srb %p\n", Srb);
+        return;
+    }
+
     IrpStack = IoGetNextIrpStackLocation(Irp);
     IrpStack->MajorFunction = IRP_MJ_SCSI;
 
@@ -3780,7 +4135,7 @@ SpiSendRequestSense(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 
 static
 VOID
-STDCALL
+NTAPI
 SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                            IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
                            OUT PBOOLEAN NeedToCallStartIo)
@@ -3817,7 +4172,6 @@ SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
         }
     }
 
-
     /* Flush adapter if needed */
     if (SrbInfo->BaseOfMapRegister)
     {
@@ -3934,7 +4288,7 @@ SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
             KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
         }
 
-        DPRINT("IoCompleting request IRP 0x%08X\n", Irp);
+        DPRINT("IoCompleting request IRP 0x%p\n", Irp);
 
         IoCompleteRequest(Irp, IO_DISK_INCREMENT);
 
@@ -4098,7 +4452,7 @@ Error:
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
                      PIRP Irp,
                      PVOID Context)
@@ -4144,7 +4498,7 @@ SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
 
     if (Irp->MdlAddress != NULL)
     {
-        MmUnlockPages(Irp->MdlAddress);
+               MmUnlockPages(Irp->MdlAddress);
         IoFreeMdl(Irp->MdlAddress);
         Irp->MdlAddress = NULL;
     }
@@ -4153,9 +4507,7 @@ SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
     return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-
-
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
             IN PVOID ServiceContext)
 {
@@ -4185,7 +4537,7 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
 }
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiSaveInterruptData(IN PVOID Context)
 {
     PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context;
@@ -4303,7 +4655,7 @@ SpiSaveInterruptData(IN PVOID Context)
 }
 
 VOID
-STDCALL
+NTAPI
 SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                          IN PSCSI_PORT_LUN_EXTENSION LunExtension)
 {
@@ -4410,7 +4762,7 @@ SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 //    IN PIRP           DpcIrp
 //    IN PVOID          DpcContext
 //
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortDpcForIsr(IN PKDPC Dpc,
                  IN PDEVICE_OBJECT DpcDeviceObject,
                  IN PIRP DpcIrp,
@@ -4610,7 +4962,7 @@ TryAgain:
 }
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiProcessTimeout(PVOID ServiceContext)
 {
     PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
@@ -4656,7 +5008,7 @@ SpiProcessTimeout(PVOID ServiceContext)
 
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiResetBus(PVOID ServiceContext)
 {
     PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext;
@@ -4689,7 +5041,7 @@ SpiResetBus(PVOID ServiceContext)
 //    IN  PVOID           Context       the Controller extension for the
 //                                      controller the device is on
 //
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
                 PVOID Context)
 {
@@ -5213,13 +5565,14 @@ ByeBye:
 }
 
 VOID
-STDCALL
+NTAPI
 SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
                     IN PVOID DeviceObject,
                     IN PVOID SystemArgument1,
                     IN PVOID SystemArgument2)
 {
     DPRINT1("Miniport timer DPC\n");
+    ASSERT(FALSE);
 }
 
 static NTSTATUS
@@ -5347,12 +5700,16 @@ TryNextAd:
             else
             {
                 /* Info was not found, exit */
+                DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
                 return STATUS_DEVICE_DOES_NOT_EXIST;
             }
         }
+        else
+        {
+            DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
+        }
     }
 
-
     /* Look at device params */
     Key = NULL;
     if (InternalConfigInfo->Parameter)
@@ -5479,7 +5836,6 @@ SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     ANSI_STRING AnsiString;
     NTSTATUS Status = STATUS_SUCCESS;
 
-
     KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
 
     /* Loop through all values in the device node */
@@ -5800,9 +6156,8 @@ SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
     }
 }
 
-
 NTSTATUS
-STDCALL
+NTAPI
 SpQueryDeviceCallout(IN PVOID  Context,
                      IN PUNICODE_STRING  PathName,
                      IN INTERFACE_TYPE  BusType,
@@ -5822,7 +6177,31 @@ SpQueryDeviceCallout(IN PVOID  Context,
     return STATUS_SUCCESS;
 }
 
+IO_ALLOCATION_ACTION
+NTAPI
+ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
+                               IN PIRP Irp,
+                               IN PVOID MapRegisterBase,
+                               IN PVOID Context)
+{
+    KIRQL Irql;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+
+    /* Guard access with the spinlock */
+    KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
 
+    /* Save MapRegisterBase we've got here */
+    DeviceExtension->MapRegisterBase = MapRegisterBase;
+
+    /* Start pending request */
+    KeSynchronizeExecution(DeviceExtension->Interrupt,
+        ScsiPortStartPacket, DeviceObject);
+
+    /* Release spinlock we took */
+    KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
+
+    return KeepObject;
+}
 
 static
 NTSTATUS
@@ -5833,7 +6212,7 @@ SpiStatusSrbToNt(UCHAR SrbStatus)
     case SRB_STATUS_TIMEOUT:
     case SRB_STATUS_COMMAND_TIMEOUT:
         return STATUS_IO_TIMEOUT;
-    
+
     case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
     case SRB_STATUS_BAD_FUNCTION:
         return STATUS_INVALID_DEVICE_REQUEST;
@@ -5862,7 +6241,7 @@ SpiStatusSrbToNt(UCHAR SrbStatus)
 /*
  * @implemented
  */
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
 {
   DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");