2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/pdo.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
17 IN ULONG DataTransferLength
,
19 IN UCHAR CommandBlockLength
,
20 IN PUCHAR CommandBlock
,
26 ASSERT(CommandBlockLength
<= 16);
31 Control
->Signature
= CBW_SIGNATURE
;
33 Control
->DataTransferLength
= DataTransferLength
;
34 Control
->Flags
= 0x80;
35 Control
->LUN
= (LUN
& MAX_LUN
);
36 Control
->CommandBlockLength
= CommandBlockLength
;
41 RtlCopyMemory(Control
->CommandBlock
, CommandBlock
, CommandBlockLength
);
46 return STATUS_SUCCESS
;
50 USBSTOR_AllocateIrpContext()
55 // allocate irp context
57 Context
= (PIRP_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(IRP_CONTEXT
));
69 Context
->cbw
= (PCBW
)AllocateItem(NonPagedPool
, 512);
89 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
93 USBSTOR_CSWCompletionRoutine(
94 PDEVICE_OBJECT DeviceObject
,
99 PIO_STACK_LOCATION IoStack
;
100 PSCSI_REQUEST_BLOCK Request
;
102 PREAD_CAPACITY_DATA_EX CapacityDataEx
;
103 PREAD_CAPACITY_DATA CapacityData
;
104 PUFI_CAPACITY_RESPONSE Response
;
106 DPRINT1("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
111 Context
= (PIRP_CONTEXT
)Ctx
;
116 if (Context
->TransferBufferMDL
)
119 // is there an irp associated
124 // did we allocate the mdl
126 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
131 IoFreeMdl(Context
->TransferBufferMDL
);
139 IoFreeMdl(Context
->TransferBufferMDL
);
146 // get current stack location
148 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
153 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
157 // FIXME: check status
159 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
162 // get SCSI command data block
164 pCDB
= (PCDB
)Request
->Cdb
;
167 // read capacity needs special work
169 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
174 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
179 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
180 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
182 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
187 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
192 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
193 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
194 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
201 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
206 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
207 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
208 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
214 FreeItem(Context
->TransferData
);
221 FreeItem(Context
->cbw
);
227 // FIXME: check status
229 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
230 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
235 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
243 KeSetEvent(Context
->Event
, 0, FALSE
);
255 return STATUS_MORE_PROCESSING_REQUIRED
;
261 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
265 USBSTOR_DataCompletionRoutine(
266 PDEVICE_OBJECT DeviceObject
,
270 PIRP_CONTEXT Context
;
271 PIO_STACK_LOCATION IoStack
;
273 DPRINT1("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
278 Context
= (PIRP_CONTEXT
)Ctx
;
281 // get next stack location
284 IoStack
= IoGetNextIrpStackLocation(Irp
);
287 // now initialize the urb for sending the csw
289 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
290 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
291 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
295 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
299 // initialize stack location
301 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
302 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
303 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
304 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
305 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
309 // setup completion routine
311 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
316 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
318 return STATUS_MORE_PROCESSING_REQUIRED
;
324 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
328 USBSTOR_CBWCompletionRoutine(
329 PDEVICE_OBJECT DeviceObject
,
333 PIRP_CONTEXT Context
;
334 PIO_STACK_LOCATION IoStack
;
336 USBD_PIPE_HANDLE PipeHandle
;
338 DPRINT1("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
343 Context
= (PIRP_CONTEXT
)Ctx
;
346 // get next stack location
348 IoStack
= IoGetNextIrpStackLocation(Irp
);
351 // is there data to be submitted
353 if (Context
->TransferDataLength
)
358 Code
= Context
->cbw
->CommandBlock
[0];
360 if (Code
== SCSIOP_WRITE
)
363 // write request use bulk out pipe
365 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
370 // default bulk in pipe
372 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
376 // now initialize the urb for sending data
378 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
379 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
382 Context
->TransferBufferMDL
,
383 Context
->TransferDataLength
,
384 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
388 // setup completion routine
390 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
395 // now initialize the urb for sending the csw
398 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
399 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
400 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
404 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
408 // setup completion routine
410 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
414 // initialize stack location
416 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
417 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
418 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
419 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
420 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
425 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
427 return STATUS_MORE_PROCESSING_REQUIRED
;
432 IN PDEVICE_OBJECT DeviceObject
,
433 IN PIRP OriginalRequest
,
434 IN OPTIONAL PKEVENT Event
,
435 IN ULONG CommandLength
,
437 IN ULONG TransferDataLength
,
438 IN PUCHAR TransferData
)
440 PIRP_CONTEXT Context
;
441 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
442 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
444 PIO_STACK_LOCATION IoStack
;
445 PULONG MdlVirtualAddress
;
448 // first allocate irp context
450 Context
= USBSTOR_AllocateIrpContext();
456 return STATUS_INSUFFICIENT_RESOURCES
;
460 // get PDO device extension
462 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
465 // get FDO device extension
467 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
472 USBSTOR_BuildCBW(0xDEADDEAD, // FIXME tag
474 PDODeviceExtension
->LUN
,
480 // now initialize the urb
482 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
483 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
484 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
488 USBD_TRANSFER_DIRECTION_OUT
| USBD_SHORT_TRANSFER_OK
,
492 // initialize rest of context
494 Context
->Irp
= OriginalRequest
;
495 Context
->TransferData
= TransferData
;
496 Context
->TransferDataLength
= TransferDataLength
;
497 Context
->FDODeviceExtension
= FDODeviceExtension
;
498 Context
->PDODeviceExtension
= PDODeviceExtension
;
499 Context
->Event
= Event
;
502 // is there transfer data
504 if (Context
->TransferDataLength
)
507 // check if the original request already does not have an mdl associated
511 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
512 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
515 // Sanity check that the Mdl does describe the TransferData for read/write
517 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
519 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
520 ASSERT(MdlVirtualAddress
== Context
->TransferData
);
524 // I/O paging request
526 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
531 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
533 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
534 if (!Context
->TransferBufferMDL
)
537 // failed to allocate MDL
539 return STATUS_INSUFFICIENT_RESOURCES
;
543 // build mdl for nonpaged pool
545 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
551 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
553 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
554 if (!Context
->TransferBufferMDL
)
557 // failed to allocate MDL
559 return STATUS_INSUFFICIENT_RESOURCES
;
563 // build mdl for nonpaged pool
565 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
570 // now allocate the request
572 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
575 FreeItem(Context
->cbw
);
577 return STATUS_INSUFFICIENT_RESOURCES
;
581 // get next stack location
583 IoStack
= IoGetNextIrpStackLocation(Irp
);
586 // initialize stack location
588 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
589 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
590 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
591 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
592 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
595 // setup completion routine
597 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
602 // mark orignal irp as pending
604 IoMarkIrpPending(OriginalRequest
);
610 IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
615 return STATUS_PENDING
;
619 USBSTOR_SendInquiryCmd(
620 IN PDEVICE_OBJECT DeviceObject
)
625 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
626 PUFI_INQUIRY_RESPONSE Response
;
630 // allocate inquiry response
632 Response
= AllocateItem(NonPagedPool
, PAGE_SIZE
);
638 return STATUS_INSUFFICIENT_RESOURCES
;
642 // get PDO device extension
644 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
647 // initialize inquiry cmd
649 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
650 Cmd
.Code
= SCSIOP_INQUIRY
;
651 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
652 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
657 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
660 // now send the request
662 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
665 // wait for the action to complete
667 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
669 DPRINT1("Response %p\n", Response
);
670 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
671 DPRINT1("RMB %x\n", Response
->RMB
);
672 DPRINT1("Version %x\n", Response
->Version
);
673 DPRINT1("Format %x\n", Response
->Format
);
674 DPRINT1("Length %x\n", Response
->Length
);
675 DPRINT1("Reserved %x\n", Response
->Reserved
);
676 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]);
677 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],
678 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
679 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
680 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
682 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
685 // store inquiry data
687 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
696 USBSTOR_SendCapacityCmd(
697 IN PDEVICE_OBJECT DeviceObject
,
700 UFI_CAPACITY_CMD Cmd
;
701 PUFI_CAPACITY_RESPONSE Response
;
702 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
705 // get PDO device extension
707 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
710 // allocate capacity response
712 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, sizeof(UFI_CAPACITY_RESPONSE
));
718 return STATUS_INSUFFICIENT_RESOURCES
;
722 // initialize capacity cmd
724 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
725 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
726 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
729 // send request, response will be freed in completion routine
731 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
);
735 USBSTOR_SendModeSenseCmd(
736 IN PDEVICE_OBJECT DeviceObject
,
742 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
745 PUFI_MODE_PARAMETER_HEADER Header
;
747 PIO_STACK_LOCATION IoStack
;
748 PSCSI_REQUEST_BLOCK Request
;
751 // get current stack location
753 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
758 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
760 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
761 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
762 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
763 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
764 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
766 return STATUS_SUCCESS
;
770 // get SCSI command data block
772 pCDB
= (PCDB
)Request
->Cdb
;
775 // get PDO device extension
777 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
780 // allocate sense response from non paged pool
782 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
788 return STATUS_INSUFFICIENT_RESOURCES
;
797 // MODE_PAGE_ERROR_RECOVERY
798 // MODE_PAGE_FLEXIBILE
799 // MODE_PAGE_LUN_MAPPING
800 // MODE_PAGE_FAULT_REPORTING
801 // MODE_SENSE_RETURN_ALL
804 // initialize mode sense cmd
806 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
807 Cmd
.Code
= SCSIOP_MODE_SENSE
;
808 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
809 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
810 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
811 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
813 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
814 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
817 // now send mode sense cmd
819 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
820 if (!NT_SUCCESS(Status
))
823 // failed to send CBW
825 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
832 // now send data block response
834 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
835 if (!NT_SUCCESS(Status
))
838 // failed to send CBW
840 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
846 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
849 // TODO: build layout
851 // first struct is the header
852 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
855 // MODE_PARAMETER_BLOCK
863 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
865 DPRINT1("------------------------\n");
866 DPRINT1("CSW %p\n", &CSW
);
867 DPRINT1("Signature %x\n", CSW
.Signature
);
868 DPRINT1("Tag %x\n", CSW
.Tag
);
869 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
870 DPRINT1("Status %x\n", CSW
.Status
);
873 // FIXME: handle error
875 ASSERT(CSW
.Status
== 0);
876 ASSERT(CSW
.DataResidue
== 0);
879 // calculate transfer length
881 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
886 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
891 FreeItem(OutControl
);
906 USBSTOR_SendReadWriteCmd(
907 IN PDEVICE_OBJECT DeviceObject
,
910 UFI_READ_WRITE_CMD Cmd
;
912 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
915 PIO_STACK_LOCATION IoStack
;
916 PSCSI_REQUEST_BLOCK Request
;
920 // get current stack location
922 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
927 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
930 // get SCSI command data block
932 pCDB
= (PCDB
)Request
->Cdb
;
935 // get PDO device extension
937 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
940 // informal debug print
942 DPRINT1("USBSTOR_SendReadWriteCmd DataTransferLength %x, BlockLength %x\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
947 ASSERT(PDODeviceExtension
->BlockLength
);
952 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
955 // initialize read cmd
957 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
958 Cmd
.Code
= pCDB
->AsByte
[0];
959 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
960 Cmd
.ContiguousLogicBlocks
= _byteswap_ushort(BlockCount
);
961 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
962 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
963 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
964 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
966 DPRINT1("BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
971 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
);
975 USBSTOR_SendTestUnitCmd(
976 IN PDEVICE_OBJECT DeviceObject
,
979 UFI_TEST_UNIT_CMD Cmd
;
980 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
981 PIO_STACK_LOCATION IoStack
;
982 PSCSI_REQUEST_BLOCK Request
;
985 // get current stack location
987 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
992 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
995 // no transfer length
997 ASSERT(Request
->DataTransferLength
== 0);
1000 // get PDO device extension
1002 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1005 // initialize test unit cmd
1007 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1008 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1009 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1014 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
);
1019 USBSTOR_HandleExecuteSCSI(
1020 IN PDEVICE_OBJECT DeviceObject
,
1025 PIO_STACK_LOCATION IoStack
;
1026 PSCSI_REQUEST_BLOCK Request
;
1029 // get current stack location
1031 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1034 // get request block
1036 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1039 // get SCSI command data block
1041 pCDB
= (PCDB
)Request
->Cdb
;
1043 DPRINT1("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1045 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1050 ASSERT(Request
->DataBuffer
);
1052 DPRINT1("SCSIOP_READ_CAPACITY Length %\n", Request
->DataTransferLength
);
1053 Status
= USBSTOR_SendCapacityCmd(DeviceObject
, Irp
);
1055 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1057 DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1058 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1059 ASSERT(Request
->DataBuffer
);
1062 // send mode sense command
1064 Status
= USBSTOR_SendModeSenseCmd(DeviceObject
, Irp
);
1066 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1068 DPRINT1("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1071 // send read / write command
1073 Status
= USBSTOR_SendReadWriteCmd(DeviceObject
, Irp
);
1075 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1077 DPRINT1("SCSIOP_MEDIUM_REMOVAL\n");
1080 // just complete the request
1082 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1083 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1084 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1085 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1086 return STATUS_SUCCESS
;
1088 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1090 DPRINT1("SCSIOP_TEST_UNIT_READY\n");
1093 // send test unit command
1095 Status
= USBSTOR_SendTestUnitCmd(DeviceObject
, Irp
);
1100 Request
->SrbStatus
= SRB_STATUS_ERROR
;
1101 Status
= STATUS_NOT_SUPPORTED
;