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);
93 if (Context
->csw
->Signature
!= CSW_SIGNATURE
)
95 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE
, Context
->csw
->Signature
);
99 if (Context
->csw
->Tag
!= (ULONG
)Context
->csw
)
101 DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG
)Context
->csw
, Context
->csw
->Tag
);
105 if (Context
->csw
->Status
!= 0x00)
107 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context
->csw
->Status
);
119 USBSTOR_QueueWorkItem(
120 PIRP_CONTEXT Context
,
123 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData
;
126 // Allocate Work Item Data
128 ErrorHandlerWorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ERRORHANDLER_WORKITEM_DATA
), USB_STOR_TAG
);
129 if (!ErrorHandlerWorkItemData
)
134 return STATUS_INSUFFICIENT_RESOURCES
;
138 // error handling started
140 Context
->FDODeviceExtension
->SrbErrorHandlingActive
= TRUE
;
143 // srb error handling finished
145 Context
->FDODeviceExtension
->TimerWorkQueueEnabled
= FALSE
;
148 // Initialize and queue the work item to handle the error
150 ExInitializeWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
,
151 ErrorHandlerWorkItemRoutine
,
152 ErrorHandlerWorkItemData
);
154 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
155 ErrorHandlerWorkItemData
->Context
= Context
;
156 ErrorHandlerWorkItemData
->Irp
= Irp
;
157 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
159 DPRINT1("Queuing WorkItemROutine\n");
160 ExQueueWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
, DelayedWorkQueue
);
161 return STATUS_MORE_PROCESSING_REQUIRED
;
168 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
172 USBSTOR_CSWCompletionRoutine(
173 PDEVICE_OBJECT DeviceObject
,
177 PIRP_CONTEXT Context
;
178 PIO_STACK_LOCATION IoStack
;
179 PSCSI_REQUEST_BLOCK Request
;
181 PREAD_CAPACITY_DATA_EX CapacityDataEx
;
182 PREAD_CAPACITY_DATA CapacityData
;
183 PUFI_CAPACITY_RESPONSE Response
;
189 Context
= (PIRP_CONTEXT
)Ctx
;
194 if (Context
->TransferBufferMDL
)
197 // is there an irp associated
202 // did we allocate the mdl
204 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
209 IoFreeMdl(Context
->TransferBufferMDL
);
217 IoFreeMdl(Context
->TransferBufferMDL
);
221 DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp
->IoStatus
.Status
);
223 if (!NT_SUCCESS(Irp
->IoStatus
.Information
))
225 if (Context
->ErrorIndex
== 0)
228 // increment error index
230 Context
->ErrorIndex
= 1;
233 // clear stall and resend cbw
235 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
236 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
237 return STATUS_MORE_PROCESSING_REQUIRED
;
241 // perform reset recovery
243 Context
->ErrorIndex
= 2;
245 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
246 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
247 return STATUS_MORE_PROCESSING_REQUIRED
;
250 if (!USBSTOR_IsCSWValid(Context
))
253 // perform reset recovery
255 Context
->ErrorIndex
= 2;
257 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
258 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
259 return STATUS_MORE_PROCESSING_REQUIRED
;
264 // get current stack location
266 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
271 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
274 Status
= Irp
->IoStatus
.Status
;
277 // get SCSI command data block
279 pCDB
= (PCDB
)Request
->Cdb
;
280 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
283 // read capacity needs special work
285 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
290 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
295 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
296 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
298 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
303 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
308 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
309 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
310 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
317 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
322 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
323 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
324 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
330 FreeItem(Context
->TransferData
);
336 FreeItem(Context
->cbw
);
339 // FIXME: check status
341 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
342 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
345 // terminate current request
347 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
352 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
355 // start next request
357 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
360 // free our allocated irp
372 return STATUS_MORE_PROCESSING_REQUIRED
;
377 PIRP_CONTEXT Context
,
380 PIO_STACK_LOCATION IoStack
;
383 // get next irp stack location
385 IoStack
= IoGetNextIrpStackLocation(Irp
);
388 // now initialize the urb for sending the csw
390 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
391 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
392 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
396 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
400 // initialize stack location
402 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
403 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
404 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
405 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
406 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
410 // setup completion routine
412 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
417 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
424 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
428 USBSTOR_DataCompletionRoutine(
429 PDEVICE_OBJECT DeviceObject
,
433 PIRP_CONTEXT Context
;
437 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
442 Context
= (PIRP_CONTEXT
)Ctx
;
444 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
447 // clear stall and resend cbw
449 Context
->ErrorIndex
= 1;
450 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
451 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
452 return STATUS_MORE_PROCESSING_REQUIRED
;
458 USBSTOR_SendCSW(Context
, Irp
);
463 return STATUS_MORE_PROCESSING_REQUIRED
;
469 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
473 USBSTOR_CBWCompletionRoutine(
474 PDEVICE_OBJECT DeviceObject
,
478 PIRP_CONTEXT Context
;
479 PIO_STACK_LOCATION IoStack
;
481 USBD_PIPE_HANDLE PipeHandle
;
483 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
488 Context
= (PIRP_CONTEXT
)Ctx
;
491 // get next stack location
493 IoStack
= IoGetNextIrpStackLocation(Irp
);
496 // is there data to be submitted
498 if (Context
->TransferDataLength
)
503 Code
= Context
->cbw
->CommandBlock
[0];
505 if (Code
== SCSIOP_WRITE
)
508 // write request use bulk out pipe
510 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
515 // default bulk in pipe
517 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
521 // now initialize the urb for sending data
523 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
524 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
527 Context
->TransferBufferMDL
,
528 Context
->TransferDataLength
,
529 ((Code
== SCSIOP_WRITE
) ? USBD_TRANSFER_DIRECTION_OUT
: (USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
)),
533 // setup completion routine
535 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
540 // now initialize the urb for sending the csw
543 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
544 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
545 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
549 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
553 // setup completion routine
555 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
559 // initialize stack location
561 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
562 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
563 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
564 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
565 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
570 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
572 return STATUS_MORE_PROCESSING_REQUIRED
;
579 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",
580 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,
581 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,
582 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,
589 PIRP_CONTEXT Context
,
592 PIO_STACK_LOCATION IoStack
;
595 // get next stack location
597 IoStack
= IoGetNextIrpStackLocation(Irp
);
600 // initialize stack location
602 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
603 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
604 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
605 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
606 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
609 // setup completion routine
611 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
616 return IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
621 IN PDEVICE_OBJECT DeviceObject
,
622 IN PIRP OriginalRequest
,
623 IN UCHAR CommandLength
,
625 IN ULONG TransferDataLength
,
626 IN PUCHAR TransferData
,
629 PIRP_CONTEXT Context
;
630 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
631 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
633 PUCHAR MdlVirtualAddress
;
636 // first allocate irp context
638 Context
= USBSTOR_AllocateIrpContext();
644 return STATUS_INSUFFICIENT_RESOURCES
;
648 // get PDO device extension
650 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
653 // get FDO device extension
655 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
660 USBSTOR_BuildCBW((ULONG
)Context
->cbw
,
662 PDODeviceExtension
->LUN
,
667 DPRINT("CBW %p\n", Context
->cbw
);
668 DumpCBW((PUCHAR
)Context
->cbw
);
671 // now initialize the urb
673 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
674 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
675 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
679 USBD_TRANSFER_DIRECTION_OUT
,
683 // initialize rest of context
685 Context
->Irp
= OriginalRequest
;
686 Context
->TransferData
= TransferData
;
687 Context
->TransferDataLength
= TransferDataLength
;
688 Context
->FDODeviceExtension
= FDODeviceExtension
;
689 Context
->PDODeviceExtension
= PDODeviceExtension
;
690 Context
->RetryCount
= RetryCount
;
693 // is there transfer data
695 if (Context
->TransferDataLength
)
698 // check if the original request already does have an mdl associated
702 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
703 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
706 // Sanity check that the Mdl does describe the TransferData for read/write
708 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
710 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
713 // is there an offset
715 if (MdlVirtualAddress
!= Context
->TransferData
)
720 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, MmGetMdlByteCount(OriginalRequest
->MdlAddress
), FALSE
, FALSE
, NULL
);
721 if (!Context
->TransferBufferMDL
)
724 // failed to allocate MDL
726 return STATUS_INSUFFICIENT_RESOURCES
;
730 // now build the partial mdl
732 IoBuildPartialMdl(OriginalRequest
->MdlAddress
, Context
->TransferBufferMDL
, Context
->TransferData
, Context
->TransferDataLength
);
736 if (!Context
->TransferBufferMDL
)
739 // I/O paging request
741 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
747 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
749 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
750 if (!Context
->TransferBufferMDL
)
753 // failed to allocate MDL
755 return STATUS_INSUFFICIENT_RESOURCES
;
759 // build mdl for nonpaged pool
761 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
767 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
769 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
770 if (!Context
->TransferBufferMDL
)
773 // failed to allocate MDL
775 return STATUS_INSUFFICIENT_RESOURCES
;
779 // build mdl for nonpaged pool
781 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
786 // now allocate the request
788 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
791 FreeItem(Context
->cbw
);
793 return STATUS_INSUFFICIENT_RESOURCES
;
799 // mark orignal irp as pending
801 IoMarkIrpPending(OriginalRequest
);
807 USBSTOR_SendCBW(Context
, Irp
);
812 return STATUS_PENDING
;
816 USBSTOR_SendFormatCapacity(
817 IN PDEVICE_OBJECT DeviceObject
,
821 UFI_READ_FORMAT_CAPACITY Cmd
;
822 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
823 PIO_STACK_LOCATION IoStack
;
824 PSCSI_REQUEST_BLOCK Request
;
827 // get current stack location
829 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
832 // get PDO device extension
834 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
839 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
842 // initialize inquiry cmd
844 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_FORMAT_CAPACITY
));
845 Cmd
.Code
= SCSIOP_READ_FORMATTED_CAPACITY
;
846 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
847 Cmd
.AllocationLengthMsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) >> 8;
848 Cmd
.AllocationLengthLsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) & 0xFF;
851 // now send the request
853 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_FORMAT_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
858 IN PDEVICE_OBJECT DeviceObject
,
863 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
864 PIO_STACK_LOCATION IoStack
;
865 PSCSI_REQUEST_BLOCK Request
;
868 // get current stack location
870 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
875 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
878 // get PDO device extension
880 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
883 // initialize inquiry cmd
885 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
886 Cmd
.Code
= SCSIOP_INQUIRY
;
887 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
888 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
893 ASSERT(Request
->DataTransferLength
>= sizeof(UFI_INQUIRY_RESPONSE
));
896 // now send the request
898 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
902 USBSTOR_SendCapacity(
903 IN PDEVICE_OBJECT DeviceObject
,
907 UFI_CAPACITY_CMD Cmd
;
908 PUFI_CAPACITY_RESPONSE Response
;
909 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
912 // get PDO device extension
914 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
917 // allocate capacity response
919 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, PAGE_SIZE
);
925 return STATUS_INSUFFICIENT_RESOURCES
;
929 // initialize capacity cmd
931 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
932 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
933 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
936 // send request, response will be freed in completion routine
938 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
, RetryCount
);
942 USBSTOR_SendModeSense(
943 IN PDEVICE_OBJECT DeviceObject
,
953 PUFI_MODE_PARAMETER_HEADER Header
;
955 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
956 PIO_STACK_LOCATION IoStack
;
957 PSCSI_REQUEST_BLOCK Request
;
960 // get PDO device extension
962 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
967 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
970 // get current stack location
972 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
977 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
979 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
980 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
981 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
982 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
983 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
984 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
987 // start next request
989 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
991 return STATUS_SUCCESS
;
995 // get SCSI command data block
997 pCDB
= (PCDB
)Request
->Cdb
;
1000 // get PDO device extension
1002 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1005 // allocate sense response from non paged pool
1007 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
1013 return STATUS_INSUFFICIENT_RESOURCES
;
1022 // MODE_PAGE_ERROR_RECOVERY
1023 // MODE_PAGE_FLEXIBILE
1024 // MODE_PAGE_LUN_MAPPING
1025 // MODE_PAGE_FAULT_REPORTING
1026 // MODE_SENSE_RETURN_ALL
1029 // initialize mode sense cmd
1031 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
1032 Cmd
.Code
= SCSIOP_MODE_SENSE
;
1033 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1034 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
1035 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
1036 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
1038 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
1039 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
1042 // now send mode sense cmd
1044 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
1045 if (!NT_SUCCESS(Status
))
1048 // failed to send CBW
1050 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
1057 // now send data block response
1059 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
1060 if (!NT_SUCCESS(Status
))
1063 // failed to send CBW
1065 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
1071 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
1074 // TODO: build layout
1076 // first struct is the header
1077 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
1080 // MODE_PARAMETER_BLOCK
1088 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
1090 DPRINT1("------------------------\n");
1091 DPRINT1("CSW %p\n", &CSW
);
1092 DPRINT1("Signature %x\n", CSW
.Signature
);
1093 DPRINT1("Tag %x\n", CSW
.Tag
);
1094 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
1095 DPRINT1("Status %x\n", CSW
.Status
);
1098 // FIXME: handle error
1100 ASSERT(CSW
.Status
== 0);
1101 ASSERT(CSW
.DataResidue
== 0);
1104 // calculate transfer length
1106 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
1111 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
1116 FreeItem(OutControl
);
1131 USBSTOR_SendReadWrite(
1132 IN PDEVICE_OBJECT DeviceObject
,
1134 IN ULONG RetryCount
)
1136 UFI_READ_WRITE_CMD Cmd
;
1137 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1139 ULONG BlockCount
, Temp
;
1140 PIO_STACK_LOCATION IoStack
;
1141 PSCSI_REQUEST_BLOCK Request
;
1144 // get current stack location
1146 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1149 // get request block
1151 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1154 // get SCSI command data block
1156 pCDB
= (PCDB
)Request
->Cdb
;
1159 // get PDO device extension
1161 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1164 // informal debug print
1166 DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
1171 ASSERT(PDODeviceExtension
->BlockLength
);
1176 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
1179 // initialize read cmd
1181 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
1182 Cmd
.Code
= pCDB
->AsByte
[0];
1183 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1184 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
1185 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
1186 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
1187 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
1188 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
1189 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
1194 Temp
= (Cmd
.ContiguousLogicBlocksByte0
<< 8 | Cmd
.ContiguousLogicBlocksByte1
);
1195 ASSERT(NTOHL(Temp
== BlockCount
));
1197 DPRINT("USBSTOR_SendReadWrite BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
1202 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
1206 USBSTOR_SendTestUnit(
1207 IN PDEVICE_OBJECT DeviceObject
,
1209 IN ULONG RetryCount
)
1211 UFI_TEST_UNIT_CMD Cmd
;
1212 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1213 PIO_STACK_LOCATION IoStack
;
1214 PSCSI_REQUEST_BLOCK Request
;
1217 // get current stack location
1219 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1222 // get request block
1224 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1227 // no transfer length
1229 ASSERT(Request
->DataTransferLength
== 0);
1232 // get PDO device extension
1234 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1237 // initialize test unit cmd
1239 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
1240 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
1241 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
1246 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
, RetryCount
);
1250 USBSTOR_SendUnknownRequest(
1251 IN PDEVICE_OBJECT DeviceObject
,
1253 IN ULONG RetryCount
)
1255 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1256 PIO_STACK_LOCATION IoStack
;
1257 PSCSI_REQUEST_BLOCK Request
;
1258 UFI_UNKNOWN_CMD Cmd
;
1261 // get current stack location
1263 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1266 // get request block
1268 Request
= IoStack
->Parameters
.Others
.Argument1
;
1271 // get PDO device extension
1273 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1276 // check that we're sending to the right LUN
1278 ASSERT(Request
->Cdb
[1] == (PDODeviceExtension
->LUN
& MAX_LUN
));
1283 ASSERT(Request
->CdbLength
<= sizeof(UFI_UNKNOWN_CMD
));
1286 // initialize test unit cmd
1288 RtlCopyMemory(&Cmd
, Request
->Cdb
, Request
->CdbLength
);
1293 return USBSTOR_SendRequest(DeviceObject
, Irp
, Request
->CdbLength
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, Request
->DataBuffer
, RetryCount
);
1297 USBSTOR_HandleExecuteSCSI(
1298 IN PDEVICE_OBJECT DeviceObject
,
1300 IN ULONG RetryCount
)
1304 PIO_STACK_LOCATION IoStack
;
1305 PSCSI_REQUEST_BLOCK Request
;
1306 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
1309 // get PDO device extension
1311 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1316 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
1319 // get current stack location
1321 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1324 // get request block
1326 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
1329 // get SCSI command data block
1331 pCDB
= (PCDB
)Request
->Cdb
;
1333 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
1335 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
1340 ASSERT(Request
->DataBuffer
);
1342 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request
->DataTransferLength
);
1343 Status
= USBSTOR_SendCapacity(DeviceObject
, Irp
, RetryCount
);
1345 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
1347 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
1348 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
1349 ASSERT(Request
->DataBuffer
);
1352 // send mode sense command
1354 Status
= USBSTOR_SendModeSense(DeviceObject
, Irp
, RetryCount
);
1356 else if (pCDB
->AsByte
[0] == SCSIOP_READ_FORMATTED_CAPACITY
)
1358 DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request
->DataTransferLength
);
1361 // send read format capacity
1363 Status
= USBSTOR_SendFormatCapacity(DeviceObject
, Irp
, RetryCount
);
1365 else if (pCDB
->AsByte
[0] == SCSIOP_INQUIRY
)
1367 DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request
->DataTransferLength
);
1370 // send read format capacity
1372 Status
= USBSTOR_SendInquiry(DeviceObject
, Irp
, RetryCount
);
1374 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
1376 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
1379 // send read / write command
1381 Status
= USBSTOR_SendReadWrite(DeviceObject
, Irp
, RetryCount
);
1383 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
1385 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1388 // just complete the request
1390 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
1391 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1392 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
1393 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
1394 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1397 // start next request
1399 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
1401 return STATUS_SUCCESS
;
1403 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
1405 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1408 // send test unit command
1410 Status
= USBSTOR_SendTestUnit(DeviceObject
, Irp
, RetryCount
);
1414 // Unknown request. Simply forward
1415 DPRINT1("Forwarding unknown Operation Code %x\n", pCDB
->AsByte
[0]);
1416 Status
= USBSTOR_SendUnknownRequest(DeviceObject
, Irp
, RetryCount
);