Author: janderwald Date: Tue May 3 19:40:03 2011 New Revision: 51567
URL: http://svn.reactos.org/svn/reactos?rev=51567&view=rev Log: [USBSTOR] - Implement retrieving string device type from SCSI device type - Handle BusQueryDeviceId - Implement support routines for sending CBW / CSW / Data - Implement retrieving device type (SCSI inquiry request) - WIP
Added: branches/usb-bringup/drivers/usb/usbstor/scsi.c (with props) Modified: branches/usb-bringup/drivers/usb/usbstor/CMakeLists.txt branches/usb-bringup/drivers/usb/usbstor/pdo.c branches/usb-bringup/drivers/usb/usbstor/usbstor.c branches/usb-bringup/drivers/usb/usbstor/usbstor.h
Modified: branches/usb-bringup/drivers/usb/usbstor/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbstor/... ============================================================================== --- branches/usb-bringup/drivers/usb/usbstor/CMakeLists.txt [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbstor/CMakeLists.txt [iso-8859-1] Tue May 3 19:40:03 2011 @@ -3,7 +3,7 @@
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
-add_library(usbstor SHARED descriptor.c fdo.c misc.c pdo.c usbstor.c usbstor.rc) +add_library(usbstor SHARED descriptor.c fdo.c misc.c pdo.c scsi.c usbstor.c usbstor.rc)
set_module_type(usbstor kernelmodedriver) add_importlibs(usbstor ntoskrnl hal usbd)
Modified: branches/usb-bringup/drivers/usb/usbstor/pdo.c URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbstor/... ============================================================================== --- branches/usb-bringup/drivers/usb/usbstor/pdo.c [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbstor/pdo.c [iso-8859-1] Tue May 3 19:40:03 2011 @@ -11,6 +11,221 @@
#include "usbstor.h"
+LPCSTR +USBSTOR_GetDeviceType( + IN PUFI_INQUIRY_RESPONSE InquiryData) +{ + // + // check if device type is zero + // + if (InquiryData->DeviceType == 0) + { + // + // direct access device + // + + // + // FIXME: check if floppy + // + return "Disk"; + } + + // + // FIXME: use constant - derrived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type + // + switch (InquiryData->DeviceType) + { + case 1: + { + // + // sequential device, i.e magnetic tape + // + return "Sequential"; + } + case 4: + { + // + // write once device + // + return "Worm"; + } + case 5: + { + // + // CDROM device + // + return "CdRom"; + } + case 7: + { + // + // optical memory device + // + return "Optical"; + } + case 8: + { + // + // medium change device + // + return "Changer"; + } + default: + { + // + // other device + // + return "CdRom"; + } + } +} + +ULONG +CopyField( + IN PUCHAR Name, + IN PUCHAR Buffer, + IN ULONG MaxLength) +{ + ULONG Index; + + for(Index = 0; Index < MaxLength; Index++) + { + if (Name[Index] == '\0') + return Index; + + Buffer[Index] = Name[Index]; + } + + return MaxLength; +} + + +NTSTATUS +USBSTOR_PdoHandleQueryDeviceId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PPDO_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + UCHAR Buffer[100]; + LPCSTR DeviceType; + ULONG Offset = 0, Index; + PUFI_INQUIRY_RESPONSE InquiryData; + ANSI_STRING AnsiString; + UNICODE_STRING DeviceId; + + // + // get device extension + // + DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // sanity check + // + ASSERT(DeviceExtension->InquiryData); + + // + // get inquiry data + // + InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData; + + // + // get device type + // + DeviceType = USBSTOR_GetDeviceType(InquiryData); + + // + // lets create device string + // + Offset = sprintf(&Buffer[Offset], "USBSTOR\%s&Ven_", DeviceType); + + // + // copy vendor id + // + Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8); + + // + // copy product string + // + Offset += sprintf(&Buffer[Offset], "&Prod_"); + + // + // copy product identifier + // + Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16); + + // + // copy revision string + // + Offset += sprintf(&Buffer[Offset], "&Rev_"); + + // + // copy revision identifer + // + Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4); + + // + // FIXME: device serial number + // + Offset +=sprintf(&Buffer[Offset], "\00000000&%d", DeviceExtension->LUN); + + // + // now convert restricted characters to underscores + // + for(Index = 0; Index < Offset; Index++) + { + if (Buffer[Index] <= ' ' || Buffer[Index] >= 0x7F /* last printable ascii character */ || Buffer[Index] == ',') + { + // + // convert to underscore + // + Buffer[Index] = '_'; + } + } + + // + // now initialize ansi string + // + RtlInitAnsiString(&AnsiString, (PCSZ)Buffer); + + // + // allocate DeviceId string + // + DeviceId.Length = 0; + DeviceId.MaximumLength = (Offset + 2) * sizeof(WCHAR); + DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength); + if (!DeviceId.Buffer) + { + // + // no memory + // + Irp->IoStatus.Information = 0; + return STATUS_INSUFFICIENT_RESOURCES; + } + + + // + // convert to unicode + // + Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE); + + if (NT_SUCCESS(Status)) + { + // + // store result + // + Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer; + } + + DPRINT1("DeviceId %wZ\n", &DeviceId); + + // + // done + // + return Status; +} + + NTSTATUS USBSTOR_PdoHandleDeviceRelations( IN PDEVICE_OBJECT DeviceObject, @@ -102,9 +317,20 @@ Status = STATUS_NOT_SUPPORTED; break; case IRP_MN_QUERY_ID: - DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID unimplemented\n"); + { + if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) + { + // + // handle query device id + // + Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp); + break; + } + + DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType); Status = STATUS_NOT_SUPPORTED; break; + } case IRP_MN_REMOVE_DEVICE: DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n"); Status = STATUS_SUCCESS; @@ -209,6 +435,8 @@ // *ChildDeviceObject = PDO;
+ USBSTOR_SendInquiryCmd(PDO); + // // done //
Added: branches/usb-bringup/drivers/usb/usbstor/scsi.c URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbstor/... ============================================================================== --- branches/usb-bringup/drivers/usb/usbstor/scsi.c (added) +++ branches/usb-bringup/drivers/usb/usbstor/scsi.c [iso-8859-1] Tue May 3 19:40:03 2011 @@ -1,0 +1,406 @@ +/* + * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbstor/pdo.c + * PURPOSE: USB block storage device driver. + * PROGRAMMERS: + * James Tabor + * Michael Martin (michael.martin@reactos.org) + * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + +#include "usbstor.h" + +NTSTATUS +USBSTOR_BuildCBW( + IN ULONG Tag, + IN ULONG DataTransferLength, + IN UCHAR LUN, + IN UCHAR CommandBlockLength, + IN PUCHAR CommandBlock, + IN OUT PCBW Control) +{ + // + // sanity check + // + ASSERT(CommandBlockLength <= 16); + + // + // now initialize CBW + // + Control->Signature = CBW_SIGNATURE; + Control->Tag = Tag; + Control->DataTransferLength = DataTransferLength; + Control->Flags = 0x80; + Control->LUN = (LUN & MAX_LUN); + Control->CommandBlockLength = CommandBlockLength; + + // + // copy command block + // + RtlCopyMemory(Control->CommandBlock, CommandBlock, CommandBlockLength); + + // + // done + // + return STATUS_SUCCESS; +} + +NTSTATUS +USBSTOR_SendCBW( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR CommandBlockLength, + IN PUCHAR CommandBlock, + IN ULONG DataTransferLength, + OUT PCBW *OutControl) +{ + PCBW Control; + NTSTATUS Status; + PURB Urb; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PFDO_DEVICE_EXTENSION FDODeviceExtension; + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // get FDO device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; + + // + // first allocate CBW + // + Control = (PCBW)AllocateItem(NonPagedPool, 512); + if (!Control) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // first allocate CBW + // + Status = USBSTOR_BuildCBW(0xDEADDEAD, DataTransferLength, PDODeviceExtension->LUN, CommandBlockLength, CommandBlock, Control); + if (!NT_SUCCESS(Status)) + { + // + // failed to build CBW + // + return Status; + } + + // + // now build the urb + // + Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB)); + if (!Urb) + { + // + // failed to allocate urb + // + FreeItem(Control); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // now initialize the urb + // + Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB); + Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; + Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle; + Urb->UrbBulkOrInterruptTransfer.TransferBuffer = (PVOID)Control; + Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = sizeof(CBW); + Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK; + + // + // now send urb + // + Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb); + + // + // free urb + // + FreeItem(Urb); + + // + // store cbw + // + *OutControl = Control; + + // + // return operation status + // + return Status; +} + +NTSTATUS +USBSTOR_SendData( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DataTransferLength, + IN PVOID DataTransfer) +{ + PMDL TransferBufferMDL; + PURB Urb; + NTSTATUS Status; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PFDO_DEVICE_EXTENSION FDODeviceExtension; + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // get FDO device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; + + // + // allocate mdl for buffer, buffer must be allocated from NonPagedPool + // + TransferBufferMDL = IoAllocateMdl(DataTransfer, DataTransferLength, FALSE, FALSE, NULL); + if (!TransferBufferMDL) + { + // + // failed to allocate MDL + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // build mdl for nonpaged pool + // + MmBuildMdlForNonPagedPool(TransferBufferMDL); + + // + // now build the urb + // + Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB)); + if (!Urb) + { + // + // failed to allocate urb + // + IoFreeMdl(TransferBufferMDL); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // now initialize the urb + // + Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB); + Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; + Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle; + Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = TransferBufferMDL; + Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DataTransferLength; + Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; + + // + // now send urb + // + Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb); + + // + // free urb + // + FreeItem(Urb); + + // + // free mdl + // + IoFreeMdl(TransferBufferMDL); + + // + // done + // + return Status; +} + +NTSTATUS +USBSTOR_SendCSW( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Data, + IN ULONG DataLength, + OUT PCSW OutCSW) +{ + NTSTATUS Status; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PFDO_DEVICE_EXTENSION FDODeviceExtension; + PURB Urb; + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // get FDO device extension + // + FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; + + // + // now build the urb + // + Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB)); + if (!Urb) + { + // + // failed to allocate urb + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // now initialize the urb + // + Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB); + Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; + Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle; + Urb->UrbBulkOrInterruptTransfer.TransferBuffer = Data; + Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DataLength; + Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; + + // + // now send urb + // + Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb); + + if (NT_SUCCESS(Status)) + { + // + // copy csw status + // + RtlCopyMemory(OutCSW, Data, sizeof(CSW)); + } + + // + // free urb + // + FreeItem(Urb); + + // + // done + // + return Status; +} + +NTSTATUS +USBSTOR_SendInquiryCmd( + IN PDEVICE_OBJECT DeviceObject) +{ + UFI_INQUIRY_CMD Cmd; + CSW CSW; + NTSTATUS Status; + PUFI_INQUIRY_RESPONSE Response; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PCBW OutControl; + + + // + // get PDO device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // allocate inquiry response + // + Response = (PUFI_INQUIRY_RESPONSE)AllocateItem(NonPagedPool, sizeof(UFI_INQUIRY_RESPONSE)); + if (!Response) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // initialize inquiry cmd + // + RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); + Cmd.Code = UFI_INQURIY_CODE; + Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); + Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE); + + // + // now send inquiry cmd + // + Status = USBSTOR_SendCBW(DeviceObject, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), &OutControl); + if (!NT_SUCCESS(Status)) + { + // + // failed to send CBW + // + DPRINT1("USBSTOR_SendInquiryCmd> USBSTOR_SendCBW failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + // + // now send inquiry response + // + Status = USBSTOR_SendData(DeviceObject, sizeof(UFI_INQUIRY_RESPONSE), Response); + if (!NT_SUCCESS(Status)) + { + // + // failed to send CBW + // + DPRINT1("USBSTOR_SendInquiryCmd> USBSTOR_SendData failed with %x\n", Status); + FreeItem(Response); + ASSERT(FALSE); + return Status; + } + + DPRINT1("Response %p\n", Response); + DPRINT1("DeviceType %x\n", Response->DeviceType); + DPRINT1("RMB %x\n", Response->RMB); + DPRINT1("Version %x\n", Response->Version); + DPRINT1("Format %x\n", Response->Format); + DPRINT1("Length %x\n", Response->Length); + DPRINT1("Reserved %x\n", Response->Reserved); + DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0], Response->Vendor[1], Response->Vendor[2], Response->Vendor[3], Response->Vendor[4], Response->Vendor[5], Response->Vendor[6], Response->Vendor[7]); + DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response->Product[0], Response->Product[1], Response->Product[2], Response->Product[3], + Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7], + Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11], + Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]); + + DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]); + + // + // send csw + // + Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW); + + DPRINT1("------------------------\n"); + DPRINT1("CSW %p\n", &CSW); + DPRINT1("Signature %x\n", CSW.Signature); + DPRINT1("Tag %x\n", CSW.Tag); + DPRINT1("DataResidue %x\n", CSW.DataResidue); + DPRINT1("Status %x\n", CSW.Status); + + // + // free item + // + FreeItem(OutControl); + + // + // store inquiry data + // + PDODeviceExtension->InquiryData = (PVOID)Response; + + // + // FIXME: handle error + // + ASSERT(CSW.Status == 0); + + + // + // done + // + return Status; +}
Propchange: branches/usb-bringup/drivers/usb/usbstor/scsi.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/usb-bringup/drivers/usb/usbstor/usbstor.c URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbstor/... ============================================================================== --- branches/usb-bringup/drivers/usb/usbstor/usbstor.c [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbstor/usbstor.c [iso-8859-1] Tue May 3 19:40:03 2011 @@ -239,9 +239,9 @@ DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
// - // driver start i/o routine - // - DriverObject->DriverStartIo = USBSTOR_StartIo; + // FIXME: driver start i/o routine + // + //DriverObject->DriverStartIo = USBSTOR_StartIo;
//
Modified: branches/usb-bringup/drivers/usb/usbstor/usbstor.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbstor/... ============================================================================== --- branches/usb-bringup/drivers/usb/usbstor/usbstor.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbstor/usbstor.h [iso-8859-1] Tue May 3 19:40:03 2011 @@ -52,7 +52,8 @@ { COMMON_DEVICE_EXTENSION Common; PDEVICE_OBJECT LowerDeviceObject; // points to FDO - + UCHAR LUN; // lun id + PVOID InquiryData; // USB SCSI inquiry data }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
@@ -60,6 +61,66 @@ // max lun command identifier // #define USB_BULK_GET_MAX_LUN 0xFE + + +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; + +#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_INQURIY_CODE 0x12 +#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 + USHORT Reserved; // 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);
//--------------------------------------------------------------------- // @@ -119,6 +180,13 @@ IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension);
+NTSTATUS +NTAPI +USBSTOR_SyncForwardIrpCompletionRoutine( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); +
//--------------------------------------------------------------------- // @@ -138,3 +206,10 @@ USBSTOR_GetPipeHandles( IN PFDO_DEVICE_EXTENSION DeviceExtension);
+//--------------------------------------------------------------------- +// +// scsi.c routines +// +NTSTATUS +USBSTOR_SendInquiryCmd( + IN PDEVICE_OBJECT DeviceObject);