[project] Don't use mini IRP handling for IRP_MJ_SCSI
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Mon, 13 Dec 2010 16:35:09 +0000 (11:35 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Mon, 13 Dec 2010 16:35:09 +0000 (11:35 -0500)
Use device::irp_mj.scsi(), instead.

WinVBlock.dev
src/include/device.h
src/include/disk_scsi.h [deleted file]
src/winvblock/bus/bus.c
src/winvblock/disk/disk.c
src/winvblock/disk/scsi.c
src/winvblock/driver.c

index c343a76..8eaad79 100644 (file)
@@ -1,7 +1,7 @@
 [Project]\r
 FileName=WinVBlock.dev\r
 Name=WinVBlock\r
-UnitCount=67\r
+UnitCount=66\r
 PchHead=-1\r
 PchSource=-1\r
 Ver=3\r
@@ -183,18 +183,8 @@ Priority=1000
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
-[Unit33]\r
-FileName=src\include\disk_scsi.h\r
-CompileCpp=1\r
-Folder=Include\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
 [Unit34]\r
-FileName=src\include\driver.h\r
+FileName=src\include\filedisk.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -204,7 +194,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit35]\r
-FileName=src\include\filedisk.h\r
+FileName=src\include\grub4dos.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -214,7 +204,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit36]\r
-FileName=src\include\grub4dos.h\r
+FileName=src\include\httpdisk.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -234,7 +224,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit37]\r
-FileName=src\include\httpdisk.h\r
+FileName=src\include\irp.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -244,7 +234,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit38]\r
-FileName=src\include\irp.h\r
+FileName=src\include\mdi.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -254,7 +244,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit39]\r
-FileName=src\include\mdi.h\r
+FileName=src\include\memdisk.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -264,7 +254,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit40]\r
-FileName=src\include\memdisk.h\r
+FileName=src\include\mount.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -274,7 +264,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit41]\r
-FileName=src\include\mount.h\r
+FileName=src\include\portable.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -284,7 +274,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit42]\r
-FileName=src\include\portable.h\r
+FileName=src\include\probe.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -294,7 +284,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit43]\r
-FileName=src\include\probe.h\r
+FileName=src\include\protocol.h\r
 Folder=Include\r
 Compile=1\r
 Link=1\r
@@ -304,7 +294,7 @@ BuildCmd=
 CompileCpp=1\r
 \r
 [Unit44]\r
-FileName=src\include\protocol.h\r
+FileName=src\include\ramdisk.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -314,7 +304,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit45]\r
-FileName=src\include\ramdisk.h\r
+FileName=src\include\registry.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -324,7 +314,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit46]\r
-FileName=src\include\registry.h\r
+FileName=src\include\resource.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -334,7 +324,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit47]\r
-FileName=src\include\resource.h\r
+FileName=src\include\winvblock.h\r
 Folder=Include\r
 Compile=1\r
 Link=1\r
@@ -344,9 +334,9 @@ BuildCmd=
 CompileCpp=1\r
 \r
 [Unit48]\r
-FileName=src\include\winvblock.h\r
+FileName=src\util\mount.c\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=Util\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -354,28 +344,28 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit49]\r
-FileName=src\util\mount.c\r
+FileName=src\aoe\aoe.rc\r
 CompileCpp=1\r
-Folder=Util\r
+Folder=AoE\r
 Compile=1\r
-Link=1\r
+Link=0\r
 Priority=1000\r
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
 [Unit50]\r
-FileName=src\aoe\aoe.rc\r
+FileName=src\include\device.h\r
 CompileCpp=1\r
-Folder=AoE\r
+Folder=Include\r
 Compile=1\r
-Link=0\r
+Link=1\r
 Priority=1000\r
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
 [Unit51]\r
-FileName=src\include\device.h\r
-Folder=Include\r
+FileName=src\winvblock\device.c\r
+Folder=WinVBlock\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -384,9 +374,9 @@ BuildCmd=
 CompileCpp=1\r
 \r
 [Unit52]\r
-FileName=src\winvblock\device.c\r
+FileName=src\winvblock\filedisk\filedisk.c\r
 CompileCpp=1\r
-Folder=WinVBlock\r
+Folder=WinVBlock/FileDisk\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -572,7 +562,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit53]\r
-FileName=src\winvblock\filedisk\filedisk.c\r
+FileName=src\winvblock\filedisk\grub4dos.c\r
 Folder=WinVBlock/FileDisk\r
 Compile=1\r
 Link=1\r
@@ -582,9 +572,9 @@ BuildCmd=
 CompileCpp=1\r
 \r
 [Unit54]\r
-FileName=src\winvblock\filedisk\grub4dos.c\r
+FileName=src\include\byte.h\r
 CompileCpp=1\r
-Folder=WinVBlock/FileDisk\r
+Folder=Include\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -592,7 +582,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit55]\r
-FileName=src\include\byte.h\r
+FileName=src\include\msvhd.h\r
 CompileCpp=1\r
 Folder=Include\r
 Compile=1\r
@@ -612,29 +602,29 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit56]\r
-FileName=src\include\msvhd.h\r
+FileName=src\util\winvblock.rc\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=Util\r
 Compile=1\r
-Link=1\r
+Link=0\r
 Priority=1000\r
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
 [Unit57]\r
-FileName=src\util\winvblock.rc\r
+FileName=src\include\wv_stdlib.h\r
 CompileCpp=1\r
-Folder=Util\r
+Folder=Include\r
 Compile=1\r
-Link=0\r
+Link=1\r
 Priority=1000\r
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
 [Unit58]\r
-FileName=src\include\wv_stdlib.h\r
+FileName=src\winvblock\wv_stdlib.c\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=WinVBlock\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -642,8 +632,8 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit59]\r
-FileName=src\winvblock\wv_stdlib.c\r
-Folder=WinVBlock\r
+FileName=src\include\wv_stddef.h\r
+Folder=Include\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -652,9 +642,9 @@ BuildCmd=
 CompileCpp=1\r
 \r
 [Unit61]\r
-FileName=src\aoe\wv_stdlib.c\r
+FileName=src\include\wv_string.h\r
 CompileCpp=1\r
-Folder=AoE\r
+Folder=Include\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -662,9 +652,9 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit60]\r
-FileName=src\include\wv_stddef.h\r
+FileName=src\aoe\wv_stdlib.c\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=AoE\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -672,9 +662,9 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit62]\r
-FileName=src\include\wv_string.h\r
+FileName=src\winvblock\wv_string.c\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=WinVBlock\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -682,9 +672,9 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit63]\r
-FileName=src\winvblock\wv_string.c\r
+FileName=src\include\wv_stdbool.h\r
 CompileCpp=1\r
-Folder=WinVBlock\r
+Folder=Include\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -692,9 +682,9 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit64]\r
-FileName=src\include\wv_stdbool.h\r
+FileName=src\aoe\wv_string.c\r
 CompileCpp=1\r
-Folder=Include\r
+Folder=AoE\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -702,7 +692,7 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit65]\r
-FileName=src\aoe\wv_string.c\r
+FileName=src\aoe\bus.c\r
 CompileCpp=1\r
 Folder=AoE\r
 Compile=1\r
@@ -712,9 +702,9 @@ OverrideBuildCmd=0
 BuildCmd=\r
 \r
 [Unit66]\r
-FileName=src\aoe\bus.c\r
+FileName=src\include\aoe_bus.h\r
 CompileCpp=1\r
-Folder=AoE\r
+Folder=Include\r
 Compile=1\r
 Link=1\r
 Priority=1000\r
@@ -771,3 +761,13 @@ Priority=1000
 OverrideBuildCmd=0\r
 BuildCmd=\r
 \r
+[Unit33]\r
+FileName=src\include\driver.h\r
+CompileCpp=1\r
+Folder=Include\r
+Compile=1\r
+Link=1\r
+Priority=1000\r
+OverrideBuildCmd=0\r
+BuildCmd=\r
+\r
index a955692..7a3a90e 100644 (file)
@@ -132,12 +132,27 @@ typedef NTSTATUS STDCALL device__dev_ctl_func(
     IN ULONG POINTER_ALIGNMENT
   );
 
+/**
+ * The prototype for a device IRP_MJ_SCSI dispatch.
+ *
+ * @v dev               Points to the device.
+ * @v irp               Points to the IRP.
+ * @v code              The SCSI function.
+ * @v srb               The SCSI request block.
+ * @ret NTSTATUS        The status of processing the IRP for the device.
+ */
+typedef NTSTATUS STDCALL device__scsi_func(
+    IN struct device__type *,
+    IN PIRP,
+    IN UCHAR
+  );
 
 /* IRP major function handler table. */
 struct device__irp_mj {
     device__dispatch_func * power;
     device__dispatch_func * sys_ctl;
     device__dev_ctl_func * dev_ctl;
+    device__scsi_func * scsi;
   };
 
 /* Details common to all devices this driver works with */
diff --git a/src/include/disk_scsi.h b/src/include/disk_scsi.h
deleted file mode 100644 (file)
index 176498e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (C) 2009-2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
- * Copyright 2006-2008, V.
- * For WinAoE contact information, see http://winaoe.org/
- *
- * This file is part of WinVBlock, derived from WinAoE.
- *
- * WinVBlock is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * WinVBlock is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 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 WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef _DISK_SCSI_H
-#  define _DISK_SCSI_H
-
-/**
- * @file
- *
- * Disk SCSI IRP handling.
- */
-
-extern irp__handler disk_scsi__dispatch;
-
-#endif                         /* _DISK_SCSI_H */
index ab7d668..3a0bc2c 100644 (file)
@@ -51,6 +51,7 @@ struct device__irp_mj bus__irp_mj_ = {
     bus__power_,
     bus__sys_ctl_,
     bus_dev_ctl__dispatch,
+    (device__scsi_func *) 0,
   };
 
 /**
index 48ad661..91b53d4 100644 (file)
@@ -35,7 +35,6 @@
 #include "device.h"
 #include "disk.h"
 #include "disk_pnp.h"
-#include "disk_scsi.h"
 #include "debug.h"
 
 #ifndef _MSC_VER
@@ -51,6 +50,8 @@ __divdi3 (
 
 /* IRP_MJ_DEVICE_CONTROL dispatcher from disk/dev_ctl.c */
 extern device__dev_ctl_func disk_dev_ctl__dispatch;
+/* IRP_MJ_SCSI dispatcher from disk/scsi.c */
+extern device__scsi_func disk_scsi__dispatch;
 
 /* Forward declarations. */
 static device__free_func free_disk;
@@ -67,6 +68,7 @@ struct device__irp_mj disk__irp_mj_ = {
     disk__power_,
     disk__sys_ctl_,
     disk_dev_ctl__dispatch,
+    disk_scsi__dispatch,
   };
 
 static
@@ -357,7 +359,6 @@ static NTSTATUS STDCALL (disk_dispatch)(
          * Why? It sets completion to true, so others won't be called.
          */
         {                     0, 0,  TRUE,  TRUE,  driver__not_supported },
-        {           IRP_MJ_SCSI, 0, FALSE,  TRUE,    disk_scsi__dispatch },
         {            IRP_MJ_PNP, 0, FALSE,  TRUE,       disk_pnp__simple },
         {            IRP_MJ_PNP,
          IRP_MN_QUERY_CAPABILITIES, FALSE, FALSE,
index 0ddf070..11b9a3a 100644 (file)
 #include "disk.h"
 #include "debug.h"
 
+/**
+ * The prototype for a disk SCSI function.
+ *
+ * @v dev               Points to the disk's device for the SCSI request.
+ * @v irp               Points to the IRP.
+ * @v disk              Points to the disk for the SCSI request.
+ * @v srb               Points to the SCSI request block.
+ * @v cdb               Points to the command descriptor block.
+ * @v completion        Points to a boolean for whether the IRP has
+ *                      been completed or not.
+ * @ret NTSTATUS        The status of the SCSI operation.
+ */
+typedef NTSTATUS STDCALL disk_scsi__func(
+    IN struct device__type *,
+    IN PIRP,
+    IN disk__type_ptr,
+    IN PSCSI_REQUEST_BLOCK,
+    IN PCDB,
+    OUT winvblock__bool_ptr
+  );
+
+/* Forward declarations. */
+disk_scsi__func disk_scsi__read_write_;
+disk_scsi__func disk_scsi__verify_;
+disk_scsi__func disk_scsi__read_capacity_;
+disk_scsi__func disk_scsi__read_capacity_16_;
+disk_scsi__func disk_scsi__mode_sense_;
+disk_scsi__func disk_scsi__read_toc_;
+device__scsi_func disk_scsi__dispatch;
+
 #if _WIN32_WINNT <= 0x0600
-#  if 0                                /* FIXME: To build with WINDDK 6001.18001 */
+#  if 0        /* FIXME: To build with WINDDK 6001.18001 */
 #    ifdef _MSC_VER
 #      pragma pack(1)
 #    endif
@@ -61,10 +91,10 @@ typedef union _EIGHT_BYTE
 #    ifdef _MSC_VER
 #      pragma pack()
 #    endif
-#  endif                       /* To build with WINDDK 6001.18001 */
+#  endif      /* To build with WINDDK 6001.18001 */
 
 #  if _WIN32_WINNT < 0x0500
-#    if 0                      /* FIXME: To build with WINDDK 6001.18001 */
+#    if 0      /* FIXME: To build with WINDDK 6001.18001 */
 #      ifdef _MSC_VER
 #        pragma pack(1)
 #      endif
@@ -77,8 +107,8 @@ typedef struct _READ_CAPACITY_DATA_EX
 #      ifdef _MSC_VER
 #        pragma pack()
 #      endif
-#    endif                     /* To build with WINDDK 6001.18001 */
-#  endif                       /* _WIN32_WINNT < 0x0500 */
+#    endif      /* To build with WINDDK 6001.18001 */
+#  endif      /* _WIN32_WINNT < 0x0500 */
 
 #  ifdef _MSC_VER
 #    pragma pack(1)
@@ -111,346 +141,388 @@ typedef struct _DISK_CDB16
   d->Byte1 = s->Byte6;                            \
   d->Byte0 = s->Byte7;                            \
 }
-#endif                         /* if _WIN32_WINNT <= 0x0600 */
-
-#define scsi_op( x ) \
-\
-NTSTATUS STDCALL                                \
-x (                                             \
-  IN struct device__type * dev_ptr,             \
-  IN PIRP Irp,                                  \
-  IN disk__type_ptr disk_ptr,                   \
-  IN PSCSI_REQUEST_BLOCK Srb,                   \
-  IN PCDB Cdb,                                  \
-  OUT winvblock__bool_ptr completion_ptr        \
- )
-
-static
-scsi_op (
-  read_write
- )
-{
-  ULONGLONG start_sector;
-  winvblock__uint32 sector_count;
-  NTSTATUS status = STATUS_SUCCESS;
-
-  if ( Cdb->AsByte[0] == SCSIOP_READ16 || Cdb->AsByte[0] == SCSIOP_WRITE16 )
-    {
-      REVERSE_BYTES_QUAD ( &start_sector,
-                          &( ( ( PDISK_CDB16 ) Cdb )->LogicalBlock[0] ) );
-      REVERSE_BYTES ( &sector_count,
-                     &( ( ( PDISK_CDB16 ) Cdb )->TransferLength[0] ) );
-    }
-  else
-    {
-      start_sector =
-       ( Cdb->CDB10.LogicalBlockByte0 << 24 ) +
-       ( Cdb->CDB10.LogicalBlockByte1 << 16 ) +
-       ( Cdb->CDB10.LogicalBlockByte2 << 8 ) + Cdb->CDB10.LogicalBlockByte3;
-      sector_count =
-       ( Cdb->CDB10.TransferBlocksMsb << 8 ) + Cdb->CDB10.TransferBlocksLsb;
-    }
-  if ( start_sector >= disk_ptr->LBADiskSize )
-    {
-      DBG ( "Fixed sector_count (start_sector off disk)!!\n" );
-      sector_count = 0;
-    }
-  if ( ( start_sector + sector_count > disk_ptr->LBADiskSize )
-       && sector_count != 0 )
-    {
-      DBG ( "Fixed sector_count (start_sector + "
-           "sector_count off disk)!!\n" );
-      sector_count =
-       ( winvblock__uint32 ) ( disk_ptr->LBADiskSize - start_sector );
-    }
-  if ( sector_count * disk_ptr->SectorSize > Srb->DataTransferLength )
-    {
-      DBG ( "Fixed sector_count (DataTransferLength " "too small)!!\n" );
-      sector_count = Srb->DataTransferLength / disk_ptr->SectorSize;
-    }
-  if ( Srb->DataTransferLength % disk_ptr->SectorSize != 0 )
-    DBG ( "DataTransferLength not aligned!!\n" );
-  if ( Srb->DataTransferLength > sector_count * disk_ptr->SectorSize )
-    DBG ( "DataTransferLength too big!!\n" );
-
-  Srb->DataTransferLength = sector_count * disk_ptr->SectorSize;
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  if ( sector_count == 0 )
-    {
-      Irp->IoStatus.Information = 0;
-      return status;
-    }
-
-  if ( ( ( ( winvblock__uint8_ptr ) Srb->DataBuffer -
-          ( winvblock__uint8_ptr )
-          MmGetMdlVirtualAddress ( Irp->MdlAddress ) ) +
-        ( winvblock__uint8_ptr )
-        MmGetSystemAddressForMdlSafe ( Irp->MdlAddress,
-                                       HighPagePriority ) ) == NULL )
-    {
-      status = STATUS_INSUFFICIENT_RESOURCES;
-      Irp->IoStatus.Information = 0;
-      return status;
-    }
-
-  if ( Cdb->AsByte[0] == SCSIOP_READ || Cdb->AsByte[0] == SCSIOP_READ16 )
-    {
-      status =
-       disk__io ( dev_ptr, disk__io_mode_read, start_sector, sector_count,
-                  ( ( winvblock__uint8_ptr ) Srb->DataBuffer -
-                    ( winvblock__uint8_ptr )
-                    MmGetMdlVirtualAddress ( Irp->MdlAddress ) ) +
-                  ( winvblock__uint8_ptr )
-                  MmGetSystemAddressForMdlSafe ( Irp->MdlAddress,
-                                                 HighPagePriority ), Irp );
-    }
-  else
-    {
-      status =
-       disk__io ( dev_ptr, disk__io_mode_write, start_sector, sector_count,
-                  ( ( winvblock__uint8_ptr ) Srb->DataBuffer -
-                    ( winvblock__uint8_ptr )
-                    MmGetMdlVirtualAddress ( Irp->MdlAddress ) ) +
-                  ( winvblock__uint8_ptr )
-                  MmGetSystemAddressForMdlSafe ( Irp->MdlAddress,
-                                                 HighPagePriority ), Irp );
-    }
-  if ( status != STATUS_PENDING )
-    *completion_ptr = TRUE;
-  return status;
-}
+#endif        /* if _WIN32_WINNT <= 0x0600 */
 
-static
-scsi_op (
-  verify
- )
-{
-  LONGLONG start_sector;
-  winvblock__uint32 sector_count;
-
-  if ( Cdb->AsByte[0] == SCSIOP_VERIFY16 )
-    {
-      REVERSE_BYTES_QUAD ( &start_sector,
-                          &( ( ( PDISK_CDB16 ) Cdb )->LogicalBlock[0] ) );
-      REVERSE_BYTES ( &sector_count,
-                     &( ( ( PDISK_CDB16 ) Cdb )->TransferLength[0] ) );
-    }
-  else
-    {
-      start_sector =
-       ( Cdb->CDB10.LogicalBlockByte0 << 24 ) +
-       ( Cdb->CDB10.LogicalBlockByte1 << 16 ) +
-       ( Cdb->CDB10.LogicalBlockByte2 << 8 ) + Cdb->CDB10.LogicalBlockByte3;
-      sector_count =
-       ( Cdb->CDB10.TransferBlocksMsb << 8 ) + Cdb->CDB10.TransferBlocksLsb;
-    }
-#if 0
-  Srb->DataTransferLength = sector_count * SECTORSIZE;
-#endif
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  return STATUS_SUCCESS;
-}
+static NTSTATUS STDCALL disk_scsi__read_write_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    ULONGLONG start_sector;
+    winvblock__uint32 sector_count;
+    NTSTATUS status = STATUS_SUCCESS;
 
-static
-scsi_op (
-  read_capacity
- )
-{
-  winvblock__uint32 temp = disk_ptr->SectorSize;
-  PREAD_CAPACITY_DATA data = ( PREAD_CAPACITY_DATA ) Srb->DataBuffer;
-
-  REVERSE_BYTES ( &data->BytesPerBlock, &temp );
-  if ( ( disk_ptr->LBADiskSize - 1 ) > 0xffffffff )
-    {
-      data->LogicalBlockAddress = -1;
-    }
-  else
-    {
-      temp = ( winvblock__uint32 ) ( disk_ptr->LBADiskSize - 1 );
-      REVERSE_BYTES ( &data->LogicalBlockAddress, &temp );
-    }
-  Irp->IoStatus.Information = sizeof ( READ_CAPACITY_DATA );
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  return STATUS_SUCCESS;
-}
+    if (cdb->AsByte[0] == SCSIOP_READ16 || cdb->AsByte[0] == SCSIOP_WRITE16) {
+        REVERSE_BYTES_QUAD(
+            &start_sector,
+            &(((PDISK_CDB16) cdb)->LogicalBlock[0])
+          );
+        REVERSE_BYTES(
+            &sector_count,
+            &(((PDISK_CDB16) cdb )->TransferLength[0])
+          );
+      } else {
+        start_sector = (cdb->CDB10.LogicalBlockByte0 << 24) +
+          (cdb->CDB10.LogicalBlockByte1 << 16) +
+          (cdb->CDB10.LogicalBlockByte2 << 8 ) +
+          cdb->CDB10.LogicalBlockByte3;
+        sector_count = (cdb->CDB10.TransferBlocksMsb << 8) +
+          cdb->CDB10.TransferBlocksLsb;
+      }
+    if (start_sector >= disk->LBADiskSize) {
+        DBG("Fixed sector_count (start_sector off disk)!!\n");
+        sector_count = 0;
+      }
+    if (
+        (start_sector + sector_count > disk->LBADiskSize) &&
+        sector_count != 0
+      ) {
+        DBG("Fixed sector_count (start_sector + sector_count off disk)!!\n");
+        sector_count = (winvblock__uint32) (disk->LBADiskSize - start_sector);
+      }
+    if (sector_count * disk->SectorSize > srb->DataTransferLength) {
+        DBG("Fixed sector_count (DataTransferLength " "too small)!!\n");
+        sector_count = srb->DataTransferLength / disk->SectorSize;
+      }
+    if (srb->DataTransferLength % disk->SectorSize != 0)
+      DBG("DataTransferLength not aligned!!\n");
+    if (srb->DataTransferLength > sector_count * disk->SectorSize)
+      DBG("DataTransferLength too big!!\n");
 
-static
-scsi_op (
-  read_capacity_16
- )
-{
-  winvblock__uint32 temp;
-  LONGLONG big_temp;
-
-  temp = disk_ptr->SectorSize;
-  REVERSE_BYTES ( &
-                 ( ( ( PREAD_CAPACITY_DATA_EX ) Srb->DataBuffer )->
-                   BytesPerBlock ), &temp );
-  big_temp = disk_ptr->LBADiskSize - 1;
-  REVERSE_BYTES_QUAD ( &
-                      ( ( ( PREAD_CAPACITY_DATA_EX ) Srb->DataBuffer )->
-                        LogicalBlockAddress.QuadPart ), &big_temp );
-  Irp->IoStatus.Information = sizeof ( READ_CAPACITY_DATA_EX );
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  return STATUS_SUCCESS;
-}
+    srb->DataTransferLength = sector_count * disk->SectorSize;
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    if (sector_count == 0) {
+        irp->IoStatus.Information = 0;
+        return status;
+      }
 
-static
-scsi_op (
-  mode_sense
- )
-{
-  PMODE_PARAMETER_HEADER mode_param_header;
-  static MEDIA_TYPE media_types[disk__media_count] =
-    { RemovableMedia, FixedMedia, RemovableMedia };
-
-  if ( Srb->DataTransferLength < sizeof ( MODE_PARAMETER_HEADER ) )
-    {
-      Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-      return STATUS_SUCCESS;
-    }
-  mode_param_header = ( PMODE_PARAMETER_HEADER ) Srb->DataBuffer;
-  RtlZeroMemory ( mode_param_header, Srb->DataTransferLength );
-  mode_param_header->ModeDataLength = sizeof ( MODE_PARAMETER_HEADER );
-  mode_param_header->MediumType = media_types[disk_ptr->media];
-  mode_param_header->BlockDescriptorLength = 0;
-  Srb->DataTransferLength = sizeof ( MODE_PARAMETER_HEADER );
-  Irp->IoStatus.Information = sizeof ( MODE_PARAMETER_HEADER );
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  return STATUS_SUCCESS;
-}
+    if ((
+        (
+            (winvblock__uint8_ptr) srb->DataBuffer -
+            (winvblock__uint8_ptr) MmGetMdlVirtualAddress(irp->MdlAddress)
+          ) + (winvblock__uint8_ptr) MmGetSystemAddressForMdlSafe(
+              irp->MdlAddress,
+              HighPagePriority
+      )) == NULL) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        irp->IoStatus.Information = 0;
+        return status;
+      }
 
-static
-scsi_op (
-  read_toc
- )
-{
-  /*
-   * With thanks to Olof's ImDisk source
-   */
-  PCDROM_TOC table_of_contents = ( PCDROM_TOC ) Srb->DataBuffer;
-
-  if ( Srb->DataTransferLength < sizeof ( CDROM_TOC ) )
-    {
-      Irp->IoStatus.Information = 0;
-      Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-      return STATUS_BUFFER_TOO_SMALL;
-    }
-  RtlZeroMemory ( table_of_contents, sizeof ( CDROM_TOC ) );
-
-  table_of_contents->FirstTrack = 1;
-  table_of_contents->LastTrack = 1;
-  table_of_contents->TrackData[0].Control = 4;
-  Irp->IoStatus.Information = sizeof ( CDROM_TOC );
-  Srb->SrbStatus = SRB_STATUS_SUCCESS;
-  return STATUS_SUCCESS;
-}
+    if (cdb->AsByte[0] == SCSIOP_READ || cdb->AsByte[0] == SCSIOP_READ16) {
+        status = disk__io(
+            dev,
+            disk__io_mode_read,
+            start_sector,
+            sector_count,
+            ((winvblock__uint8_ptr) srb->DataBuffer -
+              (winvblock__uint8_ptr) MmGetMdlVirtualAddress(irp->MdlAddress)) +
+              (winvblock__uint8_ptr) MmGetSystemAddressForMdlSafe(
+                  irp->MdlAddress,
+                  HighPagePriority
+              ),
+            irp
+          );
+      } else {
+        status = disk__io(
+            dev,
+            disk__io_mode_write,
+            start_sector,
+            sector_count,
+            ((winvblock__uint8_ptr) srb->DataBuffer -
+              (winvblock__uint8_ptr) MmGetMdlVirtualAddress(irp->MdlAddress)) +
+              (winvblock__uint8_ptr) MmGetSystemAddressForMdlSafe(
+                  irp->MdlAddress,
+                  HighPagePriority
+              ),
+            irp
+          );
+      }
+    if (status != STATUS_PENDING)
+      *completion = TRUE;
+    return status;
+  }
+
+static NTSTATUS STDCALL disk_scsi__verify_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    LONGLONG start_sector;
+    winvblock__uint32 sector_count;
+
+    if (cdb->AsByte[0] == SCSIOP_VERIFY16) {
+        REVERSE_BYTES_QUAD(
+            &start_sector,
+            &(((PDISK_CDB16) cdb)->LogicalBlock[0])
+          );
+        REVERSE_BYTES(
+            &sector_count,
+            &(((PDISK_CDB16) cdb)->TransferLength[0])
+          );
+      } else {
+        start_sector = (cdb->CDB10.LogicalBlockByte0 << 24) +
+          (cdb->CDB10.LogicalBlockByte1 << 16) +
+          (cdb->CDB10.LogicalBlockByte2 << 8) +
+          cdb->CDB10.LogicalBlockByte3;
+        sector_count = (cdb->CDB10.TransferBlocksMsb << 8) +
+          cdb->CDB10.TransferBlocksLsb;
+      }
+    #if 0
+    srb->DataTransferLength = sector_count * SECTORSIZE;
+    #endif
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+  }
+
+static NTSTATUS STDCALL disk_scsi__read_capacity_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    winvblock__uint32 temp = disk->SectorSize;
+    PREAD_CAPACITY_DATA data = (PREAD_CAPACITY_DATA) srb->DataBuffer;
+
+    REVERSE_BYTES(&data->BytesPerBlock, &temp);
+    if ((disk->LBADiskSize - 1) > 0xffffffff) {
+        data->LogicalBlockAddress = -1;
+      } else {
+        temp = (winvblock__uint32) (disk->LBADiskSize - 1);
+        REVERSE_BYTES(&data->LogicalBlockAddress, &temp);
+      }
+    irp->IoStatus.Information = sizeof (READ_CAPACITY_DATA);
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+  }
+
+static NTSTATUS STDCALL disk_scsi__read_capacity_16_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    winvblock__uint32 temp;
+    LONGLONG big_temp;
+
+    temp = disk->SectorSize;
+    REVERSE_BYTES(
+        &(((PREAD_CAPACITY_DATA_EX) srb->DataBuffer)->BytesPerBlock),
+        &temp
+      );
+    big_temp = disk->LBADiskSize - 1;
+    REVERSE_BYTES_QUAD(
+        &(((PREAD_CAPACITY_DATA_EX) srb->DataBuffer)->
+          LogicalBlockAddress.QuadPart),
+        &big_temp
+      );
+    irp->IoStatus.Information = sizeof (READ_CAPACITY_DATA_EX);
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+  }
+
+static NTSTATUS STDCALL disk_scsi__mode_sense_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    PMODE_PARAMETER_HEADER mode_param_header;
+    static MEDIA_TYPE media_types[disk__media_count] =
+      { RemovableMedia, FixedMedia, RemovableMedia };
+
+    if (srb->DataTransferLength < sizeof (MODE_PARAMETER_HEADER)) {
+        srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+        return STATUS_SUCCESS;
+      }
+    mode_param_header = (PMODE_PARAMETER_HEADER) srb->DataBuffer;
+    RtlZeroMemory(mode_param_header, srb->DataTransferLength);
+    mode_param_header->ModeDataLength = sizeof (MODE_PARAMETER_HEADER);
+    mode_param_header->MediumType = media_types[disk->media];
+    mode_param_header->BlockDescriptorLength = 0;
+    srb->DataTransferLength = sizeof (MODE_PARAMETER_HEADER);
+    irp->IoStatus.Information = sizeof (MODE_PARAMETER_HEADER);
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+  }
+
+static NTSTATUS STDCALL disk_scsi__read_toc_(
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN disk__type_ptr disk,
+    IN PSCSI_REQUEST_BLOCK srb,
+    IN PCDB cdb,
+    OUT winvblock__bool_ptr completion
+  ) {
+    /* With thanks to Olof Lagerkvist's ImDisk source. */
+    PCDROM_TOC table_of_contents = (PCDROM_TOC) srb->DataBuffer;
+
+    if (srb->DataTransferLength < sizeof (CDROM_TOC)) {
+        irp->IoStatus.Information = 0;
+        srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+        return STATUS_BUFFER_TOO_SMALL;
+      }
+    RtlZeroMemory(table_of_contents, sizeof (CDROM_TOC));
+
+    table_of_contents->FirstTrack = 1;
+    table_of_contents->LastTrack = 1;
+    table_of_contents->TrackData[0].Control = 4;
+    irp->IoStatus.Information = sizeof (CDROM_TOC);
+    srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+  }
 
 NTSTATUS STDCALL disk_scsi__dispatch(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp,
-    IN PIO_STACK_LOCATION Stack,
-    IN struct device__type * dev_ptr,
-    OUT winvblock__bool_ptr completion_ptr
-  )
-{
-  NTSTATUS status = STATUS_SUCCESS;
-  disk__type_ptr disk_ptr;
-  PSCSI_REQUEST_BLOCK Srb;
-  PCDB Cdb;
-  winvblock__bool completion = FALSE;
-
-  /*
-   * Establish a pointer to the disk
-   */
-  disk_ptr = disk__get_ptr ( dev_ptr );
-
-  Srb = Stack->Parameters.Scsi.Srb;
-  Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
-  Srb->ScsiStatus = SCSISTAT_GOOD;
-
-  Cdb = ( PCDB ) Srb->Cdb;
-
-  Irp->IoStatus.Information = 0;
-  if ( Srb->Lun != 0 )
-    {
-      DBG ( "Invalid Lun!!\n" );
-      goto ret_path;
-    }
-  switch ( Srb->Function )
-    {
-      case SRB_FUNCTION_EXECUTE_SCSI:
-       switch ( Cdb->AsByte[0] )
-         {
-           case SCSIOP_TEST_UNIT_READY:
-             Srb->SrbStatus = SRB_STATUS_SUCCESS;
-             break;
-           case SCSIOP_READ:
-           case SCSIOP_READ16:
-           case SCSIOP_WRITE:
-           case SCSIOP_WRITE16:
-             status =
-               read_write ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
-             break;
-           case SCSIOP_VERIFY:
-           case SCSIOP_VERIFY16:
-             status =
-               verify ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
-             break;
-           case SCSIOP_READ_CAPACITY:
-             status =
-               read_capacity ( dev_ptr, Irp, disk_ptr, Srb, Cdb,
-                               &completion );
-             break;
-           case SCSIOP_READ_CAPACITY16:
-             status =
-               read_capacity_16 ( dev_ptr, Irp, disk_ptr, Srb, Cdb,
-                                  &completion );
-             break;
-           case SCSIOP_MODE_SENSE:
-             status =
-               mode_sense ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
-             break;
-           case SCSIOP_MEDIUM_REMOVAL:
-             Irp->IoStatus.Information = 0;
-             Srb->SrbStatus = SRB_STATUS_SUCCESS;
-             status = STATUS_SUCCESS;
-             break;
-           case SCSIOP_READ_TOC:
-             status =
-               read_toc ( dev_ptr, Irp, disk_ptr, Srb, Cdb, &completion );
-             break;
-           default:
-             DBG ( "Invalid SCSIOP (%02x)!!\n", Cdb->AsByte[0] );
-             Srb->SrbStatus = SRB_STATUS_ERROR;
-             status = STATUS_NOT_IMPLEMENTED;
-         }
-       break;
-      case SRB_FUNCTION_IO_CONTROL:
-       Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
-       break;
-      case SRB_FUNCTION_CLAIM_DEVICE:
-       Srb->DataBuffer = DeviceObject;
-       break;
-      case SRB_FUNCTION_RELEASE_DEVICE:
-       ObDereferenceObject ( DeviceObject );
-       break;
-      case SRB_FUNCTION_SHUTDOWN:
-      case SRB_FUNCTION_FLUSH:
-       Srb->SrbStatus = SRB_STATUS_SUCCESS;
-       break;
-      default:
-       DBG ( "Invalid SRB FUNCTION (%08x)!!\n", Srb->Function );
-       status = STATUS_NOT_IMPLEMENTED;
-    }
-
-ret_path:
-  if ( !completion )
-    {
-      Irp->IoStatus.Status = status;
-      if ( status != STATUS_PENDING )
-       IoCompleteRequest ( Irp, IO_NO_INCREMENT );
-    }
-  *completion_ptr = TRUE;
-  return status;
-}
+    IN struct device__type * dev,
+    IN PIRP irp,
+    IN UCHAR code
+  ) {
+    disk__type_ptr disk = disk__get_ptr(dev);
+    PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+    PSCSI_REQUEST_BLOCK srb = io_stack_loc->Parameters.Scsi.Srb;
+    NTSTATUS status = STATUS_SUCCESS;
+    PCDB cdb;
+    winvblock__bool completion = FALSE;
+
+    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+    srb->ScsiStatus = SCSISTAT_GOOD;
+
+    cdb = (PCDB) srb->Cdb;
+
+    irp->IoStatus.Information = 0;
+    if (srb->Lun != 0) {
+        DBG("Invalid Lun!!\n");
+        goto out;
+      }
+    switch (code) {
+        case SRB_FUNCTION_EXECUTE_SCSI:
+          switch (cdb->AsByte[0]) {
+              case SCSIOP_TEST_UNIT_READY:
+                srb->SrbStatus = SRB_STATUS_SUCCESS;
+                break;
+
+              case SCSIOP_READ:
+              case SCSIOP_READ16:
+              case SCSIOP_WRITE:
+              case SCSIOP_WRITE16:
+                status = disk_scsi__read_write_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              case SCSIOP_VERIFY:
+              case SCSIOP_VERIFY16:
+                status = disk_scsi__verify_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              case SCSIOP_READ_CAPACITY:
+                status = disk_scsi__read_capacity_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              case SCSIOP_READ_CAPACITY16:
+                status = disk_scsi__read_capacity_16_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              case SCSIOP_MODE_SENSE:
+                status = disk_scsi__mode_sense_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              case SCSIOP_MEDIUM_REMOVAL:
+                irp->IoStatus.Information = 0;
+                srb->SrbStatus = SRB_STATUS_SUCCESS;
+                status = STATUS_SUCCESS;
+                break;
+
+              case SCSIOP_READ_TOC:
+                status = disk_scsi__read_toc_(
+                    dev,
+                    irp,
+                    disk,
+                    srb,
+                    cdb,
+                    &completion
+                  );
+                break;
+
+              default:
+                DBG("Invalid SCSIOP (%02x)!!\n", cdb->AsByte[0]);
+                srb->SrbStatus = SRB_STATUS_ERROR;
+                status = STATUS_NOT_IMPLEMENTED;
+            }
+          break; /* SRB_FUNCTION_EXECUTE_SCSI */
+
+        case SRB_FUNCTION_IO_CONTROL:
+          srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+          break;
+
+        case SRB_FUNCTION_CLAIM_DEVICE:
+          srb->DataBuffer = dev->Self;
+          break;
+
+        case SRB_FUNCTION_RELEASE_DEVICE:
+          ObDereferenceObject(dev->Self);
+          break;
+
+        case SRB_FUNCTION_SHUTDOWN:
+        case SRB_FUNCTION_FLUSH:
+          srb->SrbStatus = SRB_STATUS_SUCCESS;
+          break;
+
+        default:
+          DBG("Invalid SRB FUNCTION (%08x)!!\n", code);
+          status = STATUS_NOT_IMPLEMENTED;
+      }
+
+    out:
+    if (!completion) {
+        irp->IoStatus.Status = status;
+        if (status != STATUS_PENDING)
+          IoCompleteRequest(irp, IO_NO_INCREMENT);
+      }
+    return status;
+  }
index b270552..7c55c5c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <stdio.h>
 #include <ntddk.h>
+#include <scsi.h>
 
 #include "winvblock.h"
 #include "wv_stdlib.h"
@@ -60,6 +61,7 @@ static driver__dispatch_func driver__dispatch_power_;
 static driver__dispatch_func driver__dispatch_create_close_;
 static driver__dispatch_func driver__dispatch_sys_ctl_;
 static driver__dispatch_func driver__dispatch_dev_ctl_;
+static driver__dispatch_func driver__dispatch_scsi_;
 static driver__dispatch_func driver__dispatch_;
 static void STDCALL driver__unload_(IN PDRIVER_OBJECT);
 
@@ -315,7 +317,7 @@ NTSTATUS STDCALL DriverEntry(
       driver__dispatch_sys_ctl_;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
       driver__dispatch_dev_ctl_;
-    DriverObject->MajorFunction[IRP_MJ_SCSI] = driver__dispatch_;
+    DriverObject->MajorFunction[IRP_MJ_SCSI] = driver__dispatch_scsi_;
     /* Set the driver Unload callback. */
     DriverObject->DriverUnload = driver__unload_;
     /* Set the driver AddDevice callback. */
@@ -481,6 +483,33 @@ static NTSTATUS driver__dispatch_dev_ctl_(
     return driver__complete_irp(irp, 0, STATUS_NOT_SUPPORTED);
   }
 
+/* Handle an IRP_MJ_SCSI IRP. */
+static NTSTATUS driver__dispatch_scsi_(
+    IN PDEVICE_OBJECT dev_obj,
+    IN PIRP irp
+  ) {
+    /* device__get() checks for a NULL dev_obj */
+    struct device__type * dev = device__get(dev_obj);
+    PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+
+    #ifdef DEBUGIRPS
+    Debug_IrpStart(dev_obj, irp);
+    #endif
+    /* Check that the device exists. */
+    if (!dev || dev->state == device__state_deleted)
+      return driver__complete_irp(irp, 0, STATUS_NO_SUCH_DEVICE);
+    /* Call the particular device's power handler. */
+    if (dev->irp_mj && dev->irp_mj->scsi) {
+        return dev->irp_mj->scsi(
+            dev,
+            irp,
+            io_stack_loc->Parameters.Scsi.Srb->Function
+          );
+      }
+    /* Otherwise, we don't support the IRP. */
+    return driver__complete_irp(irp, 0, STATUS_NOT_SUPPORTED);
+  }
+
 static NTSTATUS STDCALL driver__dispatch_(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp