|
|
/*++
Copyright (c) 1996-2001 Microsoft Corporation
Module Name:
USBMASS.H
Abstract:
Header file for USBSTOR driver
Environment:
kernel mode
Revision History:
06-01-98 : started rewrite
--*/
//*****************************************************************************
// I N C L U D E S
//*****************************************************************************
#include <scsi.h>
#include "dbg.h"
//*****************************************************************************
// D E F I N E S
//*****************************************************************************
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define CLASS_URB(urb) urb->UrbControlVendorClassRequest
#define FEATURE_URB(urb) urb->UrbControlFeatureRequest
#define USBSTOR_MAX_TRANSFER_SIZE 0x00010000
#define USBSTOR_MAX_TRANSFER_PAGES ((USBSTOR_MAX_TRANSFER_SIZE/PAGE_SIZE)+1)
// Interface Descriptor values
//
#define USBSTOR_SUBCLASS_RBC 0x01
#define USBSTOR_SUBCLASS_SFF8020i 0x02
#define USBSTOR_SUBCLASS_QIC157 0x03
#define USBSTOR_SUBCLASS_SFF8070i_UFI 0x04
#define USBSTOR_SUBCLASS_SFF8070i 0x05
#define USBSTOR_SUBCLASS_SCSI_PASSTHROUGH 0x06
#define USBSTOR_PROTOCOL_BULK_ONLY 0x50
#define USBSTOR_DO_TYPE_FDO '!ODF'
#define USBSTOR_DO_TYPE_PDO '!ODP'
#define USB_RECIPIENT_DEVICE 0
#define USB_RECIPIENT_INTERFACE 1
#define USB_RECIPIENT_ENDPOINT 2
#define USB_RECIPIENT_OTHER 3
// Bulk-Only class-specific bRequest codes
//
#define BULK_ONLY_MASS_STORAGE_RESET 0xFF
#define BULK_ONLY_GET_MAX_LUN 0xFE
// Maximum value that can be returned by BULK_ONLY_GET_MAX_LUN request
//
#define BULK_ONLY_MAXIMUM_LUN 0x0F
#define POOL_TAG 'SAMU'
#define INCREMENT_PENDING_IO_COUNT(deviceExtension) \
InterlockedIncrement(&((deviceExtension)->PendingIoCount))
#define DECREMENT_PENDING_IO_COUNT(deviceExtension) do { \
if (InterlockedDecrement(&((deviceExtension)->PendingIoCount)) == 0) { \ KeSetEvent(&((deviceExtension)->RemoveEvent), \ IO_NO_INCREMENT, \ 0); \ } \ } while (0)
#define SET_FLAG(Flags, Bit) ((Flags) |= (Bit))
#define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit))
#define TEST_FLAG(Flags, Bit) ((Flags) & (Bit))
// PDEVICE_EXTENSION->DeviceFlags state flags
//
#define DF_SRB_IN_PROGRESS 0x00000002
#define DF_PERSISTENT_ERROR 0x00000004
#define DF_RESET_IN_PROGRESS 0x00000008
#define DF_DEVICE_DISCONNECTED 0x00000010
// PDEVICE_EXTENSION->DeviceHackFlags flags
// Force a Request Sense command between the completion of one command
// and the start of the next command.
//
#define DHF_FORCE_REQUEST_SENSE 0x00000001
// Reset the device when a Medium Changed AdditionalSenseCode is returned.
//
#define DHF_MEDIUM_CHANGE_RESET 0x00000002
// Turn SCSIOP_TEST_UNIT_READY requests into SCSIOP_START_STOP_UNIT requests.
//
#define DHF_TUR_START_UNIT 0x00000004
// Indicates that a Request Sense is being performed when the Srb has
// a SenseInfoBuffer and AutoSense is not disabled.
//
#define AUTO_SENSE 0
// Indicates that a Request Sense is being performed when the Srb has
// no SenseInfoBuffer or AutoSense is disabled. In this case the Request
// Sense is being performed to clear the "persistent error" condition
// in the wacky CBI spec. (See also the DF_PERSISTENT_ERROR flag).
//
#define NON_AUTO_SENSE 1
// Command Block Wrapper Signature 'USBC'
//
#define CBW_SIGNATURE 0x43425355
#define CBW_FLAGS_DATA_IN 0x80
#define CBW_FLAGS_DATA_OUT 0x00
// Command Status Wrapper Signature 'USBS'
//
#define CSW_SIGNATURE 0x53425355
#define CSW_STATUS_GOOD 0x00
#define CSW_STATUS_FAILED 0x01
#define CSW_STATUS_PHASE_ERROR 0x02
//*****************************************************************************
// T Y P E D E F S
//*****************************************************************************
typedef enum _DEVICE_STATE { DeviceStateCreated = 1, // After IoCreateDevice
DeviceStateStarted, // After START_DEVICE
DeviceStateStopPending, // After QUERY_STOP
DeviceStateStopped, // After STOP_DEVICE
DeviceStateRemovePending, // After QUERY_REMOVE
DeviceStateSurpriseRemove, // After SURPRISE_REMOVAL
DeviceStateRemoved // After REMOVE_DEVICE
} DEVICE_STATE;
typedef enum _DEVICE_PROTOCOL { // This value indicates that the value was not set in the registry.
// This should only happen on upgrades before the value started being
// set by the .INF?
//
DeviceProtocolUnspecified = 0,
// This value indicates that the device uses the Bulk-Only specification
//
DeviceProtocolBulkOnly,
// This value indicates that the device uses the Control/Bulk/Interrupt
// specification and that command completion Interrupt transfers are
// supported after every request.
//
DeviceProtocolCBI,
// This value indicates that the device uses the Control/Bulk/Interrupt
// specification and that command completion Interrupt transfers are not
// supported at all, or not supported after every request. The Interrupt
// endpoint will never be used by the driver for this type of device.
//
DeviceProtocolCB,
// Anything >= this value is bogus
//
DeviceProtocolLast
} DEVICE_PROTOCOL;
#pragma pack (push, 1)
// Command Block Wrapper
//
typedef struct _CBW { ULONG dCBWSignature;
ULONG dCBWTag;
ULONG dCBWDataTransferLength;
UCHAR bCBWFlags;
UCHAR bCBWLUN;
UCHAR bCDBLength;
UCHAR CBWCDB[16];
} CBW, *PCBW;
// Command Status Wrapper
//
typedef struct _CSW { ULONG dCSWSignature;
ULONG dCSWTag;
ULONG dCSWDataResidue;
UCHAR bCSWStatus;
} CSW, *PCSW;
#pragma pack (pop)
// Device Extension header that is common to both FDO and PDO Device Extensions
//
typedef struct _DEVICE_EXTENSION { // Either USBSTOR_DO_TYPE_FDO or USBSTOR_DO_TYPE_PDO
//
ULONG Type;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
// Device Extension for the FDO we attach on top of the USB enumerated PDO.
//
typedef struct _FDO_DEVICE_EXTENSION { // USBSTOR_DO_TYPE_FDO
//
ULONG Type;
// Back pointer to FDO Device Object to which this Device Extension
// is attached.
//
PDEVICE_OBJECT FdoDeviceObject;
// PDO passed to USBSTOR_AddDevice
//
PDEVICE_OBJECT PhysicalDeviceObject;
// Our FDO is attached to this device object
//
PDEVICE_OBJECT StackDeviceObject;
// List of child PDOs that we enumerate
//
LIST_ENTRY ChildPDOs;
// Device Descriptor retrieved from the device
//
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
// Configuration Descriptor retrieved from the device
//
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
// Interface Descriptor contained within above Configuration Descriptor
//
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
// Serial Number String Descriptor
//
PUSB_STRING_DESCRIPTOR SerialNumber;
// ConfigurationHandle returned from URB_FUNCTION_SELECT_CONFIGURATION
//
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
// Interface info returned from URB_FUNCTION_SELECT_CONFIGURATION
//
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
// Pointers back into InterfaceInfo for Bulk IN, Bulk OUT, and
// Interrupt IN pipes.
//
PUSBD_PIPE_INFORMATION BulkInPipe;
PUSBD_PIPE_INFORMATION BulkOutPipe;
PUSBD_PIPE_INFORMATION InterruptInPipe;
// Initialized to one in AddDevice.
// Incremented by one for each pending request.
// Decremented by one for each pending request.
// Decremented by one in REMOVE_DEVICE.
//
ULONG PendingIoCount;
// Set when PendingIoCount is decremented to zero
//
KEVENT RemoveEvent;
// DriverFlags read from regisry
//
ULONG DriverFlags;
// NonRemovable read from regisry
//
ULONG NonRemovable;
// Various DF_xxxx flags
//
ULONG DeviceFlags;
// Various DHF_xxxx flags
//
ULONG DeviceHackFlags;
// SpinLock which protects DeviceFlags
//
KSPIN_LOCK ExtensionDataSpinLock;
// Current system power state
//
SYSTEM_POWER_STATE SystemPowerState;
// Current device power state
//
DEVICE_POWER_STATE DevicePowerState;
// Current power Irp, set by USBSTOR_FdoSetPower(), used by
// USBSTOR_FdoSetPowerCompletion().
//
PIRP CurrentPowerIrp;
// Set when the DevicePowerState >PowerDeviceD0 Irp is ready to be passed
// down the stack.
//
KEVENT PowerDownEvent;
ULONG SrbTimeout;
PIRP PendingIrp;
KEVENT CancelEvent;
// Work Item used to issue Reset Pipe / Reset Port requests at PASSIVE_LEVEL
//
PIO_WORKITEM IoWorkItem;
// URB used for ADSC Control Transfer and associated Bulk Transfer.
// ADSC requests are serialized through StartIo so no need to protect
// access to this single URB.
//
union { struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ControlUrb; struct _URB_BULK_OR_INTERRUPT_TRANSFER BulkIntrUrb; } Urb;
// Original Srb saved here by USBSTOR_StartIo()
//
PSCSI_REQUEST_BLOCK OriginalSrb;
// Original CDB saved here by USBSTOR_TranslateCDB()
//
UCHAR OriginalCDB[16];
union { // Fields used only for Control/Bulk/Interrupt devices
//
struct _CONTROL_BULK_INT { // Commmand completion interrupt data transferred here
//
USHORT InterruptData;
// CDB for issuing a Request Sense when there is an error
//
UCHAR RequestSenseCDB[12];
// Buffer for receiving Request Sense sense data when the Srb
// doesn't have a sense buffer.
//
SENSE_DATA SenseData;
} Cbi;
// Fields used only for Bulk Only devices
//
struct _BULK_ONLY { union { // Command Block Wrapper
//
CBW Cbw;
// Command Status Wrapper
//
CSW Csw;
// Workaround for USB 2.0 controller Data Toggle / Babble bug
//
UCHAR MaxPacketSize[512];
} CbwCsw;
// How many times a STALL is seen trying to retrieve CSW
//
ULONG StallCount;
// Srb used by USBSTOR_IssueRequestSense()
//
SCSI_REQUEST_BLOCK InternalSrb;
} BulkOnly; };
ULONG DeviceResetCount;
BOOLEAN LastSenseWasReset;
BOOLEAN DeviceIsHighSpeed;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
// Device Extension for the PDO we we enumerate as a child of the FDO
// attached on top of the USB enumerated PDO.
//
typedef struct _PDO_DEVICE_EXTENSION { // USBSTOR_DO_TYPE_PDO
//
ULONG Type;
// Back pointer to PDO Device Object to which this Device Extension
// is attached.
//
PDEVICE_OBJECT PdoDeviceObject;
// Parent FDO that enumerated us
//
PDEVICE_OBJECT ParentFDO;
// List of child PDOs enumerated from parent FDO
//
LIST_ENTRY ListEntry;
// PnP Device State
//
DEVICE_STATE DeviceState;
// Current system power state
//
SYSTEM_POWER_STATE SystemPowerState;
// Current device power state
//
DEVICE_POWER_STATE DevicePowerState;
// Current power Irp, set by USBSTOR_PdoSetPower(), used by
// USBSTOR_PdoSetPowerCompletion().
//
PIRP CurrentPowerIrp;
BOOLEAN Claimed;
BOOLEAN IsFloppy;
// LUN value which is used in bCBWLUN
//
UCHAR LUN;
// Data returned by an Inquiry command. We are only interested in the
// first 36 bytes, not the whole 96 bytes.
//
UCHAR InquiryDataBuffer[INQUIRYDATABUFFERSIZE];
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
//*****************************************************************************
//
// F U N C T I O N P R O T O T Y P E S
//
//*****************************************************************************
//
// USBMASS.C
//
NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
VOID USBSTOR_Unload ( IN PDRIVER_OBJECT DriverObject );
NTSTATUS USBSTOR_AddDevice ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject );
VOID USBSTOR_QueryFdoParams ( IN PDEVICE_OBJECT DeviceObject );
VOID USBSTOR_QueryGlobalFdoParams ( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS USBSTOR_Power ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoSetPower ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID USBSTOR_FdoSetPowerCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus );
NTSTATUS USBSTOR_FdoSetPowerD0Completion ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID NotUsed );
NTSTATUS USBSTOR_PdoSetPower ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID USBSTOR_PdoSetPowerCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus );
NTSTATUS USBSTOR_SystemControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_Pnp ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoStartDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_GetDescriptors ( IN PDEVICE_OBJECT DeviceObject );
USBSTOR_GetStringDescriptors ( IN PDEVICE_OBJECT DeviceObject );
VOID USBSTOR_AdjustConfigurationDescriptor ( IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, OUT PUSB_INTERFACE_DESCRIPTOR *InterfaceDesc, OUT PLONG BulkInIndex, OUT PLONG BulkOutIndex, OUT PLONG InterruptInIndex );
NTSTATUS USBSTOR_GetPipes ( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS USBSTOR_CreateChildPDO ( IN PDEVICE_OBJECT FdoDeviceObject, IN UCHAR Lun );
NTSTATUS USBSTOR_FdoStopDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoQueryStopRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoCancelStopRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoQueryDeviceRelations ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_FdoQueryCapabilities ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_PdoStartDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_PdoRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_PdoQueryID ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
PCHAR USBSTOR_PdoDeviceTypeString ( IN PDEVICE_OBJECT DeviceObject );
PCHAR USBSTOR_PdoGenericTypeString ( IN PDEVICE_OBJECT DeviceObject );
VOID CopyField ( IN PUCHAR Destination, IN PUCHAR Source, IN ULONG Count, IN UCHAR Change );
NTSTATUS USBSTOR_StringArrayToMultiSz( PUNICODE_STRING MultiString, PCSTR StringArray[] );
NTSTATUS USBSTOR_PdoQueryDeviceId ( IN PDEVICE_OBJECT DeviceObject, OUT PUNICODE_STRING UnicodeString );
NTSTATUS USBSTOR_PdoQueryHardwareIds ( IN PDEVICE_OBJECT DeviceObject, OUT PUNICODE_STRING UnicodeString );
NTSTATUS USBSTOR_PdoQueryCompatibleIds ( IN PDEVICE_OBJECT DeviceObject, OUT PUNICODE_STRING UnicodeString );
NTSTATUS USBSTOR_PdoQueryDeviceText ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_PdoBusQueryInstanceId ( IN PDEVICE_OBJECT DeviceObject, OUT PUNICODE_STRING UnicodeString );
NTSTATUS USBSTOR_PdoQueryDeviceRelations ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_PdoQueryCapabilities ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_SyncPassDownIrp ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_SyncCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS USBSTOR_SyncSendUsbRequest ( IN PDEVICE_OBJECT DeviceObject, IN PURB Urb );
NTSTATUS USBSTOR_GetDescriptor ( IN PDEVICE_OBJECT DeviceObject, IN UCHAR Recipient, IN UCHAR DescriptorType, IN UCHAR Index, IN USHORT LanguageId, IN ULONG RetryCount, IN ULONG DescriptorLength, OUT PUCHAR *Descriptor );
NTSTATUS USBSTOR_GetMaxLun ( IN PDEVICE_OBJECT DeviceObject, OUT PUCHAR MaxLun );
NTSTATUS USBSTOR_SelectConfiguration ( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS USBSTOR_UnConfigure ( IN PDEVICE_OBJECT DeviceObject );
NTSTATUS USBSTOR_ResetPipe ( IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE Pipe );
NTSTATUS USBSTOR_AbortPipe ( IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE Pipe );
//
// OCRW.C
//
NTSTATUS USBSTOR_Create ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_Close ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_ReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
//
// SCSI.C
//
NTSTATUS USBSTOR_DeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS USBSTOR_Scsi ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID USBSTOR_StartIo ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID USBSTOR_TimerTick ( IN PDEVICE_OBJECT DeviceObject, IN PVOID NotUsed );
NTSTATUS USBSTOR_GetInquiryData ( IN PDEVICE_OBJECT DeviceObject );
BOOLEAN USBSTOR_IsFloppyDevice ( PDEVICE_OBJECT DeviceObject );
|