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)
9 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
20 USBSTOR_SrbStatusToNtStatus(
21 IN PSCSI_REQUEST_BLOCK Srb
)
25 SrbStatus
= SRB_STATUS(Srb
->SrbStatus
);
29 case SRB_STATUS_SUCCESS
:
30 return STATUS_SUCCESS
;
32 case SRB_STATUS_DATA_OVERRUN
:
33 return STATUS_BUFFER_OVERFLOW
;
35 case SRB_STATUS_BAD_FUNCTION
:
36 case SRB_STATUS_BAD_SRB_BLOCK_LENGTH
:
37 return STATUS_INVALID_DEVICE_REQUEST
;
39 case SRB_STATUS_INVALID_LUN
:
40 case SRB_STATUS_INVALID_TARGET_ID
:
41 case SRB_STATUS_NO_HBA
:
42 case SRB_STATUS_NO_DEVICE
:
43 return STATUS_DEVICE_DOES_NOT_EXIST
;
45 case SRB_STATUS_TIMEOUT
:
46 return STATUS_IO_TIMEOUT
;
48 case SRB_STATUS_BUS_RESET
:
49 case SRB_STATUS_COMMAND_TIMEOUT
:
50 case SRB_STATUS_SELECTION_TIMEOUT
:
51 return STATUS_DEVICE_NOT_CONNECTED
;
54 return STATUS_IO_DEVICE_ERROR
;
60 USBSTOR_IssueBulkOrInterruptRequest(
61 IN PFDO_DEVICE_EXTENSION FDODeviceExtension
,
63 IN USBD_PIPE_HANDLE PipeHandle
,
64 IN ULONG TransferFlags
,
65 IN ULONG TransferBufferLength
,
66 IN PVOID TransferBuffer
,
67 IN PMDL TransferBufferMDL
,
68 IN PIO_COMPLETION_ROUTINE CompletionRoutine
,
69 IN PIRP_CONTEXT Context
)
71 PIO_STACK_LOCATION NextStack
;
73 RtlZeroMemory(&Context
->Urb
, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
));
75 Context
->Urb
.UrbHeader
.Length
= sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER
);
76 Context
->Urb
.UrbHeader
.Function
= URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
;
78 Context
->Urb
.UrbBulkOrInterruptTransfer
.PipeHandle
= PipeHandle
;
79 Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferFlags
= TransferFlags
;
80 Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferLength
= TransferBufferLength
;
81 Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBuffer
= TransferBuffer
;
82 Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferMDL
= TransferBufferMDL
;
84 NextStack
= IoGetNextIrpStackLocation(Irp
);
85 NextStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
86 NextStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
87 NextStack
->Parameters
.Others
.Argument1
= &Context
->Urb
;
89 IoSetCompletionRoutine(Irp
,
96 return IoCallDriver(FDODeviceExtension
->LowerDeviceObject
, Irp
);
102 PIRP_CONTEXT Context
)
104 if (Context
->csw
.Signature
!= CSW_SIGNATURE
)
106 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE
, Context
->csw
.Signature
);
110 if (Context
->csw
.Tag
!= PtrToUlong(&Context
->csw
))
112 DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", PtrToUlong(&Context
->csw
), Context
->csw
.Tag
);
121 USBSTOR_IssueRequestSense(
122 IN PFDO_DEVICE_EXTENSION FDODeviceExtension
,
124 IN PIRP_CONTEXT Context
);
126 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine
;
130 USBSTOR_CSWCompletionRoutine(
131 PDEVICE_OBJECT DeviceObject
,
135 PIRP_CONTEXT Context
;
136 PIO_STACK_LOCATION IoStack
;
137 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
138 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
139 PSCSI_REQUEST_BLOCK Request
;
140 PUFI_CAPACITY_RESPONSE Response
;
142 Context
= (PIRP_CONTEXT
)Ctx
;
144 DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
146 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
147 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
148 FDODeviceExtension
= Context
->FDODeviceExtension
;
149 Request
= IoStack
->Parameters
.Scsi
.Srb
;
152 // first check for Irp errors
153 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
155 if (USBD_STATUS(Context
->Urb
.UrbHeader
.Status
) == USBD_STATUS(USBD_STATUS_STALL_PID
))
157 if (Context
->StallRetryCount
< 2)
159 ++Context
->StallRetryCount
;
161 // clear stall and resend cbw
162 USBSTOR_QueueResetPipe(FDODeviceExtension
, Context
);
164 return STATUS_MORE_PROCESSING_REQUIRED
;
169 DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context
->Urb
.UrbHeader
.Status
);
175 // now check the CSW packet validity
176 if (!USBSTOR_IsCSWValid(Context
) || Context
->csw
.Status
== CSW_STATUS_PHASE_ERROR
)
181 // finally check for CSW errors
182 if (Context
->csw
.Status
== CSW_STATUS_COMMAND_PASSED
)
184 // should happen only when a sense request was sent
185 if (Request
!= FDODeviceExtension
->ActiveSrb
)
187 ASSERT(IoStack
->Parameters
.Scsi
.Srb
== &Context
->SenseSrb
);
188 FDODeviceExtension
->ActiveSrb
->SenseInfoBufferLength
= Request
->DataTransferLength
;
189 Request
= FDODeviceExtension
->ActiveSrb
;
190 IoStack
->Parameters
.Scsi
.Srb
= Request
;
191 Request
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
194 // read capacity needs special work
195 if (Request
->Cdb
[0] == SCSIOP_READ_CAPACITY
)
198 Response
= (PUFI_CAPACITY_RESPONSE
)Request
->DataBuffer
;
201 PDODeviceExtension
->BlockLength
= NTOHL(Response
->BlockLength
);
202 PDODeviceExtension
->LastLogicBlockAddress
= NTOHL(Response
->LastLogicalBlockAddress
);
205 Irp
->IoStatus
.Status
= USBSTOR_SrbStatusToNtStatus(Request
);
207 else if (Context
->csw
.Status
== CSW_STATUS_COMMAND_FAILED
)
209 // the command is correct but with failed status - issue request sense
210 DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n");
212 ASSERT(FDODeviceExtension
->ActiveSrb
== Request
);
214 // setting a generic error status, additional information
215 // should be read by higher-level driver from SenseInfoBuffer
216 Request
->SrbStatus
= SRB_STATUS_ERROR
;
217 Request
->ScsiStatus
= 2;
218 Request
->DataTransferLength
= 0;
220 DPRINT("Flags: %x SBL: %x, buf: %p\n", Request
->SrbFlags
, Request
->SenseInfoBufferLength
, Request
->SenseInfoBuffer
);
222 if (!(Request
->SrbFlags
& SRB_FLAGS_DISABLE_AUTOSENSE
) &&
223 Request
->SenseInfoBufferLength
&&
224 Request
->SenseInfoBuffer
)
226 USBSTOR_IssueRequestSense(FDODeviceExtension
, Irp
, Context
);
227 return STATUS_MORE_PROCESSING_REQUIRED
;
230 Irp
->IoStatus
.Status
= STATUS_IO_DEVICE_ERROR
;
233 Irp
->IoStatus
.Information
= Request
->DataTransferLength
;
235 // terminate current request
236 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
237 USBSTOR_QueueNextRequest(PDODeviceExtension
->LowerDeviceObject
);
239 ExFreePoolWithTag(Context
, USB_STOR_TAG
);
240 return STATUS_CONTINUE_COMPLETION
;
244 Request
= FDODeviceExtension
->ActiveSrb
;
245 IoStack
->Parameters
.Scsi
.Srb
= Request
;
246 Irp
->IoStatus
.Information
= 0;
247 Irp
->IoStatus
.Status
= STATUS_IO_DEVICE_ERROR
;
248 Request
->SrbStatus
= SRB_STATUS_BUS_RESET
;
250 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
251 USBSTOR_QueueResetDevice(FDODeviceExtension
);
253 ExFreePoolWithTag(Context
, USB_STOR_TAG
);
254 return STATUS_CONTINUE_COMPLETION
;
258 USBSTOR_SendCSWRequest(
259 PIRP_CONTEXT Context
,
262 return USBSTOR_IssueBulkOrInterruptRequest(Context
->FDODeviceExtension
,
264 Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
,
265 USBD_TRANSFER_DIRECTION_IN
,
269 USBSTOR_CSWCompletionRoutine
,
273 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine
;
277 USBSTOR_DataCompletionRoutine(
278 PDEVICE_OBJECT DeviceObject
,
282 PIRP_CONTEXT Context
;
283 PIO_STACK_LOCATION IoStack
;
284 PSCSI_REQUEST_BLOCK Request
;
285 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
287 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
289 Context
= (PIRP_CONTEXT
)Ctx
;
290 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
291 Request
= IoStack
->Parameters
.Scsi
.Srb
;
292 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
294 // for Sense Request a partial MDL was already freed (if existed)
295 if (Request
== Context
->FDODeviceExtension
->ActiveSrb
&&
296 Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferMDL
!= Irp
->MdlAddress
)
298 IoFreeMdl(Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferMDL
);
301 if (NT_SUCCESS(Irp
->IoStatus
.Status
))
303 if (Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferLength
< Request
->DataTransferLength
)
305 Request
->SrbStatus
= SRB_STATUS_DATA_OVERRUN
;
309 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
312 Request
->DataTransferLength
= Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferLength
;
313 USBSTOR_SendCSWRequest(Context
, Irp
);
315 else if (USBD_STATUS(Context
->Urb
.UrbHeader
.Status
) == USBD_STATUS(USBD_STATUS_STALL_PID
))
317 ++Context
->StallRetryCount
;
319 Request
->SrbStatus
= SRB_STATUS_DATA_OVERRUN
;
320 Request
->DataTransferLength
= Context
->Urb
.UrbBulkOrInterruptTransfer
.TransferBufferLength
;
322 // clear stall and resend cbw
323 USBSTOR_QueueResetPipe(Context
->FDODeviceExtension
, Context
);
327 Irp
->IoStatus
.Information
= 0;
328 Irp
->IoStatus
.Status
= STATUS_IO_DEVICE_ERROR
;
329 Request
->SrbStatus
= SRB_STATUS_BUS_RESET
;
331 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
332 USBSTOR_QueueResetDevice(Context
->FDODeviceExtension
);
334 ExFreePoolWithTag(Context
, USB_STOR_TAG
);
335 return STATUS_CONTINUE_COMPLETION
;
338 return STATUS_MORE_PROCESSING_REQUIRED
;
341 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine
;
345 USBSTOR_CBWCompletionRoutine(
346 PDEVICE_OBJECT DeviceObject
,
350 PIRP_CONTEXT Context
;
351 PIO_STACK_LOCATION IoStack
;
352 PSCSI_REQUEST_BLOCK Request
;
353 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
354 USBD_PIPE_HANDLE PipeHandle
;
357 PVOID TransferBuffer
= NULL
;
359 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp
, Ctx
, Irp
->IoStatus
.Status
);
361 Context
= (PIRP_CONTEXT
)Ctx
;
362 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
363 Request
= IoStack
->Parameters
.Scsi
.Srb
;
364 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
366 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
371 // a request without the buffer AND not a sense request
372 // for a sense request we provide just a TransferBuffer, an Mdl will be allocated by usbport (see below)
373 if (!Irp
->MdlAddress
&& Request
== Context
->FDODeviceExtension
->ActiveSrb
)
375 Request
->SrbStatus
= SRB_STATUS_SUCCESS
;
376 USBSTOR_SendCSWRequest(Context
, Irp
);
377 return STATUS_MORE_PROCESSING_REQUIRED
;
380 // a request with the data buffer
382 if ((Request
->SrbFlags
& SRB_FLAGS_UNSPECIFIED_DIRECTION
) == SRB_FLAGS_DATA_IN
)
384 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkInPipeIndex
].PipeHandle
;
385 TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_SHORT_TRANSFER_OK
;
387 else if ((Request
->SrbFlags
& SRB_FLAGS_UNSPECIFIED_DIRECTION
) == SRB_FLAGS_DATA_OUT
)
389 PipeHandle
= Context
->FDODeviceExtension
->InterfaceInformation
->Pipes
[Context
->FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
;
390 TransferFlags
= USBD_TRANSFER_DIRECTION_OUT
;
394 // we check the validity of a request in disk.c so we should never be here
395 DPRINT1("Warning: shouldn't be here\n");
399 // if it is not a Sense Request
400 if (Request
== Context
->FDODeviceExtension
->ActiveSrb
)
402 if (MmGetMdlVirtualAddress(Irp
->MdlAddress
) == Request
->DataBuffer
)
404 Mdl
= Irp
->MdlAddress
;
408 Mdl
= IoAllocateMdl(Request
->DataBuffer
,
409 Request
->DataTransferLength
,
416 IoBuildPartialMdl(Irp
->MdlAddress
,
419 Request
->DataTransferLength
);
425 DPRINT1("USBSTOR_CBWCompletionRoutine: Mdl - %p\n", Mdl
);
431 ASSERT(Request
->DataBuffer
);
432 TransferBuffer
= Request
->DataBuffer
;
435 USBSTOR_IssueBulkOrInterruptRequest(Context
->FDODeviceExtension
,
439 Request
->DataTransferLength
,
442 USBSTOR_DataCompletionRoutine
,
445 return STATUS_MORE_PROCESSING_REQUIRED
;
448 Request
= Context
->FDODeviceExtension
->ActiveSrb
;
449 IoStack
->Parameters
.Scsi
.Srb
= Request
;
450 Irp
->IoStatus
.Information
= 0;
451 Irp
->IoStatus
.Status
= STATUS_IO_DEVICE_ERROR
;
452 Request
->SrbStatus
= SRB_STATUS_BUS_RESET
;
454 USBSTOR_QueueTerminateRequest(PDODeviceExtension
->LowerDeviceObject
, Irp
);
455 USBSTOR_QueueResetDevice(Context
->FDODeviceExtension
);
457 ExFreePoolWithTag(Context
, USB_STOR_TAG
);
458 return STATUS_CONTINUE_COMPLETION
;
465 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",
466 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,
467 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,
468 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,
474 USBSTOR_SendCBWRequest(
475 IN PFDO_DEVICE_EXTENSION FDODeviceExtension
,
477 IN PIRP_CONTEXT Context
)
479 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
480 PIO_STACK_LOCATION IoStack
;
481 PSCSI_REQUEST_BLOCK Request
;
483 RtlZeroMemory(&Context
->cbw
, sizeof(CBW
));
484 RtlZeroMemory(&Context
->Urb
, sizeof(URB
));
486 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
487 PDODeviceExtension
= IoStack
->DeviceObject
->DeviceExtension
;
488 Request
= IoStack
->Parameters
.Scsi
.Srb
;
490 Context
->cbw
.Signature
= CBW_SIGNATURE
;
491 Context
->cbw
.Tag
= PtrToUlong(&Context
->cbw
);
492 Context
->cbw
.DataTransferLength
= Request
->DataTransferLength
;
493 Context
->cbw
.Flags
= ((UCHAR
)Request
->SrbFlags
& SRB_FLAGS_UNSPECIFIED_DIRECTION
) << 1;
494 Context
->cbw
.LUN
= PDODeviceExtension
->LUN
;
495 Context
->cbw
.CommandBlockLength
= Request
->CdbLength
;
497 RtlCopyMemory(&Context
->cbw
.CommandBlock
, Request
->Cdb
, Request
->CdbLength
);
499 DPRINT("CBW for IRP %p\n", Irp
);
500 DumpCBW((PUCHAR
)&Context
->cbw
);
502 // initialize rest of context
504 Context
->FDODeviceExtension
= FDODeviceExtension
;
505 Context
->StallRetryCount
= 0;
507 return USBSTOR_IssueBulkOrInterruptRequest(
510 FDODeviceExtension
->InterfaceInformation
->Pipes
[FDODeviceExtension
->BulkOutPipeIndex
].PipeHandle
,
511 USBD_TRANSFER_DIRECTION_OUT
,
515 USBSTOR_CBWCompletionRoutine
,
521 USBSTOR_IssueRequestSense(
522 IN PFDO_DEVICE_EXTENSION FDODeviceExtension
,
524 IN PIRP_CONTEXT Context
)
526 PIO_STACK_LOCATION IoStack
;
527 PSCSI_REQUEST_BLOCK CurrentSrb
;
528 PSCSI_REQUEST_BLOCK SenseSrb
;
530 DPRINT("USBSTOR_IssueRequestSense: \n");
532 CurrentSrb
= FDODeviceExtension
->ActiveSrb
;
533 SenseSrb
= &Context
->SenseSrb
;
534 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
535 IoStack
->Parameters
.Scsi
.Srb
= SenseSrb
;
537 RtlZeroMemory(SenseSrb
, sizeof(*SenseSrb
));
539 SenseSrb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
540 SenseSrb
->Length
= sizeof(*SenseSrb
);
541 SenseSrb
->CdbLength
= CDB6GENERIC_LENGTH
;
542 SenseSrb
->SrbFlags
= SRB_FLAGS_DATA_IN
|
543 SRB_FLAGS_NO_QUEUE_FREEZE
|
544 SRB_FLAGS_DISABLE_AUTOSENSE
;
546 ASSERT(CurrentSrb
->SenseInfoBufferLength
);
547 ASSERT(CurrentSrb
->SenseInfoBuffer
);
548 DPRINT("SenseInfoBuffer %x, SenseInfoBufferLength %x\n", CurrentSrb
->SenseInfoBuffer
, CurrentSrb
->SenseInfoBufferLength
);
550 SenseSrb
->DataTransferLength
= CurrentSrb
->SenseInfoBufferLength
;
551 SenseSrb
->DataBuffer
= CurrentSrb
->SenseInfoBuffer
;
553 SrbGetCdb(SenseSrb
)->CDB6GENERIC
.OperationCode
= SCSIOP_REQUEST_SENSE
;
554 SrbGetCdb(SenseSrb
)->AsByte
[4] = CurrentSrb
->SenseInfoBufferLength
;
556 return USBSTOR_SendCBWRequest(FDODeviceExtension
, Irp
, Context
);
560 USBSTOR_HandleExecuteSCSI(
561 IN PDEVICE_OBJECT DeviceObject
,
565 PIO_STACK_LOCATION IoStack
;
566 PSCSI_REQUEST_BLOCK Request
;
567 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
568 PIRP_CONTEXT Context
;
570 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
571 ASSERT(PDODeviceExtension
->Common
.IsFDO
== FALSE
);
573 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
574 Request
= IoStack
->Parameters
.Scsi
.Srb
;
576 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x, Length %lu\n", SrbGetCdb(Request
)->CDB10
.OperationCode
, Request
->DataTransferLength
);
578 // check that we're sending to the right LUN
579 ASSERT(SrbGetCdb(Request
)->CDB10
.LogicalUnitNumber
== (PDODeviceExtension
->LUN
& MAX_LUN
));
580 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(IRP_CONTEXT
), USB_STOR_TAG
);
584 Status
= STATUS_INSUFFICIENT_RESOURCES
;
588 Status
= USBSTOR_SendCBWRequest(PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
, Irp
, Context
);