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
;
105 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData
;
109 DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
114 Context
= (PIRP_CONTEXT
)Ctx
;
119 if (Context
->TransferBufferMDL
)
122 // is there an irp associated
127 // did we allocate the mdl
129 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
134 IoFreeMdl(Context
->TransferBufferMDL
);
142 IoFreeMdl(Context
->TransferBufferMDL
);
149 // get current stack location
151 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
156 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
159 Status
= Irp
->IoStatus
.Status
;
164 // get SCSI command data block
166 pCDB
= (PCDB
)Request
->Cdb
;
171 if (!NT_SUCCESS(Status
))
173 DPRINT1("Status %x\n", Status
);
174 DPRINT1("UrbStatus %x\n", Urb
->UrbHeader
.Status
);
177 // Check for errors that can be handled
178 // FIXME: Verify all usb errors that can be recovered via pipe reset/port reset/controller reset
180 if ((Urb
->UrbHeader
.Status
& USB_RECOVERABLE_ERRORS
) == Urb
->UrbHeader
.Status
)
182 DPRINT1("Attempting Error Recovery\n");
184 // If a Read Capacity Request free TransferBuffer
186 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
188 FreeItem(Context
->TransferData
);
194 FreeItem(Context
->cbw
);
198 // Allocate Work Item Data
200 ErrorHandlerWorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ERRORHANDLER_WORKITEM_DATA
), USB_STOR_TAG
);
201 if (!ErrorHandlerWorkItemData
)
203 DPRINT1("Failed to allocate memory\n");
204 Status
= STATUS_INSUFFICIENT_RESOURCES
;
209 // Initialize and queue the work item to handle the error
211 ExInitializeWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
,
212 ErrorHandlerWorkItemRoutine
,
213 ErrorHandlerWorkItemData
);
215 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
216 ErrorHandlerWorkItemData
->Irp
= Irp
;
217 ErrorHandlerWorkItemData
->Context
= Context
;
218 DPRINT1("Queuing WorkItemROutine\n");
219 ExQueueWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
, DelayedWorkQueue
);
221 return STATUS_MORE_PROCESSING_REQUIRED
;
226 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
229 // read capacity needs special work
231 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
236 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
241 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
242 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
244 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
249 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
254 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
255 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
256 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
263 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
268 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
269 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
270 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
276 FreeItem(Context
->TransferData
);
283 FreeItem(Context
->cbw
);
289 // FIXME: check status
291 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
292 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
297 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
300 // terminate current request
302 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, TRUE
);
305 // start next request
307 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
315 KeSetEvent(Context
->Event
, 0, FALSE
);
327 return STATUS_MORE_PROCESSING_REQUIRED
;
333 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
337 USBSTOR_DataCompletionRoutine(
338 PDEVICE_OBJECT DeviceObject
,
342 PIRP_CONTEXT Context
;
343 PIO_STACK_LOCATION IoStack
;
345 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
350 Context
= (PIRP_CONTEXT
)Ctx
;
353 // get next stack location
356 IoStack
= IoGetNextIrpStackLocation(Irp
);
359 // now initialize the urb for sending the csw
361 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
362 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
363 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
367 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
371 // initialize stack location
373 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
374 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
375 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
376 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
377 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
381 // setup completion routine
383 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
388 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
390 return STATUS_MORE_PROCESSING_REQUIRED
;
396 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
400 USBSTOR_CBWCompletionRoutine(
401 PDEVICE_OBJECT DeviceObject
,
405 PIRP_CONTEXT Context
;
406 PIO_STACK_LOCATION IoStack
;
408 USBD_PIPE_HANDLE PipeHandle
;
410 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
415 Context
= (PIRP_CONTEXT
)Ctx
;
418 // get next stack location
420 IoStack
= IoGetNextIrpStackLocation(Irp
);
423 // is there data to be submitted
425 if (Context
->TransferDataLength
)
430 Code
= Context
->cbw
->CommandBlock
[0];
432 if (Code
== SCSIOP_WRITE
)
435 // write request use bulk out pipe
437 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
442 // default bulk in pipe
444 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
448 // now initialize the urb for sending data
450 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
451 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
454 Context
->TransferBufferMDL
,
455 Context
->TransferDataLength
,
456 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
460 // setup completion routine
462 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
467 // now initialize the urb for sending the csw
470 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
471 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
472 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
476 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
480 // setup completion routine
482 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
486 // initialize stack location
488 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
489 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
490 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
491 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
492 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
497 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
499 return STATUS_MORE_PROCESSING_REQUIRED
;
504 IN PDEVICE_OBJECT DeviceObject
,
505 IN PIRP OriginalRequest
,
506 IN OPTIONAL PKEVENT Event
,
507 IN UCHAR CommandLength
,
509 IN ULONG TransferDataLength
,
510 IN PUCHAR TransferData
)
512 PIRP_CONTEXT Context
;
513 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
514 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
516 PIO_STACK_LOCATION IoStack
;
517 PUCHAR MdlVirtualAddress
;
520 // first allocate irp context
522 Context
= USBSTOR_AllocateIrpContext();
528 return STATUS_INSUFFICIENT_RESOURCES
;
532 // get PDO device extension
534 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
537 // get FDO device extension
539 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
544 USBSTOR_BuildCBW(0xDEADDEAD, // FIXME tag
546 PDODeviceExtension
->LUN
,
552 // now initialize the urb
554 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
555 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
556 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
560 USBD_TRANSFER_DIRECTION_OUT
| USBD_SHORT_TRANSFER_OK
,
564 // initialize rest of context
566 Context
->Irp
= OriginalRequest
;
567 Context
->TransferData
= TransferData
;
568 Context
->TransferDataLength
= TransferDataLength
;
569 Context
->FDODeviceExtension
= FDODeviceExtension
;
570 Context
->PDODeviceExtension
= PDODeviceExtension
;
571 Context
->Event
= Event
;
574 // is there transfer data
576 if (Context
->TransferDataLength
)
579 // check if the original request already does not have an mdl associated
583 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
584 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
587 // Sanity check that the Mdl does describe the TransferData for read/write
589 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
591 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
592 ASSERT(MdlVirtualAddress
== Context
->TransferData
);
596 // I/O paging request
598 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
603 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
605 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
606 if (!Context
->TransferBufferMDL
)
609 // failed to allocate MDL
611 return STATUS_INSUFFICIENT_RESOURCES
;
615 // build mdl for nonpaged pool
617 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
623 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
625 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
626 if (!Context
->TransferBufferMDL
)
629 // failed to allocate MDL
631 return STATUS_INSUFFICIENT_RESOURCES
;
635 // build mdl for nonpaged pool
637 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
642 // now allocate the request
644 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
647 FreeItem(Context
->cbw
);
649 return STATUS_INSUFFICIENT_RESOURCES
;
653 // get next stack location
655 IoStack
= IoGetNextIrpStackLocation(Irp
);
658 // initialize stack location
660 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
661 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
662 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
663 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
664 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
667 // setup completion routine
669 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
674 // mark orignal irp as pending
676 IoMarkIrpPending(OriginalRequest
);
682 IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
687 return STATUS_PENDING
;
691 USBSTOR_SendInquiryCmd(
692 IN PDEVICE_OBJECT DeviceObject
)
697 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
698 PUFI_INQUIRY_RESPONSE Response
;
702 // allocate inquiry response
704 Response
= AllocateItem(NonPagedPool
, PAGE_SIZE
);
710 return STATUS_INSUFFICIENT_RESOURCES
;
714 // get PDO device extension
716 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
719 // initialize inquiry cmd
721 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
722 Cmd
.Code
= SCSIOP_INQUIRY
;
723 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
724 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
729 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
732 // now send the request
734 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
737 // wait for the action to complete
739 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
741 DPRINT1("Response %p\n", Response
);
742 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
743 DPRINT1("RMB %x\n", Response
->RMB
);
744 DPRINT1("Version %x\n", Response
->Version
);
745 DPRINT1("Format %x\n", Response
->Format
);
746 DPRINT1("Length %x\n", Response
->Length
);
747 DPRINT1("Reserved %x\n", Response
->Reserved
);
748 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]);
749 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],
750 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
751 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
752 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
754 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
757 // store inquiry data
759 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
768 USBSTOR_SendCapacityCmd(
769 IN PDEVICE_OBJECT DeviceObject
,
772 UFI_CAPACITY_CMD Cmd
;
773 PUFI_CAPACITY_RESPONSE Response
;
774 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
777 // get PDO device extension
779 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
782 // allocate capacity response
784 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, sizeof(UFI_CAPACITY_RESPONSE
));
790 return STATUS_INSUFFICIENT_RESOURCES
;
794 // initialize capacity cmd
796 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
797 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
798 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
801 // send request, response will be freed in completion routine
803 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
);
807 USBSTOR_SendModeSenseCmd(
808 IN PDEVICE_OBJECT DeviceObject
,
817 PUFI_MODE_PARAMETER_HEADER Header
;
819 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
820 PIO_STACK_LOCATION IoStack
;
821 PSCSI_REQUEST_BLOCK Request
;
824 // get current stack location
826 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
831 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
833 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
834 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
835 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
836 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
837 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
840 // get PDO device extension
842 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
847 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
850 // terminate current request
852 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, TRUE
);
855 // start next request
857 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
859 return STATUS_SUCCESS
;
863 // get SCSI command data block
865 pCDB
= (PCDB
)Request
->Cdb
;
868 // get PDO device extension
870 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
873 // allocate sense response from non paged pool
875 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
881 return STATUS_INSUFFICIENT_RESOURCES
;
890 // MODE_PAGE_ERROR_RECOVERY
891 // MODE_PAGE_FLEXIBILE
892 // MODE_PAGE_LUN_MAPPING
893 // MODE_PAGE_FAULT_REPORTING
894 // MODE_SENSE_RETURN_ALL
897 // initialize mode sense cmd
899 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
900 Cmd
.Code
= SCSIOP_MODE_SENSE
;
901 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
902 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
903 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
904 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
906 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
907 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
910 // now send mode sense cmd
912 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
913 if (!NT_SUCCESS(Status
))
916 // failed to send CBW
918 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
925 // now send data block response
927 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
928 if (!NT_SUCCESS(Status
))
931 // failed to send CBW
933 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
939 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
942 // TODO: build layout
944 // first struct is the header
945 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
948 // MODE_PARAMETER_BLOCK
956 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
958 DPRINT1("------------------------\n");
959 DPRINT1("CSW %p\n", &CSW
);
960 DPRINT1("Signature %x\n", CSW
.Signature
);
961 DPRINT1("Tag %x\n", CSW
.Tag
);
962 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
963 DPRINT1("Status %x\n", CSW
.Status
);
966 // FIXME: handle error
968 ASSERT(CSW
.Status
== 0);
969 ASSERT(CSW
.DataResidue
== 0);
972 // calculate transfer length
974 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
979 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
984 FreeItem(OutControl
);
999 USBSTOR_SendReadWriteCmd(
1000 IN PDEVICE_OBJECT DeviceObject
,
1003 UFI_READ_WRITE_CMD Cmd
;
1004 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1007 PIO_STACK_LOCATION IoStack
;
1008 PSCSI_REQUEST_BLOCK Request
;
1011 // get current stack location
1013 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1016 // get request block
1018 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1021 // get SCSI command data block
1023 pCDB
= (PCDB
)Request
->Cdb
;
1026 // get PDO device extension
1028 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1031 // informal debug print
1033 DPRINT("USBSTOR_SendReadWriteCmd DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
1038 ASSERT(PDODeviceExtension
->BlockLength
);
1043 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
1046 // initialize read cmd
1048 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
1049 Cmd
.Code
= pCDB
->AsByte
[0];
1050 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1051 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
1052 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
1053 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
1054 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
1055 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
1056 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
1058 DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
1063 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
);
1067 USBSTOR_SendTestUnitCmd(
1068 IN PDEVICE_OBJECT DeviceObject
,
1071 UFI_TEST_UNIT_CMD Cmd
;
1072 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1073 PIO_STACK_LOCATION IoStack
;
1074 PSCSI_REQUEST_BLOCK Request
;
1077 // get current stack location
1079 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1082 // get request block
1084 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1087 // no transfer length
1089 ASSERT(Request
->DataTransferLength
== 0);
1092 // get PDO device extension
1094 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1097 // initialize test unit cmd
1099 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1100 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1101 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1106 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
);
1111 USBSTOR_HandleExecuteSCSI(
1112 IN PDEVICE_OBJECT DeviceObject
,
1117 PIO_STACK_LOCATION IoStack
;
1118 PSCSI_REQUEST_BLOCK Request
;
1119 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1122 // get PDO device extension
1124 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1129 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
1132 // get current stack location
1134 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1137 // get request block
1139 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1142 // get SCSI command data block
1144 pCDB
= (PCDB
)Request
->Cdb
;
1146 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1148 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1153 ASSERT(Request
->DataBuffer
);
1155 DPRINT("SCSIOP_READ_CAPACITY Length %\n", Request
->DataTransferLength
);
1156 Status
= USBSTOR_SendCapacityCmd(DeviceObject
, Irp
);
1158 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1160 DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1161 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1162 ASSERT(Request
->DataBuffer
);
1165 // send mode sense command
1167 Status
= USBSTOR_SendModeSenseCmd(DeviceObject
, Irp
);
1169 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1171 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1174 // send read / write command
1176 Status
= USBSTOR_SendReadWriteCmd(DeviceObject
, Irp
);
1178 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1180 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1183 // just complete the request
1185 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1186 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1187 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1188 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1191 // terminate current request
1193 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, TRUE
);
1196 // start next request
1198 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
1200 return STATUS_SUCCESS
;
1202 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1204 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1207 // send test unit command
1209 Status
= USBSTOR_SendTestUnitCmd(DeviceObject
, Irp
);
1214 Request
->SrbStatus
= SRB_STATUS_ERROR
;
1215 Status
= STATUS_NOT_SUPPORTED
;