[SCSIPORT]
[reactos.git] / reactos / drivers / storage / scsiport / scsiport.c
index 2f63cb5..74b787b 100644 (file)
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Storage Stack
  * FILE:            drivers/storage/scsiport/scsiport.c
  * PURPOSE:         SCSI port driver
- * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
+ * PROGRAMMER:      Eric Kohl
  *                  Aleksey Bragin (aleksey reactos org)
  */
 
 
 #include "scsiport_int.h"
 
-#ifdef _MSC_VER
-  #define STDCALL
-  #define DDKAPI
-#endif
-
 ULONG InternalDebugLevel = 0x00;
 
+#undef ScsiPortMoveMemory
+
 /* TYPES *********************************************************************/
 
 /* GLOBALS *******************************************************************/
@@ -63,29 +60,29 @@ 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
-STDCALL
+NTAPI
 SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                   PVOID MapRegisterBase, PVOID Context);
 
@@ -121,22 +118,22 @@ SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
               IN UCHAR Lun,
               IN UCHAR QueueTag);
 
-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
-STDCALL
+NTAPI
 ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
                                IN PIRP Irp,
                                IN PVOID MapRegisterBase,
@@ -154,22 +151,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,
@@ -182,7 +179,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,
@@ -221,7 +218,9 @@ SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 static NTSTATUS
 SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize);
 
-
+NTHALAPI ULONG NTAPI HalGetBusData(BUS_DATA_TYPE, ULONG, ULONG, PVOID, ULONG);
+NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY);
+NTHALAPI NTSTATUS NTAPI HalAssignSlotResources(PUNICODE_STRING, PUNICODE_STRING, PDRIVER_OBJECT, PDEVICE_OBJECT, INTERFACE_TYPE, ULONG, ULONG, PCM_RESOURCE_LIST *);
 
 /* FUNCTIONS *****************************************************************/
 
@@ -246,7 +245,7 @@ SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCa
  *     Status.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
 {
@@ -299,25 +298,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");
@@ -328,7 +422,7 @@ ScsiPortFlushDma(IN PVOID HwDeviceExtension)
 /*
  * @implemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
                       IN PVOID MappedAddress)
 {
@@ -380,7 +474,7 @@ ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
 /*
  * @implemented
  */
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortGetBusData(IN PVOID DeviceExtension,
                   IN ULONG BusDataType,
                   IN ULONG SystemIoBusNumber,
@@ -409,7 +503,7 @@ ScsiPortGetBusData(IN PVOID DeviceExtension,
 /*
  * @implemented
  */
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
                            IN ULONG BusDataType,
                            IN ULONG SystemIoBusNumber,
@@ -430,7 +524,7 @@ ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
                      IN ULONG SystemIoBusNumber,
@@ -462,7 +556,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,
@@ -489,7 +583,7 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
 /*
  * @unimplemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
                       IN UCHAR PathId,
                       IN UCHAR TargetId,
@@ -532,7 +626,7 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
 /*
  * @implemented
  */
-SCSI_PHYSICAL_ADDRESS STDCALL
+SCSI_PHYSICAL_ADDRESS NTAPI
 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
                            IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
                            IN PVOID VirtualAddress,
@@ -598,7 +692,7 @@ ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
 /*
  * @unimplemented
  */
-PSCSI_REQUEST_BLOCK STDCALL
+PSCSI_REQUEST_BLOCK NTAPI
 ScsiPortGetSrb(IN PVOID DeviceExtension,
               IN UCHAR PathId,
               IN UCHAR TargetId,
@@ -614,7 +708,7 @@ ScsiPortGetSrb(IN PVOID DeviceExtension,
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
                             IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
                             IN ULONG NumberOfBytes)
@@ -796,7 +890,7 @@ SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCa
 /*
  * @implemented
  */
-PVOID STDCALL
+PVOID NTAPI
 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
                           IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
 {
@@ -917,7 +1011,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,
@@ -1133,8 +1227,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,
@@ -1643,7 +1737,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;
@@ -1715,7 +1809,7 @@ SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb,
                      IN PVOID LogicalAddress,
@@ -1728,7 +1822,7 @@ ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
 /*
  * @unimplemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortLogError(IN PVOID HwDeviceExtension,
                 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
                 IN UCHAR PathId,
@@ -1752,7 +1846,7 @@ ScsiPortLogError(IN PVOID HwDeviceExtension,
 /*
  * @implemented
  */
-VOID STDCALL
+VOID NTAPI
 ScsiPortMoveMemory(OUT PVOID Destination,
                   IN PVOID Source,
                   IN ULONG Length)
@@ -1867,9 +1961,12 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
                                               TargetId,
                                               Lun);
 
+            /* If returned LunExtension is NULL, break out */
+            if (!LunExtension) break;
+
             /* This request should not be processed if */
-            if ((LunExtension && LunExtension->ReadyLun) ||
-                (LunExtension && LunExtension->SrbInfo.Srb))
+            if ((LunExtension->ReadyLun) ||
+                (LunExtension->SrbInfo.Srb))
             {
                 /* Nothing to do here */
                 break;
@@ -1888,8 +1985,27 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
                 SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED;
           break;
 
+      case CallDisableInterrupts:
+          DPRINT1("UNIMPLEMENTED SCSI Notification called: CallDisableInterrupts!\n");
+          break;
+
+      case CallEnableInterrupts:
+          DPRINT1("UNIMPLEMENTED SCSI Notification called: CallEnableInterrupts!\n");
+          break;
+
+      case RequestTimerCall:
+          DPRINT("Notify: RequestTimerCall\n");
+          DeviceExtension->InterruptData.Flags |= SCSI_PORT_TIMER_NEEDED;
+          DeviceExtension->InterruptData.HwScsiTimer = (PHW_TIMER)va_arg(ap, PHW_TIMER);
+          DeviceExtension->InterruptData.MiniportTimerValue = (ULONG)va_arg(ap, ULONG);
+          break;
+
+      case BusChangeDetected:
+          DPRINT1("UNIMPLEMENTED SCSI Notification called: BusChangeDetected!\n");
+          break;
+      
       default:
-       DPRINT1 ("Unsupported notification %lu\n", NotificationType);
+       DPRINT1 ("Unsupported notification from WMI: %lu\n", NotificationType);
        break;
     }
 
@@ -1902,7 +2018,7 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
 /*
  * @implemented
  */
-BOOLEAN STDCALL
+BOOLEAN NTAPI
 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
                      IN INTERFACE_TYPE BusType,
                      IN ULONG SystemIoBusNumber,
@@ -2300,7 +2416,7 @@ SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
  *     Status.
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
                    IN PIRP Irp)
 {
@@ -2412,7 +2528,7 @@ SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
  *     NTSTATUS
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp)
 {
@@ -2653,13 +2769,13 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
  *     NTSTATUS
  */
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
                      IN PIRP Irp)
 {
     PIO_STACK_LOCATION Stack;
     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-    NTSTATUS Status = STATUS_SUCCESS;;
+    NTSTATUS Status = STATUS_SUCCESS;
 
     DPRINT("ScsiPortDeviceControl()\n");
 
@@ -2713,6 +2829,14 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
           Status = SpiGetInquiryData(DeviceExtension, Irp);
           break;
 
+      case IOCTL_SCSI_MINIPORT:
+          DPRINT1("IOCTL_SCSI_MINIPORT unimplemented!\n");
+          break;
+
+      case IOCTL_SCSI_PASS_THROUGH:
+          DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
+          break;
+
       default:
        DPRINT1("  unknown ioctl code: 0x%lX\n",
               Stack->Parameters.DeviceIoControl.IoControlCode);
@@ -2727,7 +2851,7 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
 }
 
 
-static VOID STDCALL
+static VOID NTAPI
 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp)
 {
@@ -2810,7 +2934,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);
@@ -2905,7 +3029,7 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
 }
 
 
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortStartPacket(IN OUT PVOID Context)
 {
     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
@@ -3060,7 +3184,7 @@ ScsiPortStartPacket(IN OUT PVOID Context)
 }
 
 IO_ALLOCATION_ACTION
-STDCALL
+NTAPI
 SpiAdapterControl(PDEVICE_OBJECT DeviceObject,
                   PIRP Irp,
                   PVOID MapRegisterBase,
@@ -4042,7 +4166,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)
@@ -4359,7 +4483,7 @@ Error:
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
                      PIRP Irp,
                      PVOID Context)
@@ -4405,8 +4529,7 @@ SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
 
     if (Irp->MdlAddress != NULL)
     {
-               /* We don't need to unlock this MDL because the request could 
-                * only have come from dispatch level */
+               MmUnlockPages(Irp->MdlAddress);
         IoFreeMdl(Irp->MdlAddress);
         Irp->MdlAddress = NULL;
     }
@@ -4415,7 +4538,7 @@ SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
     return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
             IN PVOID ServiceContext)
 {
@@ -4445,7 +4568,7 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
 }
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiSaveInterruptData(IN PVOID Context)
 {
     PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context;
@@ -4563,7 +4686,7 @@ SpiSaveInterruptData(IN PVOID Context)
 }
 
 VOID
-STDCALL
+NTAPI
 SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                          IN PSCSI_PORT_LUN_EXTENSION LunExtension)
 {
@@ -4670,7 +4793,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,
@@ -4682,6 +4805,7 @@ ScsiPortDpcForIsr(IN PKDPC Dpc,
     PSCSI_PORT_LUN_EXTENSION LunExtension;
     BOOLEAN NeedToStartIo;
     PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+    LARGE_INTEGER TimerValue;
 
     DPRINT("ScsiPortDpcForIsr(Dpc %p  DpcDeviceObject %p  DpcIrp %p  DpcContext %p)\n",
            Dpc, DpcDeviceObject, DpcIrp, DpcContext);
@@ -4722,10 +4846,26 @@ TryAgain:
     }
 
     /* Check if timer is needed */
-    if (InterruptData.Flags & SCIS_PORT_TIMER_NEEDED)
+    if (InterruptData.Flags & SCSI_PORT_TIMER_NEEDED)
     {
-        /* TODO: Implement */
-        ASSERT(FALSE);
+        /* Save the timer routine */
+        DeviceExtension->HwScsiTimer = InterruptData.HwScsiTimer;
+
+        if (InterruptData.MiniportTimerValue == 0)
+        {
+            /* Cancel the timer */
+            KeCancelTimer(&DeviceExtension->MiniportTimer);
+        }
+        else
+        {
+            /* Convert timer value */
+            TimerValue.QuadPart = Int32x32To64(InterruptData.MiniportTimerValue, -10);
+
+            /* Set the timer */
+            KeSetTimer(&DeviceExtension->MiniportTimer,
+                       TimerValue,
+                       &DeviceExtension->MiniportTimerDpc);
+        }
     }
 
     /* If it's ready for the next request */
@@ -4870,7 +5010,7 @@ TryAgain:
 }
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiProcessTimeout(PVOID ServiceContext)
 {
     PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
@@ -4916,7 +5056,7 @@ SpiProcessTimeout(PVOID ServiceContext)
 
 
 BOOLEAN
-STDCALL
+NTAPI
 SpiResetBus(PVOID ServiceContext)
 {
     PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext;
@@ -4949,7 +5089,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)
 {
@@ -5473,14 +5613,37 @@ 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);
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+
+    DPRINT("Miniport timer DPC\n");
+
+    DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
+
+    /* Acquire the spinlock */
+    KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
+
+    /* Call the timer routine */
+    if (DeviceExtension->HwScsiTimer != NULL)
+    {
+        DeviceExtension->HwScsiTimer(&DeviceExtension->MiniPortDeviceExtension);
+    }
+
+    /* Release the spinlock */
+    KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+
+    if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
+    {
+        ScsiPortDpcForIsr(NULL,
+                          DeviceExtension->DeviceObject,
+                          NULL,
+                          NULL);
+    }
 }
 
 static NTSTATUS
@@ -6065,7 +6228,7 @@ SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 SpQueryDeviceCallout(IN PVOID  Context,
                      IN PUNICODE_STRING  PathName,
                      IN INTERFACE_TYPE  BusType,
@@ -6086,7 +6249,7 @@ SpQueryDeviceCallout(IN PVOID  Context,
 }
 
 IO_ALLOCATION_ACTION
-STDCALL
+NTAPI
 ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
                                IN PIRP Irp,
                                IN PVOID MapRegisterBase,
@@ -6149,7 +6312,7 @@ SpiStatusSrbToNt(UCHAR SrbStatus)
 /*
  * @implemented
  */
-ULONG STDCALL
+ULONG NTAPI
 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
 {
   DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");