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 // free the allocated irp
189 // Allocate Work Item Data
191 ErrorHandlerWorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ERRORHANDLER_WORKITEM_DATA
), USB_STOR_TAG
);
192 if (!ErrorHandlerWorkItemData
)
194 DPRINT1("Failed to allocate memory\n");
195 Status
= STATUS_INSUFFICIENT_RESOURCES
;
200 // Initialize and queue the work item to handle the error
202 ExInitializeWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
,
203 ErrorHandlerWorkItemRoutine
,
204 ErrorHandlerWorkItemData
);
206 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
207 ErrorHandlerWorkItemData
->Context
= Context
;
208 DPRINT1("Queuing WorkItemROutine\n");
209 ExQueueWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
, DelayedWorkQueue
);
211 return STATUS_MORE_PROCESSING_REQUIRED
;
216 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
219 // read capacity needs special work
221 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
226 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
231 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
232 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
234 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
239 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
244 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
245 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
246 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
253 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
258 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
259 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
260 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
266 FreeItem(Context
->TransferData
);
273 FreeItem(Context
->cbw
);
279 // FIXME: check status
281 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
282 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
285 // terminate current request
287 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
292 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
295 // start next request
297 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
305 KeSetEvent(Context
->Event
, 0, FALSE
);
309 // free our allocated irp
321 return STATUS_MORE_PROCESSING_REQUIRED
;
327 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
331 USBSTOR_DataCompletionRoutine(
332 PDEVICE_OBJECT DeviceObject
,
336 PIRP_CONTEXT Context
;
337 PIO_STACK_LOCATION IoStack
;
339 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
344 Context
= (PIRP_CONTEXT
)Ctx
;
347 // get next stack location
350 IoStack
= IoGetNextIrpStackLocation(Irp
);
353 // now initialize the urb for sending the csw
355 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
356 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
357 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
361 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
365 // initialize stack location
367 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
368 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
369 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
370 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
371 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
375 // setup completion routine
377 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
382 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
384 return STATUS_MORE_PROCESSING_REQUIRED
;
390 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
394 USBSTOR_CBWCompletionRoutine(
395 PDEVICE_OBJECT DeviceObject
,
399 PIRP_CONTEXT Context
;
400 PIO_STACK_LOCATION IoStack
;
402 USBD_PIPE_HANDLE PipeHandle
;
404 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
409 Context
= (PIRP_CONTEXT
)Ctx
;
412 // get next stack location
414 IoStack
= IoGetNextIrpStackLocation(Irp
);
417 // is there data to be submitted
419 if (Context
->TransferDataLength
)
424 Code
= Context
->cbw
->CommandBlock
[0];
426 if (Code
== SCSIOP_WRITE
)
429 // write request use bulk out pipe
431 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
436 // default bulk in pipe
438 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
442 // now initialize the urb for sending data
444 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
445 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
448 Context
->TransferBufferMDL
,
449 Context
->TransferDataLength
,
450 ((Code
== SCSIOP_WRITE
) ? USBD_TRANSFER_DIRECTION_OUT
: (USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
)),
454 // setup completion routine
456 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
461 // now initialize the urb for sending the csw
464 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
465 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
466 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
470 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
474 // setup completion routine
476 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
480 // initialize stack location
482 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
483 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
484 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
485 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
486 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
491 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
493 return STATUS_MORE_PROCESSING_REQUIRED
;
498 IN PDEVICE_OBJECT DeviceObject
,
499 IN PIRP OriginalRequest
,
500 IN OPTIONAL PKEVENT Event
,
501 IN UCHAR CommandLength
,
503 IN ULONG TransferDataLength
,
504 IN PUCHAR TransferData
)
506 PIRP_CONTEXT Context
;
507 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
508 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
510 PIO_STACK_LOCATION IoStack
;
511 PUCHAR MdlVirtualAddress
;
514 // first allocate irp context
516 Context
= USBSTOR_AllocateIrpContext();
522 return STATUS_INSUFFICIENT_RESOURCES
;
526 // get PDO device extension
528 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
531 // get FDO device extension
533 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
538 USBSTOR_BuildCBW(0xDEADDEAD, // FIXME tag
540 PDODeviceExtension
->LUN
,
546 // now initialize the urb
548 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
549 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
550 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
554 USBD_TRANSFER_DIRECTION_OUT
,
558 // initialize rest of context
560 Context
->Irp
= OriginalRequest
;
561 Context
->TransferData
= TransferData
;
562 Context
->TransferDataLength
= TransferDataLength
;
563 Context
->FDODeviceExtension
= FDODeviceExtension
;
564 Context
->PDODeviceExtension
= PDODeviceExtension
;
565 Context
->Event
= Event
;
568 // is there transfer data
570 if (Context
->TransferDataLength
)
573 // check if the original request already does have an mdl associated
577 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
578 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
581 // Sanity check that the Mdl does describe the TransferData for read/write
583 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
585 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
588 // is there an offset
590 if (MdlVirtualAddress
!= Context
->TransferData
)
595 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, MmGetMdlByteCount(OriginalRequest
->MdlAddress
), FALSE
, FALSE
, NULL
);
596 if (!Context
->TransferBufferMDL
)
599 // failed to allocate MDL
601 return STATUS_INSUFFICIENT_RESOURCES
;
605 // now build the partial mdl
607 IoBuildPartialMdl(OriginalRequest
->MdlAddress
, Context
->TransferBufferMDL
, Context
->TransferData
, Context
->TransferDataLength
);
611 if (!Context
->TransferBufferMDL
)
614 // I/O paging request
616 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
622 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
624 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
625 if (!Context
->TransferBufferMDL
)
628 // failed to allocate MDL
630 return STATUS_INSUFFICIENT_RESOURCES
;
634 // build mdl for nonpaged pool
636 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
642 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
644 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
645 if (!Context
->TransferBufferMDL
)
648 // failed to allocate MDL
650 return STATUS_INSUFFICIENT_RESOURCES
;
654 // build mdl for nonpaged pool
656 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
661 // now allocate the request
663 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
666 FreeItem(Context
->cbw
);
668 return STATUS_INSUFFICIENT_RESOURCES
;
672 // get next stack location
674 IoStack
= IoGetNextIrpStackLocation(Irp
);
677 // initialize stack location
679 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
680 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
681 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
682 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
683 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
686 // setup completion routine
688 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
693 // mark orignal irp as pending
695 IoMarkIrpPending(OriginalRequest
);
701 IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
706 return STATUS_PENDING
;
710 USBSTOR_SendInquiryCmd(
711 IN PDEVICE_OBJECT DeviceObject
)
716 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
717 PUFI_INQUIRY_RESPONSE Response
;
721 // allocate inquiry response
723 Response
= AllocateItem(NonPagedPool
, PAGE_SIZE
);
729 return STATUS_INSUFFICIENT_RESOURCES
;
733 // get PDO device extension
735 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
738 // initialize inquiry cmd
740 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
741 Cmd
.Code
= SCSIOP_INQUIRY
;
742 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
743 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
748 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
751 // now send the request
753 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
756 // wait for the action to complete
758 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
760 DPRINT1("Response %p\n", Response
);
761 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
762 DPRINT1("RMB %x\n", Response
->RMB
);
763 DPRINT1("Version %x\n", Response
->Version
);
764 DPRINT1("Format %x\n", Response
->Format
);
765 DPRINT1("Length %x\n", Response
->Length
);
766 DPRINT1("Reserved %x\n", Response
->Reserved
);
767 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]);
768 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],
769 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
770 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
771 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
773 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
776 // store inquiry data
778 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
787 USBSTOR_SendCapacityCmd(
788 IN PDEVICE_OBJECT DeviceObject
,
791 UFI_CAPACITY_CMD Cmd
;
792 PUFI_CAPACITY_RESPONSE Response
;
793 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
796 // get PDO device extension
798 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
801 // allocate capacity response
803 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, sizeof(UFI_CAPACITY_RESPONSE
));
809 return STATUS_INSUFFICIENT_RESOURCES
;
813 // initialize capacity cmd
815 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
816 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
817 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
820 // send request, response will be freed in completion routine
822 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
);
826 USBSTOR_SendModeSenseCmd(
827 IN PDEVICE_OBJECT DeviceObject
,
836 PUFI_MODE_PARAMETER_HEADER Header
;
838 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
839 PIO_STACK_LOCATION IoStack
;
840 PSCSI_REQUEST_BLOCK Request
;
843 // get PDO device extension
845 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
850 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
853 // get current stack location
855 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
860 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
862 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
863 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
864 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
865 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
866 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
867 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
870 // start next request
872 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
874 return STATUS_SUCCESS
;
878 // get SCSI command data block
880 pCDB
= (PCDB
)Request
->Cdb
;
883 // get PDO device extension
885 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
888 // allocate sense response from non paged pool
890 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
896 return STATUS_INSUFFICIENT_RESOURCES
;
905 // MODE_PAGE_ERROR_RECOVERY
906 // MODE_PAGE_FLEXIBILE
907 // MODE_PAGE_LUN_MAPPING
908 // MODE_PAGE_FAULT_REPORTING
909 // MODE_SENSE_RETURN_ALL
912 // initialize mode sense cmd
914 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
915 Cmd
.Code
= SCSIOP_MODE_SENSE
;
916 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
917 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
918 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
919 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
921 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
922 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
925 // now send mode sense cmd
927 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
928 if (!NT_SUCCESS(Status
))
931 // failed to send CBW
933 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
940 // now send data block response
942 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
943 if (!NT_SUCCESS(Status
))
946 // failed to send CBW
948 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
954 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
957 // TODO: build layout
959 // first struct is the header
960 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
963 // MODE_PARAMETER_BLOCK
971 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
973 DPRINT1("------------------------\n");
974 DPRINT1("CSW %p\n", &CSW
);
975 DPRINT1("Signature %x\n", CSW
.Signature
);
976 DPRINT1("Tag %x\n", CSW
.Tag
);
977 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
978 DPRINT1("Status %x\n", CSW
.Status
);
981 // FIXME: handle error
983 ASSERT(CSW
.Status
== 0);
984 ASSERT(CSW
.DataResidue
== 0);
987 // calculate transfer length
989 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
994 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
999 FreeItem(OutControl
);
1014 USBSTOR_SendReadWriteCmd(
1015 IN PDEVICE_OBJECT DeviceObject
,
1018 UFI_READ_WRITE_CMD Cmd
;
1019 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1022 PIO_STACK_LOCATION IoStack
;
1023 PSCSI_REQUEST_BLOCK Request
;
1026 // get current stack location
1028 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1031 // get request block
1033 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1036 // get SCSI command data block
1038 pCDB
= (PCDB
)Request
->Cdb
;
1041 // get PDO device extension
1043 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1046 // informal debug print
1048 DPRINT("USBSTOR_SendReadWriteCmd DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
1053 ASSERT(PDODeviceExtension
->BlockLength
);
1058 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
1061 // initialize read cmd
1063 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
1064 Cmd
.Code
= pCDB
->AsByte
[0];
1065 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1066 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
1067 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
1068 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
1069 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
1070 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
1071 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
1073 DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
1078 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
);
1082 USBSTOR_SendTestUnitCmd(
1083 IN PDEVICE_OBJECT DeviceObject
,
1086 UFI_TEST_UNIT_CMD Cmd
;
1087 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1088 PIO_STACK_LOCATION IoStack
;
1089 PSCSI_REQUEST_BLOCK Request
;
1092 // get current stack location
1094 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1097 // get request block
1099 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1102 // no transfer length
1104 ASSERT(Request
->DataTransferLength
== 0);
1107 // get PDO device extension
1109 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1112 // initialize test unit cmd
1114 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1115 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1116 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1121 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
);
1126 USBSTOR_HandleExecuteSCSI(
1127 IN PDEVICE_OBJECT DeviceObject
,
1132 PIO_STACK_LOCATION IoStack
;
1133 PSCSI_REQUEST_BLOCK Request
;
1134 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1137 // get PDO device extension
1139 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1144 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
1147 // get current stack location
1149 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1152 // get request block
1154 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1157 // get SCSI command data block
1159 pCDB
= (PCDB
)Request
->Cdb
;
1161 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1163 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1168 ASSERT(Request
->DataBuffer
);
1170 DPRINT("SCSIOP_READ_CAPACITY Length %\n", Request
->DataTransferLength
);
1171 Status
= USBSTOR_SendCapacityCmd(DeviceObject
, Irp
);
1173 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1175 DPRINT1("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1176 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1177 ASSERT(Request
->DataBuffer
);
1180 // send mode sense command
1182 Status
= USBSTOR_SendModeSenseCmd(DeviceObject
, Irp
);
1184 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1186 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1189 // send read / write command
1191 Status
= USBSTOR_SendReadWriteCmd(DeviceObject
, Irp
);
1193 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1195 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1198 // just complete the request
1200 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1201 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1202 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1203 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
1204 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1207 // start next request
1209 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
1211 return STATUS_SUCCESS
;
1213 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1215 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1218 // send test unit command
1220 Status
= USBSTOR_SendTestUnitCmd(DeviceObject
, Irp
);
1224 DPRINT1("UNIMPLEMENTED Operation Code %x\n", pCDB
->AsByte
[0]);
1225 Request
->SrbStatus
= SRB_STATUS_ERROR
;
1226 Status
= STATUS_NOT_SUPPORTED
;