2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/pdo.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
17 IN ULONG DataTransferLength
,
19 IN UCHAR CommandBlockLength
,
20 IN PUCHAR CommandBlock
,
26 ASSERT(CommandBlockLength
<= 16);
31 Control
->Signature
= CBW_SIGNATURE
;
33 Control
->DataTransferLength
= DataTransferLength
;
34 Control
->Flags
= 0x80;
35 Control
->LUN
= (LUN
& MAX_LUN
);
36 Control
->CommandBlockLength
= CommandBlockLength
;
41 RtlCopyMemory(Control
->CommandBlock
, CommandBlock
, CommandBlockLength
);
46 return STATUS_SUCCESS
;
50 USBSTOR_AllocateIrpContext()
55 // allocate irp context
57 Context
= (PIRP_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(IRP_CONTEXT
));
69 Context
->cbw
= (PCBW
)AllocateItem(NonPagedPool
, 512);
89 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
93 USBSTOR_CSWCompletionRoutine(
94 PDEVICE_OBJECT DeviceObject
,
99 PIO_STACK_LOCATION IoStack
;
100 PSCSI_REQUEST_BLOCK Request
;
102 PREAD_CAPACITY_DATA_EX CapacityDataEx
;
103 PREAD_CAPACITY_DATA CapacityData
;
104 PUFI_CAPACITY_RESPONSE Response
;
106 DPRINT1("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
111 Context
= (PIRP_CONTEXT
)Ctx
;
116 if (Context
->TransferBufferMDL
)
119 // is there an irp associated
124 // did we allocate the mdl
126 if (Context
->TransferBufferMDL
!= Context
->Irp
->MdlAddress
)
131 IoFreeMdl(Context
->TransferBufferMDL
);
139 IoFreeMdl(Context
->TransferBufferMDL
);
146 // get current stack location
148 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
153 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
157 // FIXME: check status
159 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
162 // get SCSI command data block
164 pCDB
= (PCDB
)Request
->Cdb
;
167 // read capacity needs special work
169 if (pCDB
->AsByte
[0] == SCSIOP_READ_CAPACITY
)
174 Response
= (PUFI_CAPACITY_RESPONSE
)Context
->TransferData
;
179 Context
->PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
180 Context
->PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
182 if (Request
->DataTransferLength
== sizeof(READ_CAPACITY_DATA_EX
))
187 CapacityDataEx
= (PREAD_CAPACITY_DATA_EX
)Request
->DataBuffer
;
192 CapacityDataEx
->BytesPerBlock
= Response
->BlockLength
;
193 CapacityDataEx
->LogicalBlockAddress
.QuadPart
= Response
->LastLogicalBlockAddress
;
194 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA_EX
);
201 CapacityData
= (PREAD_CAPACITY_DATA
)Request
->DataBuffer
;
206 CapacityData
->BytesPerBlock
= Response
->BlockLength
;
207 CapacityData
->LogicalBlockAddress
= Response
->LastLogicalBlockAddress
;
208 Irp
->IoStatus
.Information
= sizeof(READ_CAPACITY_DATA
);
214 FreeItem(Context
->TransferData
);
221 FreeItem(Context
->cbw
);
227 // FIXME: check status
229 Context
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
230 Context
->Irp
->IoStatus
.Information
= Context
->TransferDataLength
;
235 IoCompleteRequest(Context
->Irp
, IO_NO_INCREMENT
);
243 KeSetEvent(Context
->Event
, 0, FALSE
);
255 return STATUS_MORE_PROCESSING_REQUIRED
;
261 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
265 USBSTOR_DataCompletionRoutine(
266 PDEVICE_OBJECT DeviceObject
,
270 PIRP_CONTEXT Context
;
271 PIO_STACK_LOCATION IoStack
;
273 DPRINT1("USBSTOR_DataCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
278 Context
= (PIRP_CONTEXT
)Ctx
;
281 // get next stack location
284 IoStack
= IoGetNextIrpStackLocation(Irp
);
287 // now initialize the urb for sending the csw
289 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
290 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
291 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
295 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
299 // initialize stack location
301 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
302 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
303 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
304 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
305 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
309 // setup completion routine
311 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
316 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
318 return STATUS_MORE_PROCESSING_REQUIRED
;
324 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
328 USBSTOR_CBWCompletionRoutine(
329 PDEVICE_OBJECT DeviceObject
,
333 PIRP_CONTEXT Context
;
334 PIO_STACK_LOCATION IoStack
;
336 DPRINT1("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p\n", Irp
, Ctx
);
341 Context
= (PIRP_CONTEXT
)Ctx
;
344 // get next stack location
346 IoStack
= IoGetNextIrpStackLocation(Irp
);
349 // is there data to be submitted
351 if (Context
->TransferDataLength
)
354 // now initialize the urb for sending data
357 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
358 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
359 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
361 Context
->TransferBufferMDL
,
362 Context
->TransferDataLength
,
363 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
367 // setup completion routine
369 IoSetCompletionRoutine(Irp
, USBSTOR_DataCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
374 // now initialize the urb for sending the csw
377 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
378 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
379 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
383 USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
,
387 // setup completion routine
389 IoSetCompletionRoutine(Irp
, USBSTOR_CSWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
393 // initialize stack location
395 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
396 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
397 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
398 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
399 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
404 IoCallDriver(Context
->FDODeviceExtension
->LowerDeviceObject
, Irp
);
406 return STATUS_MORE_PROCESSING_REQUIRED
;
411 IN PDEVICE_OBJECT DeviceObject
,
412 IN PIRP OriginalRequest
,
413 IN OPTIONAL PKEVENT Event
,
414 IN ULONG CommandLength
,
416 IN ULONG TransferDataLength
,
417 IN PUCHAR TransferData
)
419 PIRP_CONTEXT Context
;
420 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
421 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
423 PIO_STACK_LOCATION IoStack
;
426 // first allocate irp context
428 Context
= USBSTOR_AllocateIrpContext();
434 return STATUS_INSUFFICIENT_RESOURCES
;
438 // get PDO device extension
440 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
443 // get FDO device extension
445 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
450 USBSTOR_BuildCBW(0xDEADDEAD, // FIXME tag
452 PDODeviceExtension
->LUN
,
458 // now initialize the urb
460 UsbBuildInterruptOrBulkTransferRequest(&Context
->Urb
,
461 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
),
462 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
466 USBD_TRANSFER_DIRECTION_OUT
| USBD_SHORT_TRANSFER_OK
,
470 // initialize rest of context
472 Context
->Irp
= OriginalRequest
;
473 Context
->TransferData
= TransferData
;
474 Context
->TransferDataLength
= TransferDataLength
;
475 Context
->FDODeviceExtension
= FDODeviceExtension
;
476 Context
->PDODeviceExtension
= PDODeviceExtension
;
477 Context
->Event
= Event
;
480 // is there transfer data
482 if (Context
->TransferDataLength
)
485 // check if the original request already does not have an mdl associated
489 if (OriginalRequest
->MdlAddress
!= NULL
&& Context
->TransferData
== NULL
)
492 // I/O paging request
494 Context
->TransferBufferMDL
= OriginalRequest
->MdlAddress
;
499 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
501 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
502 if (!Context
->TransferBufferMDL
)
505 // failed to allocate MDL
507 return STATUS_INSUFFICIENT_RESOURCES
;
515 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
517 Context
->TransferBufferMDL
= IoAllocateMdl(Context
->TransferData
, Context
->TransferDataLength
, FALSE
, FALSE
, NULL
);
518 if (!Context
->TransferBufferMDL
)
521 // failed to allocate MDL
523 return STATUS_INSUFFICIENT_RESOURCES
;
528 // build mdl for nonpaged pool
530 MmBuildMdlForNonPagedPool(Context
->TransferBufferMDL
);
534 // now allocate the request
536 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
539 FreeItem(Context
->cbw
);
541 return STATUS_INSUFFICIENT_RESOURCES
;
545 // get next stack location
547 IoStack
= IoGetNextIrpStackLocation(Irp
);
550 // initialize stack location
552 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
553 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
554 IoStack
->Parameters
.Others
.Argument1
= (PVOID
)&Context
->Urb
;
555 IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
= Context
->Urb
.UrbHeader
.Length
;
556 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
559 // setup completion routine
561 IoSetCompletionRoutine(Irp
, USBSTOR_CBWCompletionRoutine
, Context
, TRUE
, TRUE
, TRUE
);
566 // mark orignal irp as pending
568 IoMarkIrpPending(OriginalRequest
);
574 IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
579 return STATUS_PENDING
;
583 USBSTOR_SendInquiryCmd(
584 IN PDEVICE_OBJECT DeviceObject
)
589 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
590 PUFI_INQUIRY_RESPONSE Response
;
594 // allocate inquiry response
596 Response
= AllocateItem(NonPagedPool
, PAGE_SIZE
);
602 return STATUS_INSUFFICIENT_RESOURCES
;
606 // get PDO device extension
608 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
611 // initialize inquiry cmd
613 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
614 Cmd
.Code
= SCSIOP_INQUIRY
;
615 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
616 Cmd
.AllocationLength
= sizeof(UFI_INQUIRY_RESPONSE
);
621 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
624 // now send the request
626 Status
= USBSTOR_SendRequest(DeviceObject
, NULL
, &Event
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_INQUIRY_RESPONSE
), (PUCHAR
)Response
);
629 // wait for the action to complete
631 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
633 DPRINT1("Response %p\n", Response
);
634 DPRINT1("DeviceType %x\n", Response
->DeviceType
);
635 DPRINT1("RMB %x\n", Response
->RMB
);
636 DPRINT1("Version %x\n", Response
->Version
);
637 DPRINT1("Format %x\n", Response
->Format
);
638 DPRINT1("Length %x\n", Response
->Length
);
639 DPRINT1("Reserved %x\n", Response
->Reserved
);
640 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]);
641 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],
642 Response
->Product
[4], Response
->Product
[5], Response
->Product
[6], Response
->Product
[7],
643 Response
->Product
[8], Response
->Product
[9], Response
->Product
[10], Response
->Product
[11],
644 Response
->Product
[12], Response
->Product
[13], Response
->Product
[14], Response
->Product
[15]);
646 DPRINT1("Revision %c%c%c%c\n", Response
->Revision
[0], Response
->Revision
[1], Response
->Revision
[2], Response
->Revision
[3]);
649 // store inquiry data
651 PDODeviceExtension
->InquiryData
= (PVOID
)Response
;
660 USBSTOR_SendCapacityCmd(
661 IN PDEVICE_OBJECT DeviceObject
,
664 UFI_CAPACITY_CMD Cmd
;
665 PUFI_CAPACITY_RESPONSE Response
;
666 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
669 // get PDO device extension
671 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
674 // allocate capacity response
676 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, sizeof(UFI_CAPACITY_RESPONSE
));
682 return STATUS_INSUFFICIENT_RESOURCES
;
686 // initialize capacity cmd
688 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
689 Cmd
.Code
= SCSIOP_READ_CAPACITY
;
690 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
693 // send request, response will be freed in completion routine
695 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_INQUIRY_CMD_LEN
, (PUCHAR
)&Cmd
, sizeof(UFI_CAPACITY_RESPONSE
), (PUCHAR
)Response
);
699 USBSTOR_SendModeSenseCmd(
700 IN PDEVICE_OBJECT DeviceObject
,
706 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
709 PUFI_MODE_PARAMETER_HEADER Header
;
711 PIO_STACK_LOCATION IoStack
;
712 PSCSI_REQUEST_BLOCK Request
;
715 // get current stack location
717 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
722 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
724 RtlZeroMemory(Request
->DataBuffer
, Request
->DataTransferLength
);
725 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
726 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
727 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
728 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
730 return STATUS_SUCCESS
;
734 // get SCSI command data block
736 pCDB
= (PCDB
)Request
->Cdb
;
739 // get PDO device extension
741 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
744 // allocate sense response from non paged pool
746 Response
= (PUFI_CAPACITY_RESPONSE
)AllocateItem(NonPagedPool
, Request
->DataTransferLength
);
752 return STATUS_INSUFFICIENT_RESOURCES
;
761 // MODE_PAGE_ERROR_RECOVERY
762 // MODE_PAGE_FLEXIBILE
763 // MODE_PAGE_LUN_MAPPING
764 // MODE_PAGE_FAULT_REPORTING
765 // MODE_SENSE_RETURN_ALL
768 // initialize mode sense cmd
770 RtlZeroMemory(&Cmd
, sizeof(UFI_INQUIRY_CMD
));
771 Cmd
.Code
= SCSIOP_MODE_SENSE
;
772 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
773 Cmd
.PageCode
= pCDB
->MODE_SENSE
.PageCode
;
774 Cmd
.PC
= pCDB
->MODE_SENSE
.Pc
;
775 Cmd
.AllocationLength
= HTONS(pCDB
->MODE_SENSE
.AllocationLength
);
777 DPRINT1("PageCode %x\n", pCDB
->MODE_SENSE
.PageCode
);
778 DPRINT1("PC %x\n", pCDB
->MODE_SENSE
.Pc
);
781 // now send mode sense cmd
783 Status
= USBSTOR_SendCBW(DeviceObject
, UFI_SENSE_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, &OutControl
);
784 if (!NT_SUCCESS(Status
))
787 // failed to send CBW
789 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status
);
796 // now send data block response
798 Status
= USBSTOR_SendData(DeviceObject
, Request
->DataTransferLength
, Response
);
799 if (!NT_SUCCESS(Status
))
802 // failed to send CBW
804 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status
);
810 Header
= (PUFI_MODE_PARAMETER_HEADER
)Response
;
813 // TODO: build layout
815 // first struct is the header
816 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
819 // MODE_PARAMETER_BLOCK
827 Status
= USBSTOR_SendCSW(DeviceObject
, OutControl
, 512, &CSW
);
829 DPRINT1("------------------------\n");
830 DPRINT1("CSW %p\n", &CSW
);
831 DPRINT1("Signature %x\n", CSW
.Signature
);
832 DPRINT1("Tag %x\n", CSW
.Tag
);
833 DPRINT1("DataResidue %x\n", CSW
.DataResidue
);
834 DPRINT1("Status %x\n", CSW
.Status
);
837 // FIXME: handle error
839 ASSERT(CSW
.Status
== 0);
840 ASSERT(CSW
.DataResidue
== 0);
843 // calculate transfer length
845 *TransferBufferLength
= Request
->DataTransferLength
- CSW
.DataResidue
;
850 RtlCopyMemory(Request
->DataBuffer
, Response
, *TransferBufferLength
);
855 FreeItem(OutControl
);
871 IN PDEVICE_OBJECT DeviceObject
,
876 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
879 PIO_STACK_LOCATION IoStack
;
880 PSCSI_REQUEST_BLOCK Request
;
884 // get current stack location
886 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
891 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
894 // get SCSI command data block
896 pCDB
= (PCDB
)Request
->Cdb
;
899 // get PDO device extension
901 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
904 // informal debug print
906 DPRINT1("USBSTOR_SendReadCmd DataTransferLength %x, BlockLength %x\n", Request
->DataTransferLength
, PDODeviceExtension
->BlockLength
);
911 BlockCount
= Request
->DataTransferLength
/ PDODeviceExtension
->BlockLength
;
914 // initialize read cmd
916 RtlZeroMemory(&Cmd
, sizeof(UFI_READ_CMD
));
917 Cmd
.Code
= SCSIOP_READ
;
918 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
919 Cmd
.ContiguousLogicBlocks
= _byteswap_ushort(BlockCount
);
921 RtlCopyMemory(&Cmd
.LogicalBlockAddress
, pCDB
->READ12
.LogicalBlock
, sizeof(UCHAR
) * 4);
923 DPRINT1("BlockAddress %lu BlockCount %lu BlockLength %lu\n", NTOHL(Cmd
.LogicalBlockAddress
), BlockCount
, PDODeviceExtension
->BlockLength
);
928 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_READ_CMD_LEN
, (PUCHAR
)&Cmd
, Request
->DataTransferLength
, (PUCHAR
)Request
->DataBuffer
);
932 USBSTOR_SendTestUnitCmd(
933 IN PDEVICE_OBJECT DeviceObject
,
936 UFI_TEST_UNIT_CMD Cmd
;
937 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
938 PIO_STACK_LOCATION IoStack
;
939 PSCSI_REQUEST_BLOCK Request
;
942 // get current stack location
944 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
949 Request
= (PSCSI_REQUEST_BLOCK
)IoStack
->Parameters
.Others
.Argument1
;
952 // no transfer length
954 ASSERT(Request
->DataTransferLength
== 0);
957 // get PDO device extension
959 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
962 // initialize test unit cmd
964 RtlZeroMemory(&Cmd
, sizeof(UFI_TEST_UNIT_CMD
));
965 Cmd
.Code
= SCSIOP_TEST_UNIT_READY
;
966 Cmd
.LUN
= (PDODeviceExtension
->LUN
& MAX_LUN
);
971 return USBSTOR_SendRequest(DeviceObject
, Irp
, NULL
, UFI_TEST_UNIT_CMD_LEN
, (PUCHAR
)&Cmd
, 0, NULL
);