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)
20 IN ULONG DataTransferLength
,
22 IN UCHAR CommandBlockLength
,
23 IN PUCHAR CommandBlock
,
29 ASSERT(CommandBlockLength
<= 16);
34 Control
->Signature
= CBW_SIGNATURE
;
36 Control
->DataTransferLength
= DataTransferLength
;
37 Control
->Flags
= (CommandBlock
[0] != SCSIOP_WRITE
) ? 0x80 : 0x00;
38 Control
->LUN
= (LUN
& MAX_LUN
);
39 Control
->CommandBlockLength
= CommandBlockLength
;
44 RtlCopyMemory(Control
->CommandBlock
, CommandBlock
, CommandBlockLength
);
49 return STATUS_SUCCESS
;
53 USBSTOR_AllocateIrpContext()
58 // allocate irp context
60 Context
= (PIRP_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(IRP_CONTEXT
));
72 Context
->cbw
= (PCBW
)AllocateItem(NonPagedPool
, 512);
96 if (Context
->csw
->Signature
!= CSW_SIGNATURE
)
98 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE
, Context
->csw
->Signature
);
102 if (Context
->csw
->Tag
!= (ULONG
)Context
->csw
)
104 DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG
)Context
->csw
, Context
->csw
->Tag
);
108 if (Context
->csw
->Status
!= 0x00)
110 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context
->csw
->Status
);
122 USBSTOR_QueueWorkItem(
123 PIRP_CONTEXT Context
,
126 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData
;
129 // Allocate Work Item Data
131 ErrorHandlerWorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ERRORHANDLER_WORKITEM_DATA
), USB_STOR_TAG
);
132 if (!ErrorHandlerWorkItemData
)
137 return STATUS_INSUFFICIENT_RESOURCES
;
141 // error handling started
143 Context
->FDODeviceExtension
->SrbErrorHandlingActive
= TRUE
;
146 // srb error handling finished
148 Context
->FDODeviceExtension
->TimerWorkQueueEnabled
= FALSE
;
151 // Initialize and queue the work item to handle the error
153 ExInitializeWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
,
154 ErrorHandlerWorkItemRoutine
,
155 ErrorHandlerWorkItemData
);
157 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
158 ErrorHandlerWorkItemData
->Context
= Context
;
159 ErrorHandlerWorkItemData
->Irp
= Irp
;
160 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
162 DPRINT1("Queuing WorkItemROutine\n");
163 ExQueueWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
, DelayedWorkQueue
);
164 return STATUS_MORE_PROCESSING_REQUIRED
;
171 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
175 USBSTOR_CSWCompletionRoutine(
176 PDEVICE_OBJECT DeviceObject
,
180 PIRP_CONTEXT Context
;
181 PIO_STACK_LOCATION IoStack
;
182 PSCSI_REQUEST_BLOCK Request
;
184 PREAD_CAPACITY_DATA_EX CapacityDataEx
;
185 PREAD_CAPACITY_DATA CapacityData
;
186 PUFI_CAPACITY_RESPONSE Response
;
192 Context
= (PIRP_CONTEXT
)Ctx
;
197 if (Context
->TransferBufferMDL
)
200 // is there an irp associated
205 // did we allocate the mdl
207 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
212 IoFreeMdl(Context
->TransferBufferMDL
);
220 IoFreeMdl(Context
->TransferBufferMDL
);
224 DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp
->IoStatus
.Status
);
226 if (!NT_SUCCESS(Irp
->IoStatus
.Information
))
228 if (Context
->ErrorIndex
== 0)
231 // increment error index
233 Context
->ErrorIndex
= 1;
236 // clear stall and resend cbw
238 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
239 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
240 return STATUS_MORE_PROCESSING_REQUIRED
;
244 // perform reset recovery
246 Context
->ErrorIndex
= 2;
248 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
249 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
250 return STATUS_MORE_PROCESSING_REQUIRED
;
253 if (!USBSTOR_IsCSWValid(Context
))
256 // perform reset recovery
258 Context
->ErrorIndex
= 2;
260 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
261 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
262 return STATUS_MORE_PROCESSING_REQUIRED
;
267 // get current stack location
269 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
274 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
277 Status
= Irp
->IoStatus
.Status
;
280 // get SCSI command data block
282 pCDB
= (PCDB
)Request
->Cdb
;
283 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
286 // read capacity needs special work
288 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
293 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
298 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
299 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
301 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
306 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
311 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
312 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
313 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
320 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
325 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
326 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
327 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
333 FreeItem(Context
->TransferData
);
339 FreeItem(Context
->cbw
);
342 // FIXME: check status
344 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
345 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
348 // terminate current request
350 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
355 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
358 // start next request
360 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
363 // free our allocated irp
375 return STATUS_MORE_PROCESSING_REQUIRED
;
380 PIRP_CONTEXT Context
,
383 PIO_STACK_LOCATION IoStack
;
386 // get next irp stack location
388 IoStack
= IoGetNextIrpStackLocation(Irp
);
391 // now initialize the urb for sending the csw
393 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
394 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
395 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
399 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
403 // initialize stack location
405 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
406 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
407 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
408 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
409 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
413 // setup completion routine
415 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
420 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
427 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
431 USBSTOR_DataCompletionRoutine(
432 PDEVICE_OBJECT DeviceObject
,
436 PIRP_CONTEXT Context
;
440 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
445 Context
= (PIRP_CONTEXT
)Ctx
;
447 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
450 // clear stall and resend cbw
452 Context
->ErrorIndex
= 1;
453 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
454 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
455 return STATUS_MORE_PROCESSING_REQUIRED
;
461 USBSTOR_SendCSW(Context
, Irp
);
466 return STATUS_MORE_PROCESSING_REQUIRED
;
472 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
476 USBSTOR_CBWCompletionRoutine(
477 PDEVICE_OBJECT DeviceObject
,
481 PIRP_CONTEXT Context
;
482 PIO_STACK_LOCATION IoStack
;
484 USBD_PIPE_HANDLE PipeHandle
;
486 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
491 Context
= (PIRP_CONTEXT
)Ctx
;
494 // get next stack location
496 IoStack
= IoGetNextIrpStackLocation(Irp
);
499 // is there data to be submitted
501 if (Context
->TransferDataLength
)
506 Code
= Context
->cbw
->CommandBlock
[0];
508 if (Code
== SCSIOP_WRITE
)
511 // write request use bulk out pipe
513 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
518 // default bulk in pipe
520 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
524 // now initialize the urb for sending data
526 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
527 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
530 Context
->TransferBufferMDL
,
531 Context
->TransferDataLength
,
532 ((Code
== SCSIOP_WRITE
) ? USBD_TRANSFER_DIRECTION_OUT
: (USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
)),
536 // setup completion routine
538 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
543 // now initialize the urb for sending the csw
546 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
547 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
548 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
552 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
556 // setup completion routine
558 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
562 // initialize stack location
564 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
565 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
566 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
567 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
568 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
573 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
575 return STATUS_MORE_PROCESSING_REQUIRED
;
582 DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
583 Block
[0] & 0xFF, Block
[1] & 0xFF, Block
[2] & 0xFF, Block
[3] & 0xFF, Block
[4] & 0xFF, Block
[5] & 0xFF, Block
[6] & 0xFF, Block
[7] & 0xFF, Block
[8] & 0xFF, Block
[9] & 0xFF,
584 Block
[10] & 0xFF, Block
[11] & 0xFF, Block
[12] & 0xFF, Block
[13] & 0xFF, Block
[14] & 0xFF, Block
[15] & 0xFF, Block
[16] & 0xFF, Block
[17] & 0xFF, Block
[18] & 0xFF, Block
[19] & 0xFF,
585 Block
[20] & 0xFF, Block
[21] & 0xFF, Block
[22] & 0xFF, Block
[23] & 0xFF, Block
[24] & 0xFF, Block
[25] & 0xFF, Block
[26] & 0xFF, Block
[27] & 0xFF, Block
[28] & 0xFF, Block
[29] & 0xFF,
592 PIRP_CONTEXT Context
,
595 PIO_STACK_LOCATION IoStack
;
598 // get next stack location
600 IoStack
= IoGetNextIrpStackLocation(Irp
);
603 // initialize stack location
605 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
606 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
607 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
608 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
609 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
612 // setup completion routine
614 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
619 return IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
624 IN PDEVICE_OBJECT DeviceObject
,
625 IN PIRP OriginalRequest
,
626 IN UCHAR CommandLength
,
628 IN ULONG TransferDataLength
,
629 IN PUCHAR TransferData
,
632 PIRP_CONTEXT Context
;
633 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
634 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
636 PUCHAR MdlVirtualAddress
;
639 // first allocate irp context
641 Context
= USBSTOR_AllocateIrpContext();
647 return STATUS_INSUFFICIENT_RESOURCES
;
651 // get PDO device extension
653 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
656 // get FDO device extension
658 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
663 USBSTOR_BuildCBW((ULONG
)Context
->cbw
,
665 PDODeviceExtension
->LUN
,
670 DPRINT("CBW %p\n", Context
->cbw
);
671 DumpCBW((PUCHAR
)Context
->cbw
);
674 // now initialize the urb
676 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
677 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
678 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
682 USBD_TRANSFER_DIRECTION_OUT
,
686 // initialize rest of context
688 Context
->Irp
= OriginalRequest
;
689 Context
->TransferData
= TransferData
;
690 Context
->TransferDataLength
= TransferDataLength
;
691 Context
->FDODeviceExtension
= FDODeviceExtension
;
692 Context
->PDODeviceExtension
= PDODeviceExtension
;
693 Context
->RetryCount
= RetryCount
;
696 // is there transfer data
698 if (Context
->TransferDataLength
)
701 // check if the original request already does have an mdl associated
705 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
706 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
709 // Sanity check that the Mdl does describe the TransferData for read/write
711 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
713 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
716 // is there an offset
718 if (MdlVirtualAddress
!= Context
->TransferData
)
723 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, MmGetMdlByteCount(OriginalRequest
->MdlAddress
), FALSE
, FALSE
, NULL
);
724 if (!Context
->TransferBufferMDL
)
727 // failed to allocate MDL
729 return STATUS_INSUFFICIENT_RESOURCES
;
733 // now build the partial mdl
735 IoBuildPartialMdl(OriginalRequest
->MdlAddress
, Context
->TransferBufferMDL
, Context
->TransferData
, Context
->TransferDataLength
);
739 if (!Context
->TransferBufferMDL
)
742 // I/O paging request
744 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
750 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
752 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
753 if (!Context
->TransferBufferMDL
)
756 // failed to allocate MDL
758 return STATUS_INSUFFICIENT_RESOURCES
;
762 // build mdl for nonpaged pool
764 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
770 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
772 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
773 if (!Context
->TransferBufferMDL
)
776 // failed to allocate MDL
778 return STATUS_INSUFFICIENT_RESOURCES
;
782 // build mdl for nonpaged pool
784 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
789 // now allocate the request
791 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
794 FreeItem(Context
->cbw
);
796 return STATUS_INSUFFICIENT_RESOURCES
;
802 // mark orignal irp as pending
804 IoMarkIrpPending(OriginalRequest
);
810 USBSTOR_SendCBW(Context
, Irp
);
815 return STATUS_PENDING
;
819 USBSTOR_SendFormatCapacity(
820 IN PDEVICE_OBJECT DeviceObject
,
824 UFI_READ_FORMAT_CAPACITY Cmd
;
825 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
826 PIO_STACK_LOCATION IoStack
;
827 PSCSI_REQUEST_BLOCK Request
;
830 // get current stack location
832 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
835 // get PDO device extension
837 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
842 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
845 // initialize inquiry cmd
847 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_FORMAT_CAPACITY
));
848 Cmd
.Code
= SCSIOP_READ_FORMATTED_CAPACITY
;
849 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
850 Cmd
.AllocationLengthMsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) >> 8;
851 Cmd
.AllocationLengthLsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) & 0xFF;
854 // now send the request
856 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_FORMAT_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
861 IN PDEVICE_OBJECT DeviceObject
,
866 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
867 PIO_STACK_LOCATION IoStack
;
868 PSCSI_REQUEST_BLOCK Request
;
871 // get current stack location
873 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
878 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
881 // get PDO device extension
883 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
886 // initialize inquiry cmd
888 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
889 Cmd
.Code
= SCSIOP_INQUIRY
;
890 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
891 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
896 ASSERT(Request
->DataTransferLength
>= sizeof(UFI_INQUIRY_RESPONSE
));
899 // now send the request
901 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
905 USBSTOR_SendCapacity(
906 IN PDEVICE_OBJECT DeviceObject
,
910 UFI_CAPACITY_CMD Cmd
;
911 PUFI_CAPACITY_RESPONSE Response
;
912 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
915 // get PDO device extension
917 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
920 // allocate capacity response
922 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, PAGE_SIZE
);
928 return STATUS_INSUFFICIENT_RESOURCES
;
932 // initialize capacity cmd
934 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
935 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
936 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
939 // send request, response will be freed in completion routine
941 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
, RetryCount
);
945 USBSTOR_SendModeSense(
946 IN PDEVICE_OBJECT DeviceObject
,
956 PUFI_MODE_PARAMETER_HEADER Header
;
958 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
959 PIO_STACK_LOCATION IoStack
;
960 PSCSI_REQUEST_BLOCK Request
;
963 // get PDO device extension
965 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
970 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
973 // get current stack location
975 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
980 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
982 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
983 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
984 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
985 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
986 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
987 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
990 // start next request
992 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
994 return STATUS_SUCCESS
;
998 // get SCSI command data block
1000 pCDB
= (PCDB
)Request
->Cdb
;
1003 // get PDO device extension
1005 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1008 // allocate sense response from non paged pool
1010 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
1016 return STATUS_INSUFFICIENT_RESOURCES
;
1025 // MODE_PAGE_ERROR_RECOVERY
1026 // MODE_PAGE_FLEXIBILE
1027 // MODE_PAGE_LUN_MAPPING
1028 // MODE_PAGE_FAULT_REPORTING
1029 // MODE_SENSE_RETURN_ALL
1032 // initialize mode sense cmd
1034 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
1035 Cmd
.Code
= SCSIOP_MODE_SENSE
;
1036 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1037 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
1038 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
1039 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
1041 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
1042 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
1045 // now send mode sense cmd
1047 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
1048 if (!NT_SUCCESS(Status
))
1051 // failed to send CBW
1053 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
1060 // now send data block response
1062 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
1063 if (!NT_SUCCESS(Status
))
1066 // failed to send CBW
1068 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
1074 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
1077 // TODO: build layout
1079 // first struct is the header
1080 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
1083 // MODE_PARAMETER_BLOCK
1091 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
1093 DPRINT1("------------------------\n");
1094 DPRINT1("CSW %p\n", &CSW
);
1095 DPRINT1("Signature %x\n", CSW
.Signature
);
1096 DPRINT1("Tag %x\n", CSW
.Tag
);
1097 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
1098 DPRINT1("Status %x\n", CSW
.Status
);
1101 // FIXME: handle error
1103 ASSERT(CSW
.Status
== 0);
1104 ASSERT(CSW
.DataResidue
== 0);
1107 // calculate transfer length
1109 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
1114 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
1119 FreeItem(OutControl
);
1134 USBSTOR_SendReadWrite(
1135 IN PDEVICE_OBJECT DeviceObject
,
1137 IN ULONG RetryCount
)
1139 UFI_READ_WRITE_CMD Cmd
;
1140 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1142 ULONG BlockCount
, Temp
;
1143 PIO_STACK_LOCATION IoStack
;
1144 PSCSI_REQUEST_BLOCK Request
;
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
;
1162 // get PDO device extension
1164 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1167 // informal debug print
1169 DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
1174 ASSERT(PDODeviceExtension
->BlockLength
);
1179 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
1182 // initialize read cmd
1184 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
1185 Cmd
.Code
= pCDB
->AsByte
[0];
1186 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1187 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
1188 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
1189 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
1190 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
1191 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
1192 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
1197 Temp
= (Cmd
.ContiguousLogicBlocksByte0
<< 8 | Cmd
.ContiguousLogicBlocksByte1
);
1198 ASSERT(NTOHL(Temp
== BlockCount
));
1200 DPRINT("USBSTOR_SendReadWrite BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
1205 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
1209 USBSTOR_SendTestUnit(
1210 IN PDEVICE_OBJECT DeviceObject
,
1212 IN ULONG RetryCount
)
1214 UFI_TEST_UNIT_CMD Cmd
;
1215 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1216 PIO_STACK_LOCATION IoStack
;
1217 PSCSI_REQUEST_BLOCK Request
;
1220 // get current stack location
1222 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1225 // get request block
1227 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1230 // no transfer length
1232 ASSERT(Request
->DataTransferLength
== 0);
1235 // get PDO device extension
1237 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1240 // initialize test unit cmd
1242 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1243 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1244 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1249 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
, RetryCount
);
1253 USBSTOR_SendUnknownRequest(
1254 IN PDEVICE_OBJECT DeviceObject
,
1256 IN ULONG RetryCount
)
1258 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1259 PIO_STACK_LOCATION IoStack
;
1260 PSCSI_REQUEST_BLOCK Request
;
1261 UFI_UNKNOWN_CMD Cmd
;
1264 // get current stack location
1266 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1269 // get request block
1271 Request
= IoStack
->Parameters
.Others
.Argument1
;
1274 // get PDO device extension
1276 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1279 // check that we're sending to the right LUN
1281 ASSERT(Request
->Cdb
[1] == (PDODeviceExtension
->LUN
& MAX_LUN
));
1286 ASSERT(Request
->CdbLength
<= sizeof(UFI_UNKNOWN_CMD
));
1289 // initialize test unit cmd
1291 RtlCopyMemory(&Cmd
, Request
->Cdb
, Request
->CdbLength
);
1296 return USBSTOR_SendRequest(DeviceObject
, Irp
, Request
->CdbLength
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, Request
->DataBuffer
, RetryCount
);
1300 USBSTOR_HandleExecuteSCSI(
1301 IN PDEVICE_OBJECT DeviceObject
,
1303 IN ULONG RetryCount
)
1307 PIO_STACK_LOCATION IoStack
;
1308 PSCSI_REQUEST_BLOCK Request
;
1309 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1312 // get PDO device extension
1314 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1319 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
1322 // get current stack location
1324 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1327 // get request block
1329 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1332 // get SCSI command data block
1334 pCDB
= (PCDB
)Request
->Cdb
;
1336 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1338 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1343 ASSERT(Request
->DataBuffer
);
1345 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request
->DataTransferLength
);
1346 Status
= USBSTOR_SendCapacity(DeviceObject
, Irp
, RetryCount
);
1348 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1350 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1351 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1352 ASSERT(Request
->DataBuffer
);
1355 // send mode sense command
1357 Status
= USBSTOR_SendModeSense(DeviceObject
, Irp
, RetryCount
);
1359 else if (pCDB
->AsByte
[0] == SCSIOP_READ_FORMATTED_CAPACITY
)
1361 DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request
->DataTransferLength
);
1364 // send read format capacity
1366 Status
= USBSTOR_SendFormatCapacity(DeviceObject
, Irp
, RetryCount
);
1368 else if (pCDB
->AsByte
[0] == SCSIOP_INQUIRY
)
1370 DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request
->DataTransferLength
);
1373 // send read format capacity
1375 Status
= USBSTOR_SendInquiry(DeviceObject
, Irp
, RetryCount
);
1377 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1379 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1382 // send read / write command
1384 Status
= USBSTOR_SendReadWrite(DeviceObject
, Irp
, RetryCount
);
1386 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1388 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1391 // just complete the request
1393 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1394 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1395 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1396 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
1397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1400 // start next request
1402 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
1404 return STATUS_SUCCESS
;
1406 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1408 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1411 // send test unit command
1413 Status
= USBSTOR_SendTestUnit(DeviceObject
, Irp
, RetryCount
);
1417 // Unknown request. Simply forward
1418 DPRINT1("Forwarding unknown Operation Code %x\n", pCDB
->AsByte
[0]);
1419 Status
= USBSTOR_SendUnknownRequest(DeviceObject
, Irp
, RetryCount
);