#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 _COMMON_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;
-}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
+}USBSTOR_COMMON_DEVICE_EXTENSION, *PUSBSTOR_COMMON_DEVICE_EXTENSION;
typedef struct
{
- COMMON_DEVICE_EXTENSION Common; // common device extension
+ USBSTOR_COMMON_DEVICE_EXTENSION Common; // common device extension
PDEVICE_OBJECT FunctionalDeviceObject; // functional device object
PDEVICE_OBJECT PhysicalDeviceObject; // physical 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
{
- COMMON_DEVICE_EXTENSION Common;
+ 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
+{
+ 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;
+
+C_ASSERT(sizeof(UFI_READ_WRITE_CMD) == 12);
+
+#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);
+
+//--------------------------------------------------------------------------------------------------------------------------------------------
+//
+// 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;
+
+
+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
IN PDEVICE_OBJECT DeviceObject,
IN PFDO_DEVICE_EXTENSION DeviceExtension);
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrpCompletionRoutine(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context);
+
//---------------------------------------------------------------------
//
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);