+
+#pragma once
+
#include <ntddk.h>
+#define NDEBUG
+#include <debug.h>
#include <usbdi.h>
+#include <hubbusif.h>
+#include <usbbusif.h>
+#include <usbioctl.h>
#include <usbiodef.h>
-#include <initguid.h>
-#include <debug.h>
+#include <usb.h>
+#include <usbdlib.h>
+#include <stdio.h>
+#include <wdmguid.h>
+#include <classpnp.h>
+#include <scsi.h>
#define USB_STOR_TAG 'sbsu'
#define USB_MAXCHILDREN (16)
-NTSTATUS NTAPI
-IoAttachDeviceToDeviceStackSafe(
- IN PDEVICE_OBJECT SourceDevice,
- IN PDEVICE_OBJECT TargetDevice,
- OUT PDEVICE_OBJECT *AttachedToDeviceObject);
-typedef struct _USBSTOR_DEVICE_EXTENSION
+
+#define HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+#define NTOHS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+
+#define HTONL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \
+ ((((unsigned long)(n) & 0xFF00)) << 8) | \
+ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
+ ((((unsigned long)(n) & 0xFF000000)) >> 24))
+
+
+#define NTOHL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \
+ ((((unsigned long)(n) & 0xFF00)) << 8) | \
+ ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
+ ((((unsigned long)(n) & 0xFF000000)) >> 24))
+
+#define USB_RECOVERABLE_ERRORS (USBD_STATUS_STALL_PID | USBD_STATUS_DEV_NOT_RESPONDING \
+ | USBD_STATUS_ENDPOINT_HALTED | USBD_STATUS_NO_BANDWIDTH)
+
+typedef struct __COMMON_DEVICE_EXTENSION__
+{
+ BOOLEAN IsFDO;
+
+}USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
+
+typedef struct
+{
+ USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
+
+ PDEVICE_OBJECT FunctionalDeviceObject; // functional device object
+ PDEVICE_OBJECT PhysicalDeviceObject; // physical device object
+ PDEVICE_OBJECT LowerDeviceObject; // lower device object
+ USB_BUS_INTERFACE_USBDI_V2 BusInterface; // bus interface of device
+ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
+ PUSB_STRING_DESCRIPTOR SerialNumber; // usb serial number
+ PUSBD_INTERFACE_INFORMATION InterfaceInformation; // usb interface information
+ USBD_CONFIGURATION_HANDLE ConfigurationHandle; // usb configuration handle
+ UCHAR BulkInPipeIndex; // bulk in pipe index
+ UCHAR BulkOutPipeIndex; // bulk out pipe index
+ UCHAR MaxLUN; // max lun for device
+ PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
+ KSPIN_LOCK IrpListLock; // irp list lock
+ LIST_ENTRY IrpListHead; // irp list head
+ BOOLEAN IrpListFreeze; // if true the irp list is freezed
+ BOOLEAN ResetInProgress; // if hard reset is in progress
+ ULONG IrpPendingCount; // count of irp pending
+ BOOLEAN SrbActive; // debug field if srb is pending
+}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
+
+typedef struct
+{
+ USBSTOR_COMMON_DEVICE_EXTENSION Common;
+ PDEVICE_OBJECT LowerDeviceObject; // points to FDO
+ UCHAR LUN; // lun id
+ PVOID InquiryData; // USB SCSI inquiry data
+ UCHAR Claimed; // indicating if it has been claimed by upper driver
+ ULONG BlockLength; // length of block
+ ULONG LastLogicBlockAddress; // last block address
+}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
+
+//
+// max lun command identifier
+//
+#define USB_BULK_GET_MAX_LUN 0xFE
+
+#include <pshpack1.h>
+typedef struct
+{
+ ULONG Signature; // CBW signature
+ ULONG Tag; // CBW Tag of operation
+ ULONG DataTransferLength; // data transfer length
+ UCHAR Flags; // CBW Flags endpoint direction
+ UCHAR LUN; // lun unit
+ UCHAR CommandBlockLength; // Command block length
+ UCHAR CommandBlock[16];
+}CBW, *PCBW;
+
+C_ASSERT(sizeof(CBW) == 31);
+
+
+#define CBW_SIGNATURE 0x43425355
+#define MAX_LUN 0xF
+
+typedef struct
+{
+ ULONG Signature; // CSW signature
+ ULONG Tag; // CSW tag
+ ULONG DataResidue; // CSW data transfer diff
+ UCHAR Status; // CSW status
+}CSW, *PCSW;
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI INQUIRY command
+//
+typedef struct
+{
+ UCHAR Code; // operation code 0x12
+ UCHAR LUN; // lun address
+ UCHAR PageCode; // product data information, always 0x00
+ UCHAR Reserved; // reserved 0x00
+ UCHAR AllocationLength; // length of inquiry data to be returned, default 36 bytes
+ UCHAR Reserved1[7]; //reserved bytes 0x00
+}UFI_INQUIRY_CMD, *PUFI_INQUIRY_CMD;
+
+C_ASSERT(sizeof(UFI_INQUIRY_CMD) == 12);
+
+#define UFI_INQUIRY_CMD_LEN 0x6
+
+//
+// UFI INQUIRY command response
+//
+typedef struct
+{
+ UCHAR DeviceType; // device type
+ UCHAR RMB; // removable media bit
+ UCHAR Version; // contains version 0x00
+ UCHAR Format; // response format
+ UCHAR Length; // additional length
+ UCHAR Reserved[3]; // reserved
+ UCHAR Vendor[8]; // vendor identification string
+ UCHAR Product[16]; // product identification string
+ UCHAR Revision[4]; // product revision code
+}UFI_INQUIRY_RESPONSE, *PUFI_INQUIRY_RESPONSE;
+
+C_ASSERT(sizeof(UFI_INQUIRY_RESPONSE) == 36);
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI read cmd
+//
+typedef struct
{
- BOOLEAN IsFDO;
- struct usb_device* dev;
- PDEVICE_OBJECT LowerDevice;
+ UCHAR Code; // operation code
+ UCHAR LUN; // lun
+ UCHAR LogicalBlockByte0; // lba byte 0
+ UCHAR LogicalBlockByte1; // lba byte 1
+ UCHAR LogicalBlockByte2; // lba byte 2
+ UCHAR LogicalBlockByte3; // lba byte 3
+ UCHAR Reserved; // reserved 0x00
+ UCHAR ContiguousLogicBlocksByte0; // msb contigious logic blocks byte
+ UCHAR ContiguousLogicBlocksByte1; // msb contigious logic blocks
+ UCHAR Reserved1[3]; // reserved 0x00
+}UFI_READ_WRITE_CMD;
- PDEVICE_OBJECT Children[USB_MAXCHILDREN];
+C_ASSERT(sizeof(UFI_READ_WRITE_CMD) == 12);
- /* Fields valid only when IsFDO == FALSE */
- UNICODE_STRING DeviceDescription; // REG_SZ
- UNICODE_STRING DeviceId; // REG_SZ
- UNICODE_STRING InstanceId; // REG_SZ
- UNICODE_STRING HardwareIds; // REG_MULTI_SZ
- UNICODE_STRING CompatibleIds; // REG_MULTI_SZ
- UNICODE_STRING SymbolicLinkName;
-} USBSTOR_DEVICE_EXTENSION, *PUSBSTOR_DEVICE_EXTENSION;
+#define UFI_READ_WRITE_CMD_LEN (0xA)
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI read capacity cmd
+//
+typedef struct
+{
+ UCHAR Code; // operation code 0x25
+ UCHAR LUN; // lun address
+ UCHAR LBA[4]; // logical block address, should be zero
+ UCHAR Reserved1[2]; // reserved 0x00
+ UCHAR PMI; // PMI = 0x00
+ UCHAR Reserved2[3]; // reserved 0x00
+}UFI_CAPACITY_CMD, *PUFI_CAPACITY_CMD;
+
+C_ASSERT(sizeof(UFI_CAPACITY_CMD) == 12);
+
+#define UFI_CAPACITY_CMD_LEN 0xA //FIXME support length 16 too if requested
+
+//
+// UFI Read Capcacity command response
+//
+typedef struct
+{
+ ULONG LastLogicalBlockAddress; // last logical block address
+ ULONG BlockLength; // block length in bytes
+}UFI_CAPACITY_RESPONSE, *PUFI_CAPACITY_RESPONSE;
+
+C_ASSERT(sizeof(UFI_CAPACITY_RESPONSE) == 8);
-/* cleanup.c */
-NTSTATUS NTAPI
-UsbStorCleanup(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI sense mode cmd
+//
+typedef struct
+{
+ UCHAR Code; // operation code
+ UCHAR LUN; // lun address
+ UCHAR PageCode:6; // page code selector
+ UCHAR PC:2; // type of parameters to be returned
+ UCHAR Reserved[4]; // reserved 0x00
+ USHORT AllocationLength; // parameters length
+ UCHAR Reserved1[3];
+}UFI_SENSE_CMD, *PUFI_SENSE_CMD;
+
+C_ASSERT(sizeof(UFI_SENSE_CMD) == 12);
+
+#define UFI_SENSE_CMD_LEN (6)
+
+typedef struct
+{
+ USHORT ModeDataLength; // length of parameters for sense cmd
+ UCHAR MediumTypeCode; // 00 for mass storage, 0x94 for floppy
+ UCHAR WP:1; // write protect bit
+ UCHAR Reserved1:2; // reserved 00
+ UCHAR DPOFUA:1; // should be zero
+ UCHAR Reserved2:4; // reserved
+ UCHAR Reserved[4]; // reserved
+}UFI_MODE_PARAMETER_HEADER, *PUFI_MODE_PARAMETER_HEADER;
-/* fdo.c */
-NTSTATUS NTAPI
-UsbStorPnpFdo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+C_ASSERT(sizeof(UFI_MODE_PARAMETER_HEADER) == 8);
+
+typedef struct
+{
+ UCHAR PC;
+ UCHAR PageLength;
+ UCHAR Reserved1;
+ UCHAR ITM;
+ UCHAR Flags;
+ UCHAR Reserved[3];
+}UFI_TIMER_PROTECT_PAGE, *PUFI_TIMER_PROTECT_PAGE;
+C_ASSERT(sizeof(UFI_TIMER_PROTECT_PAGE) == 8);
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// UFI test unit command
+//
+
+typedef struct
+{
+ UCHAR Code; // operation code 0x00
+ UCHAR LUN; // lun
+ UCHAR Reserved[10]; // reserved 0x00
+}UFI_TEST_UNIT_CMD, *PUFI_TEST_UNIT_CMD;
+
+C_ASSERT(sizeof(UFI_TEST_UNIT_CMD) == 12);
+
+#define UFI_TEST_UNIT_CMD_LEN (6)
+
+typedef struct
+{
+ union
+ {
+ PCBW cbw;
+ PCSW csw;
+ };
+ URB Urb;
+ PIRP Irp;
+ ULONG TransferDataLength;
+ PUCHAR TransferData;
+ PFDO_DEVICE_EXTENSION FDODeviceExtension;
+ PPDO_DEVICE_EXTENSION PDODeviceExtension;
+ PMDL TransferBufferMDL;
+ PKEVENT Event;
+}IRP_CONTEXT, *PIRP_CONTEXT;
+
+typedef struct _ERRORHANDLER_WORKITEM_DATA
+{
+ PDEVICE_OBJECT DeviceObject;
+ PIRP_CONTEXT Context;
+ WORK_QUEUE_ITEM WorkQueueItem;
+} ERRORHANDLER_WORKITEM_DATA, *PERRORHANDLER_WORKITEM_DATA;
+
+
+//---------------------------------------------------------------------
+//
+// fdo.c routines
+//
NTSTATUS
-UsbStorDeviceControlFdo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+USBSTOR_FdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
-/* misc.c */
+//---------------------------------------------------------------------
+//
+// pdo.c routines
+//
NTSTATUS
-ForwardIrpAndWait(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+USBSTOR_PdoHandlePnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
-NTSTATUS NTAPI
-ForwardIrpAndForget(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+NTSTATUS
+USBSTOR_CreatePDO(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PDEVICE_OBJECT *ChildDeviceObject);
+//---------------------------------------------------------------------
+//
+// misc.c routines
+//
NTSTATUS
-UsbStorDuplicateUnicodeString(
- OUT PUNICODE_STRING Destination,
- IN PUNICODE_STRING Source,
- IN POOL_TYPE PoolType);
+NTAPI
+USBSTOR_SyncForwardIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp);
NTSTATUS
-UsbStorInitMultiSzString(
- OUT PUNICODE_STRING Destination,
- ... /* list of PCSZ */);
+NTAPI
+USBSTOR_GetBusInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface);
-/* pdo.c */
-NTSTATUS NTAPI
-UsbStorPnpPdo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+PVOID
+AllocateItem(
+ IN POOL_TYPE PoolType,
+ IN ULONG ItemSize);
+
+VOID
+FreeItem(
+ IN PVOID Item);
+
+NTSTATUS
+USBSTOR_SyncUrbRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ OUT PURB UrbRequest);
NTSTATUS
-UsbStorDeviceControlPdo(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
+USBSTOR_GetMaxLUN(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrpCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context);
+
+
+//---------------------------------------------------------------------
+//
+// descriptor.c routines
+//
+
+NTSTATUS
+USBSTOR_GetDescriptors(
+ IN PDEVICE_OBJECT DeviceObject);
+
+NTSTATUS
+USBSTOR_SelectConfigurationAndInterface(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+NTSTATUS
+USBSTOR_GetPipeHandles(
+ IN PFDO_DEVICE_EXTENSION DeviceExtension);
+
+//---------------------------------------------------------------------
+//
+// scsi.c routines
+//
+NTSTATUS
+USBSTOR_HandleExecuteSCSI(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+USBSTOR_SendInquiryCmd(
+ IN PDEVICE_OBJECT DeviceObject);
+
+//---------------------------------------------------------------------
+//
+// disk.c routines
+//
+NTSTATUS
+USBSTOR_HandleInternalDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+USBSTOR_HandleDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+//---------------------------------------------------------------------
+//
+// queue.c routines
+//
+VOID
+NTAPI
+USBSTOR_StartIo(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp);
+
+VOID
+USBSTOR_QueueFlushIrps(
+ IN PDEVICE_OBJECT DeviceObject);
+
+VOID
+USBSTOR_QueueRelease(
+ IN PDEVICE_OBJECT DeviceObject);
+
+BOOLEAN
+USBSTOR_QueueAddIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+VOID
+NTAPI
+USBSTOR_CancelIo(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+VOID
+USBSTOR_QueueInitialize(
+ PFDO_DEVICE_EXTENSION FDODeviceExtension);
+
+VOID
+NTAPI
+ErrorHandlerWorkItemRoutine(
+ PVOID Context);
+
+VOID
+USBSTOR_QueueNextRequest(
+ IN PDEVICE_OBJECT DeviceObject);
+VOID
+USBSTOR_QueueTerminateRequest(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN BOOLEAN ModifySrbState);