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
= (CommandBlock
[0] != SCSIOP_WRITE
) ? 0x80 : 0x00;
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 if (Context
->csw
->Signature
!= CSW_SIGNATURE
)
275 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE
, Context
->csw
->Signature
);
278 if (Context
->csw
->Tag
!= (ULONG
)Context
->csw
)
280 DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG
)Context
->csw
, Context
->csw
->Tag
);
283 if (Context
->csw
->Status
!= 0x00)
285 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context
->csw
->Status
);
291 FreeItem(Context
->cbw
);
297 // FIXME: check status
299 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
300 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
303 // terminate current request
305 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
310 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
313 // start next request
315 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
323 KeSetEvent(Context
->Event
, 0, FALSE
);
327 // free our allocated irp
339 return STATUS_MORE_PROCESSING_REQUIRED
;
345 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
349 USBSTOR_DataCompletionRoutine(
350 PDEVICE_OBJECT DeviceObject
,
354 PIRP_CONTEXT Context
;
355 PIO_STACK_LOCATION IoStack
;
357 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
362 Context
= (PIRP_CONTEXT
)Ctx
;
365 // get next stack location
368 IoStack
= IoGetNextIrpStackLocation(Irp
);
371 // now initialize the urb for sending the csw
373 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
374 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
375 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
379 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
383 // initialize stack location
385 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
386 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
387 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
388 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
389 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
393 // setup completion routine
395 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
400 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
402 return STATUS_MORE_PROCESSING_REQUIRED
;
408 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
412 USBSTOR_CBWCompletionRoutine(
413 PDEVICE_OBJECT DeviceObject
,
417 PIRP_CONTEXT Context
;
418 PIO_STACK_LOCATION IoStack
;
420 USBD_PIPE_HANDLE PipeHandle
;
422 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
427 Context
= (PIRP_CONTEXT
)Ctx
;
430 // get next stack location
432 IoStack
= IoGetNextIrpStackLocation(Irp
);
435 // is there data to be submitted
437 if (Context
->TransferDataLength
)
442 Code
= Context
->cbw
->CommandBlock
[0];
444 if (Code
== SCSIOP_WRITE
)
447 // write request use bulk out pipe
449 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
454 // default bulk in pipe
456 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
460 // now initialize the urb for sending data
462 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
463 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
466 Context
->TransferBufferMDL
,
467 Context
->TransferDataLength
,
468 ((Code
== SCSIOP_WRITE
) ? USBD_TRANSFER_DIRECTION_OUT
: (USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
)),
472 // setup completion routine
474 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
479 // now initialize the urb for sending the csw
482 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
483 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
484 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
488 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
492 // setup completion routine
494 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
498 // initialize stack location
500 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
501 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
502 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
503 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
504 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
509 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
511 return STATUS_MORE_PROCESSING_REQUIRED
;
516 IN PDEVICE_OBJECT DeviceObject
,
517 IN PIRP OriginalRequest
,
518 IN OPTIONAL PKEVENT Event
,
519 IN UCHAR CommandLength
,
521 IN ULONG TransferDataLength
,
522 IN PUCHAR TransferData
)
524 PIRP_CONTEXT Context
;
525 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
526 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
528 PIO_STACK_LOCATION IoStack
;
529 PUCHAR MdlVirtualAddress
;
532 // first allocate irp context
534 Context
= USBSTOR_AllocateIrpContext();
540 return STATUS_INSUFFICIENT_RESOURCES
;
544 // get PDO device extension
546 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
549 // get FDO device extension
551 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
556 USBSTOR_BuildCBW((ULONG
)Context
->cbw
,
558 PDODeviceExtension
->LUN
,
563 DPRINT("CBW %p\n", Context
->cbw
);
566 // now initialize the urb
568 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
569 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
570 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
574 USBD_TRANSFER_DIRECTION_OUT
,
578 // initialize rest of context
580 Context
->Irp
= OriginalRequest
;
581 Context
->TransferData
= TransferData
;
582 Context
->TransferDataLength
= TransferDataLength
;
583 Context
->FDODeviceExtension
= FDODeviceExtension
;
584 Context
->PDODeviceExtension
= PDODeviceExtension
;
585 Context
->Event
= Event
;
588 // is there transfer data
590 if (Context
->TransferDataLength
)
593 // check if the original request already does have an mdl associated
597 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
598 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
601 // Sanity check that the Mdl does describe the TransferData for read/write
603 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
605 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
608 // is there an offset
610 if (MdlVirtualAddress
!= Context
->TransferData
)
615 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, MmGetMdlByteCount(OriginalRequest
->MdlAddress
), FALSE
, FALSE
, NULL
);
616 if (!Context
->TransferBufferMDL
)
619 // failed to allocate MDL
621 return STATUS_INSUFFICIENT_RESOURCES
;
625 // now build the partial mdl
627 IoBuildPartialMdl(OriginalRequest
->MdlAddress
, Context
->TransferBufferMDL
, Context
->TransferData
, Context
->TransferDataLength
);
631 if (!Context
->TransferBufferMDL
)
634 // I/O paging request
636 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
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
);
662 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
664 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
665 if (!Context
->TransferBufferMDL
)
668 // failed to allocate MDL
670 return STATUS_INSUFFICIENT_RESOURCES
;
674 // build mdl for nonpaged pool
676 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
681 // now allocate the request
683 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
686 FreeItem(Context
->cbw
);
688 return STATUS_INSUFFICIENT_RESOURCES
;
692 // get next stack location
694 IoStack
= IoGetNextIrpStackLocation(Irp
);
697 // initialize stack location
699 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
700 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
701 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
702 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
703 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
706 // setup completion routine
708 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
713 // mark orignal irp as pending
715 IoMarkIrpPending(OriginalRequest
);
721 IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
726 return STATUS_PENDING
;
730 USBSTOR_SendInquiryCmd(
731 IN PDEVICE_OBJECT DeviceObject
)
736 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
737 PUFI_INQUIRY_RESPONSE Response
;
741 // allocate inquiry response
743 Response
= AllocateItem(NonPagedPool
, PAGE_SIZE
);
749 return STATUS_INSUFFICIENT_RESOURCES
;
753 // get PDO device extension
755 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
758 // initialize inquiry cmd
760 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
761 Cmd
.Code
= SCSIOP_INQUIRY
;
762 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
763 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
768 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
771 // now send the request
773 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
776 // wait for the action to complete
778 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
780 KeResetEvent(&Event
);
781 DPRINT("Resending request\n");
784 // now send the request
786 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
789 // wait for the action to complete
791 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
795 DPRINT1("Response %p\n", Response
);
796 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
797 DPRINT1("RMB %x\n", Response
->RMB
);
798 DPRINT1("Version %x\n", Response
->Version
);
799 DPRINT1("Format %x\n", Response
->Format
);
800 DPRINT1("Length %x\n", Response
->Length
);
801 DPRINT1("Reserved %x\n", Response
->Reserved
);
802 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]);
803 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],
804 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
805 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
806 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
808 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
811 // store inquiry data
813 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
822 USBSTOR_SendCapacityCmd(
823 IN PDEVICE_OBJECT DeviceObject
,
826 UFI_CAPACITY_CMD Cmd
;
827 PUFI_CAPACITY_RESPONSE Response
;
828 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
829 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
832 // get PDO device extension
834 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
838 // get FDO device extension
840 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
844 // allocate capacity response
846 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, PAGE_SIZE
);
852 return STATUS_INSUFFICIENT_RESOURCES
;
856 // initialize capacity cmd
858 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
859 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
860 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
863 // send request, response will be freed in completion routine
865 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
);
869 USBSTOR_SendModeSenseCmd(
870 IN PDEVICE_OBJECT DeviceObject
,
879 PUFI_MODE_PARAMETER_HEADER Header
;
881 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
882 PIO_STACK_LOCATION IoStack
;
883 PSCSI_REQUEST_BLOCK Request
;
886 // get PDO device extension
888 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
893 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
896 // get current stack location
898 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
903 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
905 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
906 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
907 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
908 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
909 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
910 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
913 // start next request
915 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
917 return STATUS_SUCCESS
;
921 // get SCSI command data block
923 pCDB
= (PCDB
)Request
->Cdb
;
926 // get PDO device extension
928 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
931 // allocate sense response from non paged pool
933 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
939 return STATUS_INSUFFICIENT_RESOURCES
;
948 // MODE_PAGE_ERROR_RECOVERY
949 // MODE_PAGE_FLEXIBILE
950 // MODE_PAGE_LUN_MAPPING
951 // MODE_PAGE_FAULT_REPORTING
952 // MODE_SENSE_RETURN_ALL
955 // initialize mode sense cmd
957 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
958 Cmd
.Code
= SCSIOP_MODE_SENSE
;
959 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
960 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
961 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
962 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
964 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
965 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
968 // now send mode sense cmd
970 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
971 if (!NT_SUCCESS(Status
))
974 // failed to send CBW
976 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
983 // now send data block response
985 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
986 if (!NT_SUCCESS(Status
))
989 // failed to send CBW
991 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
997 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
1000 // TODO: build layout
1002 // first struct is the header
1003 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
1006 // MODE_PARAMETER_BLOCK
1014 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
1016 DPRINT1("------------------------\n");
1017 DPRINT1("CSW %p\n", &CSW
);
1018 DPRINT1("Signature %x\n", CSW
.Signature
);
1019 DPRINT1("Tag %x\n", CSW
.Tag
);
1020 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
1021 DPRINT1("Status %x\n", CSW
.Status
);
1024 // FIXME: handle error
1026 ASSERT(CSW
.Status
== 0);
1027 ASSERT(CSW
.DataResidue
== 0);
1030 // calculate transfer length
1032 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
1037 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
1042 FreeItem(OutControl
);
1057 USBSTOR_SendReadWriteCmd(
1058 IN PDEVICE_OBJECT DeviceObject
,
1061 UFI_READ_WRITE_CMD Cmd
;
1062 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1065 PIO_STACK_LOCATION IoStack
;
1066 PSCSI_REQUEST_BLOCK Request
;
1069 // get current stack location
1071 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1074 // get request block
1076 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1079 // get SCSI command data block
1081 pCDB
= (PCDB
)Request
->Cdb
;
1084 // get PDO device extension
1086 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1089 // informal debug print
1091 DPRINT("USBSTOR_SendReadWriteCmd DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
1096 ASSERT(PDODeviceExtension
->BlockLength
);
1101 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
1104 // initialize read cmd
1106 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
1107 Cmd
.Code
= pCDB
->AsByte
[0];
1108 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1109 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
1110 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
1111 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
1112 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
1113 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
1114 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
1116 DPRINT("USBSTOR_SendReadWriteCmd BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
1121 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
);
1125 USBSTOR_SendTestUnitCmd(
1126 IN PDEVICE_OBJECT DeviceObject
,
1129 UFI_TEST_UNIT_CMD Cmd
;
1130 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1131 PIO_STACK_LOCATION IoStack
;
1132 PSCSI_REQUEST_BLOCK Request
;
1135 // get current stack location
1137 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1140 // get request block
1142 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1145 // no transfer length
1147 ASSERT(Request
->DataTransferLength
== 0);
1150 // get PDO device extension
1152 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1155 // initialize test unit cmd
1157 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1158 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1159 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1164 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
);
1169 USBSTOR_HandleExecuteSCSI(
1170 IN PDEVICE_OBJECT DeviceObject
,
1175 PIO_STACK_LOCATION IoStack
;
1176 PSCSI_REQUEST_BLOCK Request
;
1177 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1180 // get PDO device extension
1182 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1187 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
1190 // get current stack location
1192 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1195 // get request block
1197 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1200 // get SCSI command data block
1202 pCDB
= (PCDB
)Request
->Cdb
;
1204 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1206 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1211 ASSERT(Request
->DataBuffer
);
1213 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request
->DataTransferLength
);
1214 Status
= USBSTOR_SendCapacityCmd(DeviceObject
, Irp
);
1216 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1218 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1219 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1220 ASSERT(Request
->DataBuffer
);
1223 // send mode sense command
1225 Status
= USBSTOR_SendModeSenseCmd(DeviceObject
, Irp
);
1227 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1229 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1232 // send read / write command
1234 Status
= USBSTOR_SendReadWriteCmd(DeviceObject
, Irp
);
1236 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1238 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1241 // just complete the request
1243 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1244 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1245 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1246 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
1247 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1250 // start next request
1252 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
1254 return STATUS_SUCCESS
;
1256 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1258 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1261 // send test unit command
1263 Status
= USBSTOR_SendTestUnitCmd(DeviceObject
, Irp
);
1267 DPRINT1("UNIMPLEMENTED Operation Code %x\n", pCDB
->AsByte
[0]);
1268 Request
->SrbStatus
= SRB_STATUS_ERROR
;
1269 Status
= STATUS_NOT_SUPPORTED
;