2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
19 IN ULONG DataTransferLength
,
21 IN UCHAR CommandBlockLength
,
22 IN PUCHAR CommandBlock
,
25 ASSERT(CommandBlockLength
<= 16);
27 Control
->Signature
= CBW_SIGNATURE
;
29 Control
->DataTransferLength
= DataTransferLength
;
30 Control
->Flags
= (CommandBlock
[0] != SCSIOP_WRITE
) ? 0x80 : 0x00;
31 Control
->LUN
= (LUN
& MAX_LUN
);
32 Control
->CommandBlockLength
= CommandBlockLength
;
34 RtlCopyMemory(Control
->CommandBlock
, CommandBlock
, CommandBlockLength
);
36 return STATUS_SUCCESS
;
40 USBSTOR_AllocateIrpContext()
44 Context
= (PIRP_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(IRP_CONTEXT
));
50 Context
->cbw
= (PCBW
)AllocateItem(NonPagedPool
, 512);
64 if (Context
->csw
->Signature
!= CSW_SIGNATURE
)
66 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE
, Context
->csw
->Signature
);
70 if (Context
->csw
->Tag
!= (ULONG_PTR
)Context
->csw
)
72 DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", (ULONG_PTR
)Context
->csw
, Context
->csw
->Tag
);
76 if (Context
->csw
->Status
!= 0x00)
78 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context
->csw
->Status
);
86 USBSTOR_QueueWorkItem(
90 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData
;
92 ErrorHandlerWorkItemData
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ERRORHANDLER_WORKITEM_DATA
), USB_STOR_TAG
);
93 if (!ErrorHandlerWorkItemData
)
95 return STATUS_INSUFFICIENT_RESOURCES
;
98 // error handling started
99 Context
->FDODeviceExtension
->SrbErrorHandlingActive
= TRUE
;
101 // srb error handling finished
102 Context
->FDODeviceExtension
->TimerWorkQueueEnabled
= FALSE
;
104 // Initialize and queue the work item to handle the error
105 ExInitializeWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
,
106 ErrorHandlerWorkItemRoutine
,
107 ErrorHandlerWorkItemData
);
109 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
110 ErrorHandlerWorkItemData
->Context
= Context
;
111 ErrorHandlerWorkItemData
->Irp
= Irp
;
112 ErrorHandlerWorkItemData
->DeviceObject
= Context
->FDODeviceExtension
->FunctionalDeviceObject
;
114 DPRINT1("Queuing WorkItemROutine\n");
115 ExQueueWorkItem(&ErrorHandlerWorkItemData
->WorkQueueItem
, DelayedWorkQueue
);
116 return STATUS_MORE_PROCESSING_REQUIRED
;
119 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
123 USBSTOR_CSWCompletionRoutine(
124 PDEVICE_OBJECT DeviceObject
,
128 PIRP_CONTEXT Context
;
129 PIO_STACK_LOCATION IoStack
;
130 PSCSI_REQUEST_BLOCK Request
;
132 PREAD_CAPACITY_DATA_EX CapacityDataEx
;
133 PREAD_CAPACITY_DATA CapacityData
;
134 PUFI_CAPACITY_RESPONSE Response
;
137 Context
= (PIRP_CONTEXT
)Ctx
;
139 if (Context
->TransferBufferMDL
)
141 // is there an irp associated
144 // did we allocate the mdl
145 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
147 IoFreeMdl(Context
->TransferBufferMDL
);
152 IoFreeMdl(Context
->TransferBufferMDL
);
156 DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp
->IoStatus
.Status
);
158 if (!NT_SUCCESS(Irp
->IoStatus
.Information
))
160 if (Context
->ErrorIndex
== 0)
162 Context
->ErrorIndex
= 1;
164 // clear stall and resend cbw
165 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
166 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
167 return STATUS_MORE_PROCESSING_REQUIRED
;
170 // perform reset recovery
171 Context
->ErrorIndex
= 2;
173 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
174 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
175 return STATUS_MORE_PROCESSING_REQUIRED
;
178 if (!USBSTOR_IsCSWValid(Context
))
180 // perform reset recovery
181 Context
->ErrorIndex
= 2;
183 Status
= USBSTOR_QueueWorkItem(Context
, NULL
);
184 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
185 return STATUS_MORE_PROCESSING_REQUIRED
;
189 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
191 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
194 Status
= Irp
->IoStatus
.Status
;
196 pCDB
= (PCDB
)Request
->Cdb
;
197 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
199 // read capacity needs special work
200 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
203 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
206 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
207 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
209 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
212 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
215 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
216 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
217 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
222 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
225 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
226 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
227 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
230 FreeItem(Context
->TransferData
);
233 FreeItem(Context
->cbw
);
235 // FIXME: check status
236 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
237 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
239 // terminate current request
240 USBSTOR_QueueTerminateRequest(Context
->PDODeviceExtension
->LowerDeviceObject
, Context
->Irp
);
242 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
244 USBSTOR_QueueNextRequest(Context
->PDODeviceExtension
->LowerDeviceObject
);
248 return STATUS_MORE_PROCESSING_REQUIRED
;
253 PIRP_CONTEXT Context
,
256 PIO_STACK_LOCATION IoStack
;
258 IoStack
= IoGetNextIrpStackLocation(Irp
);
260 // now initialize the urb for sending the csw
261 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
262 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
263 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
267 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
270 // initialize stack location
271 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
272 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
273 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
274 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
275 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
277 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
279 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
282 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
286 USBSTOR_DataCompletionRoutine(
287 PDEVICE_OBJECT DeviceObject
,
291 PIRP_CONTEXT Context
;
295 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
297 Context
= (PIRP_CONTEXT
)Ctx
;
299 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
301 // clear stall and resend cbw
302 Context
->ErrorIndex
= 1;
303 Status
= USBSTOR_QueueWorkItem(Context
, Irp
);
304 ASSERT(Status
== STATUS_MORE_PROCESSING_REQUIRED
);
305 return STATUS_MORE_PROCESSING_REQUIRED
;
308 USBSTOR_SendCSW(Context
, Irp
);
310 return STATUS_MORE_PROCESSING_REQUIRED
;
313 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
317 USBSTOR_CBWCompletionRoutine(
318 PDEVICE_OBJECT DeviceObject
,
322 PIRP_CONTEXT Context
;
323 PIO_STACK_LOCATION IoStack
;
325 USBD_PIPE_HANDLE PipeHandle
;
327 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
329 Context
= (PIRP_CONTEXT
)Ctx
;
330 IoStack
= IoGetNextIrpStackLocation(Irp
);
332 // is there data to be submitted
333 if (Context
->TransferDataLength
)
336 Code
= Context
->cbw
->CommandBlock
[0];
338 if (Code
== SCSIOP_WRITE
)
340 // write request - use bulk out pipe
341 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
345 // default bulk in pipe
346 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
349 // now initialize the urb for sending data
350 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
351 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
354 Context
->TransferBufferMDL
,
355 Context
->TransferDataLength
,
356 ((Code
== SCSIOP_WRITE
) ? USBD_TRANSFER_DIRECTION_OUT
: (USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
)),
359 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
363 // now initialize the urb for sending the csw
364 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
365 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
366 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
370 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
373 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
376 // initialize stack location
377 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
378 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
379 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
380 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
381 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
383 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
385 return STATUS_MORE_PROCESSING_REQUIRED
;
392 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",
393 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,
394 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,
395 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,
402 PIRP_CONTEXT Context
,
405 PIO_STACK_LOCATION IoStack
;
407 IoStack
= IoGetNextIrpStackLocation(Irp
);
409 // initialize stack location
410 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
411 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
412 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
413 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
414 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
416 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
418 return IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
423 IN PDEVICE_OBJECT DeviceObject
,
424 IN PIRP OriginalRequest
,
425 IN UCHAR CommandLength
,
427 IN ULONG TransferDataLength
,
428 IN PUCHAR TransferData
,
431 PIRP_CONTEXT Context
;
432 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
433 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
435 PUCHAR MdlVirtualAddress
;
437 Context
= USBSTOR_AllocateIrpContext();
440 return STATUS_INSUFFICIENT_RESOURCES
;
443 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
444 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
446 USBSTOR_BuildCBW(PtrToUlong(Context
->cbw
),
448 PDODeviceExtension
->LUN
,
453 DPRINT("CBW %p\n", Context
->cbw
);
454 DumpCBW((PUCHAR
)Context
->cbw
);
456 // now initialize the urb
457 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
458 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
459 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
463 USBD_TRANSFER_DIRECTION_OUT
,
466 // initialize rest of context
467 Context
->Irp
= OriginalRequest
;
468 Context
->TransferData
= TransferData
;
469 Context
->TransferDataLength
= TransferDataLength
;
470 Context
->FDODeviceExtension
= FDODeviceExtension
;
471 Context
->PDODeviceExtension
= PDODeviceExtension
;
472 Context
->RetryCount
= RetryCount
;
474 // is there transfer data
475 if (Context
->TransferDataLength
)
477 // check if the original request already does have an mdl associated
480 if ((OriginalRequest
->MdlAddress
!= NULL
) &&
481 (Context
->TransferData
== NULL
|| Command
[0] == SCSIOP_READ
|| Command
[0] == SCSIOP_WRITE
))
483 // Sanity check that the Mdl does describe the TransferData for read/write
484 if (CommandLength
== UFI_READ_WRITE_CMD_LEN
)
486 MdlVirtualAddress
= MmGetMdlVirtualAddress(OriginalRequest
->MdlAddress
);
488 // is there an offset
489 if (MdlVirtualAddress
!= Context
->TransferData
)
492 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, MmGetMdlByteCount(OriginalRequest
->MdlAddress
), FALSE
, FALSE
, NULL
);
493 if (!Context
->TransferBufferMDL
)
495 FreeItem(Context
->cbw
);
497 return STATUS_INSUFFICIENT_RESOURCES
;
500 IoBuildPartialMdl(OriginalRequest
->MdlAddress
, Context
->TransferBufferMDL
, Context
->TransferData
, Context
->TransferDataLength
);
504 if (!Context
->TransferBufferMDL
)
506 // I/O paging request
507 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
512 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
513 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
514 if (!Context
->TransferBufferMDL
)
516 FreeItem(Context
->cbw
);
518 return STATUS_INSUFFICIENT_RESOURCES
;
521 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
526 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
527 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
528 if (!Context
->TransferBufferMDL
)
530 FreeItem(Context
->cbw
);
532 return STATUS_INSUFFICIENT_RESOURCES
;
535 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
539 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
542 FreeItem(Context
->cbw
);
544 return STATUS_INSUFFICIENT_RESOURCES
;
549 IoMarkIrpPending(OriginalRequest
);
552 USBSTOR_SendCBW(Context
, Irp
);
554 return STATUS_PENDING
;
558 USBSTOR_SendFormatCapacity(
559 IN PDEVICE_OBJECT DeviceObject
,
563 UFI_READ_FORMAT_CAPACITY Cmd
;
564 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
565 PIO_STACK_LOCATION IoStack
;
566 PSCSI_REQUEST_BLOCK Request
;
568 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
569 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
570 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
572 // initialize inquiry cmd
573 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_FORMAT_CAPACITY
));
574 Cmd
.Code
= SCSIOP_READ_FORMATTED_CAPACITY
;
575 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
576 Cmd
.AllocationLengthMsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) >> 8;
577 Cmd
.AllocationLengthLsb
= HTONS(Request
->DataTransferLength
& 0xFFFF) & 0xFF;
579 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_FORMAT_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
584 IN PDEVICE_OBJECT DeviceObject
,
589 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
590 PIO_STACK_LOCATION IoStack
;
591 PSCSI_REQUEST_BLOCK Request
;
593 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
594 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
595 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
597 // initialize inquiry cmd
598 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
599 Cmd
.Code
= SCSIOP_INQUIRY
;
600 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
601 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
603 ASSERT(Request
->DataTransferLength
>= sizeof(UFI_INQUIRY_RESPONSE
));
605 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
609 USBSTOR_SendCapacity(
610 IN PDEVICE_OBJECT DeviceObject
,
614 UFI_CAPACITY_CMD Cmd
;
615 PUFI_CAPACITY_RESPONSE Response
;
616 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
618 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
620 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, PAGE_SIZE
);
623 return STATUS_INSUFFICIENT_RESOURCES
;
626 // initialize capacity cmd
627 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
628 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
629 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
631 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_CAPACITY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
, RetryCount
);
635 USBSTOR_SendModeSense(
636 IN PDEVICE_OBJECT DeviceObject
,
646 PUFI_MODE_PARAMETER_HEADER Header
;
648 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
649 PIO_STACK_LOCATION IoStack
;
650 PSCSI_REQUEST_BLOCK Request
;
652 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
653 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
655 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
656 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
658 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
659 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
660 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
661 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
662 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
663 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
665 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
667 return STATUS_SUCCESS
;
671 // get SCSI command data block
673 pCDB
= (PCDB
)Request
->Cdb
;
676 // get PDO device extension
678 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
681 // allocate sense response from non paged pool
683 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
689 return STATUS_INSUFFICIENT_RESOURCES
;
698 // MODE_PAGE_ERROR_RECOVERY
699 // MODE_PAGE_FLEXIBILE
700 // MODE_PAGE_LUN_MAPPING
701 // MODE_PAGE_FAULT_REPORTING
702 // MODE_SENSE_RETURN_ALL
705 // initialize mode sense cmd
707 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
708 Cmd
.Code
= SCSIOP_MODE_SENSE
;
709 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
710 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
711 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
712 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
714 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
715 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
718 // now send mode sense cmd
720 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
721 if (!NT_SUCCESS(Status
))
724 // failed to send CBW
726 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
733 // now send data block response
735 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
736 if (!NT_SUCCESS(Status
))
739 // failed to send CBW
741 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
747 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
750 // TODO: build layout
752 // first struct is the header
753 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
756 // MODE_PARAMETER_BLOCK
764 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
766 DPRINT1("------------------------\n");
767 DPRINT1("CSW %p\n", &CSW
);
768 DPRINT1("Signature %x\n", CSW
.Signature
);
769 DPRINT1("Tag %x\n", CSW
.Tag
);
770 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
771 DPRINT1("Status %x\n", CSW
.Status
);
774 // FIXME: handle error
776 ASSERT(CSW
.Status
== 0);
777 ASSERT(CSW
.DataResidue
== 0);
780 // calculate transfer length
782 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
787 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
792 FreeItem(OutControl
);
807 USBSTOR_SendReadWrite(
808 IN PDEVICE_OBJECT DeviceObject
,
812 UFI_READ_WRITE_CMD Cmd
;
813 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
815 ULONG BlockCount
, Temp
;
816 PIO_STACK_LOCATION IoStack
;
817 PSCSI_REQUEST_BLOCK Request
;
819 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
820 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
822 pCDB
= (PCDB
)Request
->Cdb
;
824 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
826 DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
828 ASSERT(PDODeviceExtension
->BlockLength
);
830 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
832 // initialize read cmd
833 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_WRITE_CMD
));
834 Cmd
.Code
= pCDB
->AsByte
[0];
835 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
836 Cmd
.ContiguousLogicBlocksByte0
= pCDB
->CDB10
.TransferBlocksMsb
;
837 Cmd
.ContiguousLogicBlocksByte1
= pCDB
->CDB10
.TransferBlocksLsb
;
838 Cmd
.LogicalBlockByte0
= pCDB
->CDB10
.LogicalBlockByte0
;
839 Cmd
.LogicalBlockByte1
= pCDB
->CDB10
.LogicalBlockByte1
;
840 Cmd
.LogicalBlockByte2
= pCDB
->CDB10
.LogicalBlockByte2
;
841 Cmd
.LogicalBlockByte3
= pCDB
->CDB10
.LogicalBlockByte3
;
843 Temp
= (Cmd
.ContiguousLogicBlocksByte0
<< 8 | Cmd
.ContiguousLogicBlocksByte1
);
844 ASSERT(Temp
== BlockCount
);
846 DPRINT("USBSTOR_SendReadWrite BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd
.LogicalBlockByte0
, Cmd
.LogicalBlockByte1
, Cmd
.LogicalBlockByte2
, Cmd
.LogicalBlockByte3
, BlockCount
, PDODeviceExtension
->BlockLength
);
848 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_READ_WRITE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
, RetryCount
);
852 USBSTOR_SendTestUnit(
853 IN PDEVICE_OBJECT DeviceObject
,
857 UFI_TEST_UNIT_CMD Cmd
;
858 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
859 PIO_STACK_LOCATION IoStack
;
860 PSCSI_REQUEST_BLOCK Request
;
862 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
863 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
865 ASSERT(Request
->DataTransferLength
== 0);
867 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
869 // initialize test unit cmd
870 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
871 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
872 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
874 return USBSTOR_SendRequest(DeviceObject
, Irp
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
, RetryCount
);
878 USBSTOR_SendUnknownRequest(
879 IN PDEVICE_OBJECT DeviceObject
,
883 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
884 PIO_STACK_LOCATION IoStack
;
885 PSCSI_REQUEST_BLOCK Request
;
888 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
889 Request
= IoStack
->Parameters
.Others
.Argument1
;
890 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
892 // check that we're sending to the right LUN
893 ASSERT(Request
->Cdb
[1] == (PDODeviceExtension
->LUN
& MAX_LUN
));
894 ASSERT(Request
->CdbLength
<= sizeof(UFI_UNKNOWN_CMD
));
896 RtlCopyMemory(&Cmd
, Request
->Cdb
, Request
->CdbLength
);
898 return USBSTOR_SendRequest(DeviceObject
, Irp
, Request
->CdbLength
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, Request
->DataBuffer
, RetryCount
);
902 USBSTOR_HandleExecuteSCSI(
903 IN PDEVICE_OBJECT DeviceObject
,
909 PIO_STACK_LOCATION IoStack
;
910 PSCSI_REQUEST_BLOCK Request
;
911 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
913 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
914 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
916 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
917 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
918 pCDB
= (PCDB
)Request
->Cdb
;
920 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB
->AsByte
[0]);
922 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
924 ASSERT(Request
->DataBuffer
);
926 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request
->DataTransferLength
);
927 Status
= USBSTOR_SendCapacity(DeviceObject
, Irp
, RetryCount
);
929 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_MODE_SENSE
)
931 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request
->DataTransferLength
);
932 ASSERT(pCDB
->MODE_SENSE
.AllocationLength
== Request
->DataTransferLength
);
933 ASSERT(Request
->DataBuffer
);
935 Status
= USBSTOR_SendModeSense(DeviceObject
, Irp
, RetryCount
);
937 else if (pCDB
->AsByte
[0] == SCSIOP_READ_FORMATTED_CAPACITY
)
939 DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request
->DataTransferLength
);
941 Status
= USBSTOR_SendFormatCapacity(DeviceObject
, Irp
, RetryCount
);
943 else if (pCDB
->AsByte
[0] == SCSIOP_INQUIRY
)
945 DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request
->DataTransferLength
);
947 Status
= USBSTOR_SendInquiry(DeviceObject
, Irp
, RetryCount
);
949 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_READ
|| pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_WRITE
)
951 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request
->DataTransferLength
);
953 Status
= USBSTOR_SendReadWrite(DeviceObject
, Irp
, RetryCount
);
955 else if (pCDB
->AsByte
[0] == SCSIOP_MEDIUM_REMOVAL
)
957 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
959 // just complete the request
960 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
961 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
962 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
963 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
964 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
966 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
968 return STATUS_SUCCESS
;
970 else if (pCDB
->MODE_SENSE
.OperationCode
== SCSIOP_TEST_UNIT_READY
)
972 DPRINT("SCSIOP_TEST_UNIT_READY\n");
974 Status
= USBSTOR_SendTestUnit(DeviceObject
, Irp
, RetryCount
);
978 // Unknown request. Simply forward
979 DPRINT1("Forwarding unknown Operation Code %x\n", pCDB
->AsByte
[0]);
980 Status
= USBSTOR_SendUnknownRequest(DeviceObject
, Irp
, RetryCount
);