merged in MDL fix and a makefile mod from the 0.1.4 release branch. This represents...
[reactos.git] / reactos / drivers / storage / class2 / class2.c
index 2ee8619..55c3238 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2001, 2002 ReactOS Team
+ *  Copyright (C) 2001, 2002, 2003 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: class2.c,v 1.26 2002/10/01 19:27:18 chorns Exp $
+/* $Id: class2.c,v 1.41 2003/10/15 22:16:44 vizzini Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -55,10 +55,6 @@ static NTSTATUS STDCALL
 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp);
 
-static NTSTATUS STDCALL
-ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
-                    IN PIRP Irp);
-
 static NTSTATUS STDCALL
 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp);
@@ -69,9 +65,7 @@ ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
 
 static VOID
 ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
-                     PIRP Irp,
-                     PSCSI_REQUEST_BLOCK Srb,
-                     BOOLEAN Associated);
+                     PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated);
 
 /* FUNCTIONS ****************************************************************/
 
@@ -125,6 +119,9 @@ ScsiClassDebugPrint(IN ULONG DebugPrintLevel,
 }
 
 
+/*
+ * @unimplemented
+ */
 NTSTATUS STDCALL
 ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
                                IN PIRP Irp,
@@ -134,9 +131,12 @@ ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
-ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
-                     PIRP Irp)
+ScsiClassBuildRequest(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
 {
   PDEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION CurrentIrpStack;
@@ -160,9 +160,7 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
   DPRINT("Logical block address: %lu\n", LogicalBlockAddress);
 
   /* Allocate and initialize an SRB */
-  /* FIXME: use lookaside list instead */
-  Srb = ExAllocatePool(NonPagedPool,
-                      sizeof(SCSI_REQUEST_BLOCK));
+  Srb = ExAllocateFromNPagedLookasideList(&DeviceExtension->SrbLookasideListHead);
 
   Srb->SrbFlags = 0;
   Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE;
@@ -171,6 +169,7 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
   Srb->TargetId = DeviceExtension->TargetId;
   Srb->Lun = DeviceExtension->Lun;
   Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+  //FIXME: NT4 DDK sample uses MmGetMdlVirtualAddress! Why shouldn't we?
   Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
   Srb->DataTransferLength = CurrentIrpStack->Parameters.Read.Length;
   Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
@@ -240,10 +239,9 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
   /* Initialize next stack location */
   NextIrpStack->MajorFunction = IRP_MJ_SCSI;
   NextIrpStack->Parameters.Scsi.Srb = Srb;
-  NextIrpStack->DeviceObject = DeviceObject;
 
   /* Set retry count */
-  NextIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
+  CurrentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
 
   DPRINT("IoSetCompletionRoutine (Irp %p  Srb %p)\n", Irp, Srb);
   IoSetCompletionRoutine(Irp,
@@ -255,6 +253,9 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
                     PSCSI_INQUIRY_DATA LunInfo,
@@ -342,6 +343,9 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
                            IN PCCHAR ObjectNameBuffer,
@@ -411,23 +415,57 @@ ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
-                      PIRP Irp)
+ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp)
 {
   PDEVICE_EXTENSION DeviceExtension;
+  PIO_STACK_LOCATION NextStack;
   PIO_STACK_LOCATION Stack;
   ULONG IoControlCode;
+  ULONG InputBufferLength;
   ULONG OutputBufferLength;
+  ULONG ModifiedControlCode;
+  PSCSI_REQUEST_BLOCK Srb;
+  PCDB Cdb;
 
-  DPRINT1("ScsiClassDeviceControl() called\n");
+  DPRINT("ScsiClassDeviceControl() called\n");
 
   DeviceExtension = DeviceObject->DeviceExtension;
   Stack = IoGetCurrentIrpStackLocation(Irp);
 
   IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
+  InputBufferLength = Stack->Parameters.DeviceIoControl.InputBufferLength;
   OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
 
+  if (IoControlCode == IOCTL_SCSI_GET_DUMP_POINTERS)
+    {
+      PDUMP_POINTERS DumpPointers;
+
+      if (OutputBufferLength < sizeof(DUMP_POINTERS))
+       {
+         Irp->IoStatus.Information = 0;
+         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+         return(STATUS_BUFFER_TOO_SMALL);
+       }
+      DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
+
+      /* Initialize next stack location for call to the port driver */
+      NextStack = IoGetNextIrpStackLocation(Irp);
+
+      NextStack->Parameters = Stack->Parameters;
+      NextStack->MajorFunction = Stack->MajorFunction;
+      NextStack->MinorFunction = Stack->MinorFunction;
+
+      /* Call port driver */
+      return(IoCallDriver(DeviceExtension->PortDeviceObject,
+                         Irp));
+    }
   if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
     {
       PSCSI_ADDRESS ScsiAddress;
@@ -458,17 +496,87 @@ ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
   if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
       IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
     {
-      DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
+      PSCSI_PASS_THROUGH ScsiPassThrough;
 
+      DPRINT("IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
 
-      Irp->IoStatus.Information = 0;
-      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+      /* Check input size */
+      if (InputBufferLength < sizeof(SCSI_PASS_THROUGH))
+       {
+         Irp->IoStatus.Information = 0;
+         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+         return(STATUS_INVALID_PARAMETER);
+       }
+
+      /* Initialize next stack location for call to the port driver */
+      NextStack = IoGetNextIrpStackLocation(Irp);
+
+      ScsiPassThrough = Irp->AssociatedIrp.SystemBuffer;
+      ScsiPassThrough->PathId = DeviceExtension->PathId;
+      ScsiPassThrough->TargetId = DeviceExtension->TargetId;
+      ScsiPassThrough->Lun = DeviceExtension->Lun;
+      ScsiPassThrough->Cdb[1] |= DeviceExtension->Lun << 5;
+
+      NextStack->Parameters = Stack->Parameters;
+      NextStack->MajorFunction = Stack->MajorFunction;
+      NextStack->MinorFunction = Stack->MinorFunction;
 
-      return(STATUS_UNSUCCESSFUL);
+      /* Call port driver */
+      return(IoCallDriver(DeviceExtension->PortDeviceObject,
+                         Irp));
+    }
+
+  /* Allocate an SRB */
+  Srb = ExAllocatePool (NonPagedPool,
+                       sizeof(SCSI_REQUEST_BLOCK));
+  if (Srb == NULL)
+    {
+      Irp->IoStatus.Information = 0;
+      Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+      IoCompleteRequest(Irp,
+                       IO_NO_INCREMENT);
+      return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
-  DPRINT1("Fixme: unknown device io control code\n");
+  /* Initialize the SRB */
+  RtlZeroMemory(Srb,
+               sizeof(SCSI_REQUEST_BLOCK));
+  Cdb = (PCDB)Srb->Cdb;
+
+  ModifiedControlCode = (IoControlCode & 0x0000FFFF) | (IOCTL_DISK_BASE << 16);
+  switch (ModifiedControlCode)
+    {
+      case IOCTL_DISK_CHECK_VERIFY:
+       DPRINT("IOCTL_DISK_CHECK_VERIFY\n");
+
+       /* Initialize SRB operation */
+       Srb->CdbLength = 6;
+       Srb->TimeOutValue = DeviceExtension->TimeOutValue;
+       Cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
+
+       return(ScsiClassSendSrbAsynchronous(DeviceObject,
+                                           Srb,
+                                           Irp,
+                                           NULL,
+                                           0,
+                                           FALSE));
+
+      default:
+       DPRINT1("Unknown device io control code %lx\n",
+               ModifiedControlCode);
+       ExFreePool(Srb);
+
+       /* Pass the IOCTL down to the port driver */
+       NextStack = IoGetNextIrpStackLocation(Irp);
+       NextStack->Parameters = Stack->Parameters;
+       NextStack->MajorFunction = Stack->MajorFunction;
+       NextStack->MinorFunction = Stack->MinorFunction;
+
+       /* Call port driver */
+       return(IoCallDriver(DeviceExtension->PortDeviceObject,
+                           Irp));
+    }
 
   Irp->IoStatus.Information = 0;
   Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
@@ -478,19 +586,64 @@ ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 PVOID STDCALL
-ScsiClassFindModePage(PCHAR ModeSenseBuffer,
-                     ULONG Length,
-                     UCHAR PageMode,
-                     BOOLEAN Use6Byte)
+ScsiClassFindModePage(IN PCHAR ModeSenseBuffer,
+                     IN ULONG Length,
+                     IN UCHAR PageMode,
+                     IN BOOLEAN Use6Byte)
 {
-  UNIMPLEMENTED;
+  ULONG DescriptorLength;
+  ULONG HeaderLength;
+  PCHAR End;
+  PCHAR Ptr;
+
+  DPRINT("ScsiClassFindModePage() called\n");
+
+  /* Get header length */
+  HeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
+
+  /* Check header length */
+  if (Length < HeaderLength)
+    return NULL;
+
+  /* Get descriptor length */
+  if (Use6Byte == TRUE)
+    {
+      DescriptorLength = ((PMODE_PARAMETER_HEADER)ModeSenseBuffer)->BlockDescriptorLength;
+    }
+  else
+    {
+      DescriptorLength = ((PMODE_PARAMETER_HEADER10)ModeSenseBuffer)->BlockDescriptorLength[1];
+    }
+
+  /* Set page pointers */
+  Ptr = ModeSenseBuffer + HeaderLength + DescriptorLength;
+  End = ModeSenseBuffer + Length;
+
+  /* Search for page */
+  while (Ptr < End)
+    {
+      /* Check page code */
+      if (((PMODE_DISCONNECT_PAGE)Ptr)->PageCode == PageMode)
+       return Ptr;
+
+      /* Skip to next page */
+      Ptr += ((PMODE_DISCONNECT_PAGE)Ptr)->PageLength;
+    }
+
+  return NULL;
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
-ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
-                             PSCSI_ADAPTER_BUS_INFO AdapterInformation)
+ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData,
+                             IN PSCSI_ADAPTER_BUS_INFO AdapterInformation)
 {
   PSCSI_INQUIRY_DATA UnitInfo;
   PINQUIRYDATA InquiryData;
@@ -532,9 +685,12 @@ ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
-                        PIO_SCSI_CAPABILITIES *PortCapabilities)
+ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject,
+                        OUT PIO_SCSI_CAPABILITIES *PortCapabilities)
 {
   IO_STATUS_BLOCK IoStatusBlock;
   NTSTATUS Status;
@@ -577,9 +733,12 @@ ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
-                       PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
+ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject,
+                       IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
 {
   PSCSI_ADAPTER_BUS_INFO Buffer;
   IO_STATUS_BLOCK IoStatusBlock;
@@ -643,10 +802,13 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
-ScsiClassInitialize(PVOID Argument1,
-                   PVOID Argument2,
-                   PCLASS_INIT_DATA InitializationData)
+ScsiClassInitialize(IN PVOID Argument1,
+                   IN PVOID Argument2,
+                   IN PCLASS_INIT_DATA InitializationData)
 {
   PCONFIGURATION_INFORMATION ConfigInfo;
   PDRIVER_OBJECT DriverObject = Argument1;
@@ -660,14 +822,14 @@ ScsiClassInitialize(PVOID Argument1,
 
   DPRINT("ScsiClassInitialize() called!\n");
 
-  DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
-  DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
-  DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
-  DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
-  DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch;
-  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
-  DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
-  DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
+  DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)ScsiClassCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)ScsiClassCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)ScsiClassReadWrite;
+  DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)ScsiClassReadWrite;
+  DriverObject->MajorFunction[IRP_MJ_SCSI] = (PDRIVER_DISPATCH)ScsiClassInternalIoControl;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)ScsiClassDeviceDispatch;
+  DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)ScsiClassShutdownFlush;
+  DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)ScsiClassShutdownFlush;
   if (InitializationData->ClassStartIo)
     {
       DriverObject->DriverStartIo = InitializationData->ClassStartIo;
@@ -736,11 +898,12 @@ ScsiClassInitialize(PVOID Argument1,
  *
  * RETURN VALUE
  *     None.
+ *
+ * @implemented
  */
-
 VOID STDCALL
-ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension,
-                                   ULONG NumberElements)
+ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension,
+                                   IN ULONG NumberElements)
 {
   ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
                                  NULL,
@@ -752,24 +915,41 @@ ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension,
 }
 
 
+/*
+ * @unimplemented
+ */
 NTSTATUS STDCALL
-ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject,
-                          PIRP Irp)
+ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject,
+                          IN PIRP Irp)
 {
-  UNIMPLEMENTED;
+  DPRINT1("ScsiClassInternalIoContol() called\n");
+
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return(STATUS_SUCCESS);
 }
 
 
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
-ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
-                           PSCSI_REQUEST_BLOCK Srb,
-                           UCHAR MajorFunctionCode,
-                           ULONG IoDeviceCode,
-                           ULONG RetryCount,
-                           NTSTATUS *Status)
+ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject,
+                           IN PSCSI_REQUEST_BLOCK Srb,
+                           IN UCHAR MajorFunctionCode,
+                           IN ULONG IoDeviceCode,
+                           IN ULONG RetryCount,
+                           OUT NTSTATUS *Status)
 {
   PDEVICE_EXTENSION DeviceExtension;
+#if 0
+  PIO_ERROR_LOG_PACKET LogPacket;
+#endif
   PSENSE_DATA SenseData;
+  NTSTATUS LogStatus;
+  BOOLEAN LogError;
   BOOLEAN Retry;
 
   DPRINT("ScsiClassInterpretSenseInfo() called\n");
@@ -784,6 +964,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
 
   DeviceExtension = DeviceObject->DeviceExtension;
   SenseData = Srb->SenseInfoBuffer;
+  LogError = FALSE;
   Retry = TRUE;
 
   if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
@@ -797,11 +978,98 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
 
       switch (SenseData->SenseKey & 0xf)
        {
-         /* FIXME: add more sense key codes */
+         case SCSI_SENSE_NO_SENSE:
+           DPRINT("SCSI_SENSE_NO_SENSE\n");
+           if (SenseData->IncorrectLength)
+             {
+               DPRINT("Incorrect block length\n");
+               *Status = STATUS_INVALID_BLOCK_LENGTH;
+               Retry = FALSE;
+             }
+           else
+             {
+               DPRINT("Unspecified error\n");
+               *Status = STATUS_IO_DEVICE_ERROR;
+               Retry = FALSE;
+             }
+           break;
+
+         case SCSI_SENSE_RECOVERED_ERROR:
+           DPRINT("SCSI_SENSE_RECOVERED_ERROR\n");
+           *Status = STATUS_SUCCESS;
+           Retry = FALSE;
+           break;
 
          case SCSI_SENSE_NOT_READY:
            DPRINT("SCSI_SENSE_NOT_READY\n");
            *Status = STATUS_DEVICE_NOT_READY;
+           switch (SenseData->AdditionalSenseCode)
+             {
+               case SCSI_ADSENSE_LUN_NOT_READY:
+                 DPRINT("SCSI_ADSENSE_LUN_NOT_READY\n");
+                 break;
+
+               case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
+                 DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n");
+                 *Status = STATUS_NO_MEDIA_IN_DEVICE;
+                 Retry = FALSE;
+                 break;
+             }
+           break;
+
+         case SCSI_SENSE_MEDIUM_ERROR:
+           DPRINT("SCSI_SENSE_MEDIUM_ERROR\n");
+           *Status = STATUS_DEVICE_DATA_ERROR;
+           Retry = FALSE;
+           break;
+
+         case SCSI_SENSE_HARDWARE_ERROR:
+           DPRINT("SCSI_SENSE_HARDWARE_ERROR\n");
+           *Status = STATUS_IO_DEVICE_ERROR;
+           break;
+
+         case SCSI_SENSE_ILLEGAL_REQUEST:
+           DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
+           *Status = STATUS_INVALID_DEVICE_REQUEST;
+           switch (SenseData->AdditionalSenseCode)
+             {
+               case SCSI_ADSENSE_ILLEGAL_COMMAND:
+                 DPRINT("SCSI_ADSENSE_ILLEGAL_COMMAND\n");
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_ILLEGAL_BLOCK:
+                 DPRINT("SCSI_ADSENSE_ILLEGAL_BLOCK\n");
+                 *Status = STATUS_NONEXISTENT_SECTOR;
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_INVALID_LUN:
+                 DPRINT("SCSI_ADSENSE_INVALID_LUN\n");
+                 *Status = STATUS_NO_SUCH_DEVICE;
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_MUSIC_AREA:
+                 DPRINT("SCSI_ADSENSE_MUSIC_AREA\n");
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_DATA_AREA:
+                 DPRINT("SCSI_ADSENSE_DATA_AREA\n");
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_VOLUME_OVERFLOW:
+                 DPRINT("SCSI_ADSENSE_VOLUME_OVERFLOW\n");
+                 Retry = FALSE;
+                 break;
+
+               case SCSI_ADSENSE_INVALID_CDB:
+                 DPRINT("SCSI_ADSENSE_INVALID_CDB\n");
+                 Retry = FALSE;
+                 break;
+             }
            break;
 
          case SCSI_SENSE_UNIT_ATTENTION:
@@ -819,12 +1087,16 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
              }
            break;
 
-         case SCSI_SENSE_ILLEGAL_REQUEST:
-           DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
-           *Status = STATUS_INVALID_DEVICE_REQUEST;
+         case SCSI_SENSE_DATA_PROTECT:
+           DPRINT("SCSI_SENSE_DATA_PROTECT\n");
+           *Status = STATUS_MEDIA_WRITE_PROTECTED;
            Retry = FALSE;
            break;
 
+         case SCSI_SENSE_ABORTED_COMMAND:
+           DPRINT("SCSI_SENSE_ABORTED_COMMAND\n");
+           *Status = STATUS_IO_DEVICE_ERROR;
+           break;
 
          default:
            DPRINT1("SCSI error (sense key: %x)\n",
@@ -862,6 +1134,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
          default:
            DPRINT1("SCSI error (SRB status: %x)\n",
                    SRB_STATUS(Srb->SrbStatus));
+           LogError = TRUE;
            *Status = STATUS_IO_DEVICE_ERROR;
            break;
        }
@@ -876,18 +1149,57 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
                                  &Retry);
     }
 
-  /* FIXME: log severe errors */
+  if (LogError == TRUE)
+    {
+#if 0
+      /* Allocate error packet */
+      LogPacket = IoAllocateErrorLogEntry (DeviceObject,
+                                          sizeof(IO_ERROR_LOG_PACKET) +
+                                            5 * sizeof(ULONG));
+      if (LogPacket == NULL)
+       {
+         DPRINT1 ("Failed to allocate a log packet!\n");
+         return Retry;
+       }
+
+      /* Initialize error packet */
+      LogPacket->MajorFunctionCode = MajorFunctionCode;
+      LogPacket->RetryCount = (UCHAR)RetryCount;
+      LogPacket->DumpDataSize = 6 * sizeof(ULONG);
+      LogPacket->ErrorCode = 0; /* FIXME */
+      LogPacket->FinalStatus = *Status;
+      LogPacket->IoControlCode = IoDeviceCode;
+      LogPacket->DeviceOffset.QuadPart = 0; /* FIXME */
+      LogPacket->DumpData[0] = Srb->PathId;
+      LogPacket->DumpData[1] = Srb->TargetId;
+      LogPacket->DumpData[2] = Srb->Lun;
+      LogPacket->DumpData[3] = 0;
+      LogPacket->DumpData[4] = (Srb->SrbStatus << 8) | Srb->ScsiStatus;
+      if (SenseData != NULL)
+       {
+         LogPacket->DumpData[5] = (SenseData->SenseKey << 16) |
+                                  (SenseData->AdditionalSenseCode << 8) |
+                                  SenseData->AdditionalSenseCodeQualifier;
+       }
+
+      /* Write error packet */
+      IoWriteErrorLogEntry (LogPacket);
+#endif
+    }
 
   DPRINT("ScsiClassInterpretSenseInfo() done\n");
 
-  return(Retry);
+  return Retry;
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
-                   PIRP Irp,
-                   PVOID Context)
+ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject,
+                   IN PIRP Irp,
+                   IN PVOID Context)
 {
   PDEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION IrpStack;
@@ -899,11 +1211,19 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
          DeviceObject, Irp, Context);
 
   DeviceExtension = DeviceObject->DeviceExtension;
-  Srb = (PSCSI_REQUEST_BLOCK)Context;
-  DPRINT("Srb %p\n", Srb);
 
   IrpStack = IoGetCurrentIrpStackLocation(Irp);
 
+  /*
+   * BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
+   * Must pass Srb as Context arg!! See comment about Completion routines in 
+   * IofCallDriver for more info.
+   */
+
+  Srb = (PSCSI_REQUEST_BLOCK)Context;
+
+  DPRINT("Srb %p\n", Srb);
+
   if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
     {
       Status = STATUS_SUCCESS;
@@ -916,7 +1236,7 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
                                          0,
                                          MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
                                          &Status);
-      if ((Retry == TRUE) &&
+      if ((Retry) &&
          ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
        {
          ((ULONG)IrpStack->Parameters.Others.Argument4)--;
@@ -925,13 +1245,14 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
                                Irp,
                                Srb,
                                FALSE);
+
          return(STATUS_MORE_PROCESSING_REQUIRED);
        }
     }
 
-  /* FIXME: use lookaside list instead */
-  DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
-  ExFreePool(IrpStack->Parameters.Scsi.Srb);
+  /* Free the SRB */
+  ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
+                             Srb);
 
   Irp->IoStatus.Status = Status;
   if (!NT_SUCCESS(Status))
@@ -959,10 +1280,13 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
-                             PIRP Irp,
-                             PVOID Context)
+ScsiClassIoCompleteAssociated(IN PDEVICE_OBJECT DeviceObject,
+                             IN PIRP Irp,
+                             IN PVOID Context)
 {
   PDEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION IrpStack;
@@ -977,11 +1301,19 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
 
   MasterIrp = Irp->AssociatedIrp.MasterIrp;
   DeviceExtension = DeviceObject->DeviceExtension;
-  Srb = (PSCSI_REQUEST_BLOCK)Context;
-  DPRINT("Srb %p\n", Srb);
 
   IrpStack = IoGetCurrentIrpStackLocation(Irp);
 
+  /*
+   * BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
+   * Must pass Srb as Context arg!! See comment about Completion routines in 
+   * IofCallDriver for more info.
+   */
+
+  Srb = (PSCSI_REQUEST_BLOCK)Context;
+  
+  DPRINT("Srb %p\n", Srb);
+
   if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
     {
       Status = STATUS_SUCCESS;
@@ -996,9 +1328,7 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
                                          MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
                                          &Status);
 
-      DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
-
-      if ((Retry == TRUE) &&
+      if ((Retry) &&
          ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
        {
          ((ULONG)IrpStack->Parameters.Others.Argument4)--;
@@ -1007,13 +1337,14 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
                                Irp,
                                Srb,
                                TRUE);
+
          return(STATUS_MORE_PROCESSING_REQUIRED);
        }
     }
 
-  /* FIXME: use lookaside list instead */
-  DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
-  ExFreePool(IrpStack->Parameters.Scsi.Srb);
+  /* Free the SRB */
+  ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
+                             Srb);
 
   Irp->IoStatus.Status = Status;
 
@@ -1053,23 +1384,143 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
-ScsiClassModeSense(PDEVICE_OBJECT DeviceObject,
-                  CHAR ModeSenseBuffer,
-                  ULONG Length,
-                  UCHAR PageMode)
+ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject,
+                  IN PCHAR ModeSenseBuffer,
+                  IN ULONG Length,
+                  IN UCHAR PageMode)
 {
-  UNIMPLEMENTED;
+  PDEVICE_EXTENSION DeviceExtension;
+  SCSI_REQUEST_BLOCK Srb;
+  ULONG RetryCount;
+  PCDB Cdb;
+  NTSTATUS Status;
+
+  DPRINT("ScsiClassModeSense() called\n");
+
+  DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+  RetryCount = 1;
+
+  /* Initialize the SRB */
+  RtlZeroMemory (&Srb,
+                sizeof(SCSI_REQUEST_BLOCK));
+  Srb.CdbLength = 6;
+  Srb.TimeOutValue = DeviceExtension->TimeOutValue;
+
+  /* Initialize the CDB */
+  Cdb = (PCDB)&Srb.Cdb;
+  Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
+  Cdb->MODE_SENSE.PageCode = PageMode;
+  Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
+
+TryAgain:
+  Status = ScsiClassSendSrbSynchronous (DeviceObject,
+                                       &Srb,
+                                       ModeSenseBuffer,
+                                       Length,
+                                       FALSE);
+  if (Status == STATUS_VERIFY_REQUIRED)
+    {
+      if (RetryCount != 0)
+       {
+         RetryCount--;
+         goto TryAgain;
+       }
+    }
+  else if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
+    {
+      Status = STATUS_SUCCESS;
+    }
+
+  if (!NT_SUCCESS(Status))
+    {
+      return 0;
+    }
+
+  return Srb.DataTransferLength;
 }
 
 
+/*
+ * @implemented
+ */
 ULONG STDCALL
 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
 {
-  UNIMPLEMENTED;
+  PRTL_QUERY_REGISTRY_TABLE Table;
+  ULONG TimeOutValue;
+  ULONG ZeroTimeOut;
+  ULONG Size;
+  PWSTR Path;
+  NTSTATUS Status;
+
+  if (RegistryPath == NULL)
+    {
+      return 0;
+    }
+
+  TimeOutValue = 0;
+  ZeroTimeOut = 0;
+
+  /* Allocate zero-terminated path string */
+  Size = RegistryPath->Length + sizeof(WCHAR);
+  Path = (PWSTR)ExAllocatePool (NonPagedPool,
+                               Size);
+  if (Path == NULL)
+    {
+      return 0;
+    }
+  RtlZeroMemory (Path,
+                Size);
+  RtlCopyMemory (Path,
+                RegistryPath->Buffer,
+                Size - sizeof(WCHAR));
+
+  /* Allocate query table */
+  Size = sizeof(RTL_QUERY_REGISTRY_TABLE) * 2;
+  Table = (PRTL_QUERY_REGISTRY_TABLE)ExAllocatePool (NonPagedPool,
+                                                    Size);
+  if (Table == NULL)
+    {
+      ExFreePool (Path);
+      return 0;
+    }
+  RtlZeroMemory (Table,
+                Size);
+
+  Table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  Table[0].Name = L"TimeOutValue";
+  Table[0].EntryContext = &TimeOutValue;
+  Table[0].DefaultType = REG_DWORD;
+  Table[0].DefaultData = &ZeroTimeOut;
+  Table[0].DefaultLength = sizeof(ULONG);
+
+  Status = RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                  Path,
+                                  Table,
+                                  NULL,
+                                  NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("RtlQueryRegistryValue() failed (Status %lx)\n", Status);
+      TimeOutValue = 0;
+    }
+
+  ExFreePool (Table);
+  ExFreePool (Path);
+
+  DPRINT("TimeOut: %lu\n", TimeOutValue);
+
+  return TimeOutValue;
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
 {
@@ -1172,6 +1623,9 @@ ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
 }
 
 
+/*
+ * @unimplemented
+ */
 VOID STDCALL
 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
 {
@@ -1179,6 +1633,9 @@ ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
                             PSCSI_REQUEST_BLOCK Srb,
@@ -1187,10 +1644,85 @@ ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
                             ULONG BufferLength,
                             BOOLEAN WriteToDevice)
 {
-  UNIMPLEMENTED;
+  PDEVICE_EXTENSION DeviceExtension;
+  PIO_STACK_LOCATION Stack;
+
+  DPRINT("ScsiClassSendSrbAsynchronous() called\n");
+
+  DeviceExtension = DeviceObject->DeviceExtension;
+
+  /* Initialize the SRB */
+  Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
+  Srb->PathId = DeviceExtension->PathId;
+  Srb->TargetId = DeviceExtension->TargetId;
+  Srb->Lun = DeviceExtension->Lun;
+  Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+  Srb->Cdb[1] |= DeviceExtension->Lun << 5;
+
+  Srb->SenseInfoBuffer = DeviceExtension->SenseData;
+  Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
+
+  Srb->DataBuffer = BufferAddress;
+  Srb->DataTransferLength = BufferLength;
+
+  Srb->ScsiStatus = 0;
+  Srb->SrbStatus = 0;
+  Srb->NextSrb = NULL;
+
+  if (BufferAddress != NULL)
+    {
+      if (Irp->MdlAddress == NULL)
+       {
+         /* Allocate an MDL */
+         if (!IoAllocateMdl(BufferAddress,
+                            BufferLength,
+                            FALSE,
+                            FALSE,
+                            Irp))
+           {
+             DPRINT1("Mdl-Allocation failed\n");
+             return(STATUS_INSUFFICIENT_RESOURCES);
+           }
+
+         MmBuildMdlForNonPagedPool(Irp->MdlAddress);
+       }
+
+      /* Set data direction */
+      Srb->SrbFlags = (WriteToDevice) ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
+    }
+  else
+    {
+      /* Set data direction */
+      Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
+    }
+
+  /* Set the retry counter */
+  Stack = IoGetCurrentIrpStackLocation(Irp);
+  Stack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
+
+  /* Set the completion routine */
+  IoSetCompletionRoutine(Irp,
+                        ScsiClassIoComplete,
+                        Srb,
+                        TRUE,
+                        TRUE,
+                        TRUE);
+
+  /* Attach Srb to the Irp */
+  Stack = IoGetNextIrpStackLocation(Irp);
+  Stack->MajorFunction = IRP_MJ_SCSI;
+  Stack->Parameters.Scsi.Srb = Srb;
+  Srb->OriginalRequest = Irp;
+
+  /* Call the port driver */
+  return(IoCallDriver(DeviceExtension->PortDeviceObject,
+                     Irp));
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
                            PSCSI_REQUEST_BLOCK Srb,
@@ -1235,12 +1767,12 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
     {
       if (WriteToDevice == TRUE)
        {
-         RequestType = IOCTL_SCSI_EXECUTE_OUT;
-         Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
+         RequestType = IOCTL_SCSI_EXECUTE_IN;  // needs _in_ to the device
+         Srb->SrbFlags = SRB_FLAGS_DATA_OUT;   // needs _out_ from the caller
        }
       else
        {
-         RequestType = IOCTL_SCSI_EXECUTE_IN;
+         RequestType = IOCTL_SCSI_EXECUTE_OUT;
          Srb->SrbFlags = SRB_FLAGS_DATA_IN;
        }
     }
@@ -1321,10 +1853,13 @@ TryAgain:
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
-ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
-                     PIRP Irp,
-                     ULONG MaximumBytes)
+ScsiClassSplitRequest(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp,
+                     IN ULONG MaximumBytes)
 {
   PDEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION CurrentStack;
@@ -1345,7 +1880,7 @@ ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
   DeviceExtension = DeviceObject->DeviceExtension;
   CurrentStack = IoGetCurrentIrpStackLocation(Irp);
   NextStack = IoGetNextIrpStackLocation(Irp);
-  DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
+  DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
 
   /* Initialize transfer data for first request */
   Offset = CurrentStack->Parameters.Read.ByteOffset;
@@ -1518,7 +2053,8 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
     }
 
   /* Adjust partition-relative starting offset to absolute offset */
-  IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart;
+  IrpStack->Parameters.Read.ByteOffset.QuadPart += 
+    (DeviceExtension->StartingOffset.QuadPart + DeviceExtension->DMByteSkew);
 
   /* Calculate number of pages in this transfer */
   CurrentTransferPages =
@@ -1561,20 +2097,6 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
 }
 
 
-static NTSTATUS STDCALL
-ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-  DPRINT1("ScsiClassScsiDispatch() called\n");
-
-  Irp->IoStatus.Status = STATUS_SUCCESS;
-  Irp->IoStatus.Information = 0;
-  IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-  return(STATUS_SUCCESS);
-}
-
-
 static NTSTATUS STDCALL
 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
                        IN PIRP Irp)
@@ -1626,6 +2148,7 @@ ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
   PDEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION CurrentIrpStack;
   PIO_STACK_LOCATION NextIrpStack;
+
   ULONG TransferLength;
 
   DPRINT("ScsiPortRetryRequest() called\n");
@@ -1634,21 +2157,23 @@ ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
   CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
   NextIrpStack = IoGetNextIrpStackLocation(Irp);
 
-  if (CurrentIrpStack->MajorFunction == IRP_MJ_READ ||
-      CurrentIrpStack->MajorFunction == IRP_MJ_WRITE)
-    {
-      TransferLength = CurrentIrpStack->Parameters.Read.Length;
-    }
-  else if (Irp->MdlAddress != NULL)
+  if (CurrentIrpStack->MajorFunction != IRP_MJ_READ &&
+      CurrentIrpStack->MajorFunction != IRP_MJ_WRITE)
     {
-      TransferLength = Irp->MdlAddress->ByteCount;
-    }
-  else
-    {
-      TransferLength = 0;
+      /* We shouldn't setup the buffer pointer and transfer length on read/write requests. */
+      if (Irp->MdlAddress != NULL)
+        {
+          TransferLength = Irp->MdlAddress->ByteCount;
+        }
+      else
+        {
+          TransferLength = 0;
+        }
+
+      Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+      Srb->DataTransferLength = TransferLength;
     }
 
-  Srb->DataTransferLength = TransferLength;
   Srb->SrbStatus = 0;
   Srb->ScsiStatus = 0;
 
@@ -1667,7 +2192,7 @@ ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
                             TRUE,
                             TRUE,
                             TRUE);
-    }
+    }                  
   else
     {
       IoSetCompletionRoutine(Irp,