xref: /reactos/drivers/usb/usbstor/scsi.c (revision 9592728f)
1 /*
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)
8  *              2017 Vadim Galyant
9  *              2019 Victor Perevertkin (victor.perevertkin@reactos.org)
10  */
11 
12 #include "usbstor.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 
18 static
19 NTSTATUS
20 USBSTOR_SrbStatusToNtStatus(
21     IN PSCSI_REQUEST_BLOCK Srb)
22 {
23     UCHAR SrbStatus;
24 
25     SrbStatus = SRB_STATUS(Srb->SrbStatus);
26 
27     switch (SrbStatus)
28     {
29         case SRB_STATUS_SUCCESS:
30             return STATUS_SUCCESS;
31 
32         case SRB_STATUS_DATA_OVERRUN:
33             return STATUS_BUFFER_OVERFLOW;
34 
35         case SRB_STATUS_BAD_FUNCTION:
36         case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
37             return STATUS_INVALID_DEVICE_REQUEST;
38 
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;
44 
45         case SRB_STATUS_TIMEOUT:
46             return STATUS_IO_TIMEOUT;
47 
48         case SRB_STATUS_BUS_RESET:
49         case SRB_STATUS_COMMAND_TIMEOUT:
50         case SRB_STATUS_SELECTION_TIMEOUT:
51             return STATUS_DEVICE_NOT_CONNECTED;
52 
53         default:
54             return STATUS_IO_DEVICE_ERROR;
55     }
56 }
57 
58 static
59 NTSTATUS
60 USBSTOR_IssueBulkOrInterruptRequest(
61     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
62     IN PIRP Irp,
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)
70 {
71     PIO_STACK_LOCATION NextStack;
72 
73     RtlZeroMemory(&Context->Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
74 
75     Context->Urb.UrbHeader.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
76     Context->Urb.UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
77 
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;
83 
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;
88 
89     IoSetCompletionRoutine(Irp,
90                            CompletionRoutine,
91                            Context,
92                            TRUE,
93                            TRUE,
94                            TRUE);
95 
96     return IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp);
97 }
98 
99 static
100 BOOLEAN
101 USBSTOR_IsCSWValid(
102     PIRP_CONTEXT Context)
103 {
104     if (Context->csw.Signature != CSW_SIGNATURE)
105     {
106         DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw.Signature);
107         return FALSE;
108     }
109 
110     if (Context->csw.Tag != PtrToUlong(&Context->csw))
111     {
112         DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", PtrToUlong(&Context->csw), Context->csw.Tag);
113         return FALSE;
114     }
115 
116     return TRUE;
117 }
118 
119 static
120 NTSTATUS
121 USBSTOR_IssueRequestSense(
122     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
123     IN PIRP Irp,
124     IN PIRP_CONTEXT Context);
125 
126 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
127 
128 NTSTATUS
129 NTAPI
130 USBSTOR_CSWCompletionRoutine(
131     PDEVICE_OBJECT DeviceObject,
132     PIRP Irp,
133     PVOID Ctx)
134 {
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;
141 
142     Context = (PIRP_CONTEXT)Ctx;
143 
144     DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
145 
146     IoStack = IoGetCurrentIrpStackLocation(Irp);
147     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
148     FDODeviceExtension = Context->FDODeviceExtension;
149     Request = IoStack->Parameters.Scsi.Srb;
150     ASSERT(Request);
151 
152     // first check for Irp errors
153     if (!NT_SUCCESS(Irp->IoStatus.Status))
154     {
155         if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
156         {
157             if (Context->StallRetryCount < 2)
158             {
159                 ++Context->StallRetryCount;
160 
161                 // clear stall and resend cbw
162                 USBSTOR_QueueResetPipe(FDODeviceExtension, Context);
163 
164                 return STATUS_MORE_PROCESSING_REQUIRED;
165             }
166         }
167         else
168         {
169             DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
170         }
171 
172         goto ResetRecovery;
173     }
174 
175     // now check the CSW packet validity
176     if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
177     {
178         goto ResetRecovery;
179     }
180 
181     // finally check for CSW errors
182     if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
183     {
184         // should happen only when a sense request was sent
185         if (Request != FDODeviceExtension->ActiveSrb)
186         {
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;
192         }
193 
194         // read capacity needs special work
195         if (Request->Cdb[0] == SCSIOP_READ_CAPACITY)
196         {
197             // get output buffer
198             Response = (PUFI_CAPACITY_RESPONSE)Request->DataBuffer;
199 
200             // store in pdo
201             PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
202             PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
203         }
204 
205         Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request);
206     }
207     else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
208     {
209         // the command is correct but with failed status - issue request sense
210         DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n");
211 
212         ASSERT(FDODeviceExtension->ActiveSrb == Request);
213 
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;
219 
220         DPRINT("Flags: %x SBL: %x, buf: %p\n", Request->SrbFlags, Request->SenseInfoBufferLength, Request->SenseInfoBuffer);
221 
222         if (!(Request->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
223               Request->SenseInfoBufferLength &&
224               Request->SenseInfoBuffer)
225         {
226             USBSTOR_IssueRequestSense(FDODeviceExtension, Irp, Context);
227             return STATUS_MORE_PROCESSING_REQUIRED;
228         }
229 
230         Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
231     }
232 
233     Irp->IoStatus.Information = Request->DataTransferLength;
234 
235     // terminate current request
236     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
237     USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
238 
239     ExFreePoolWithTag(Context, USB_STOR_TAG);
240     return STATUS_CONTINUE_COMPLETION;
241 
242 ResetRecovery:
243 
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;
249 
250     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
251     USBSTOR_QueueResetDevice(FDODeviceExtension);
252 
253     ExFreePoolWithTag(Context, USB_STOR_TAG);
254     return STATUS_CONTINUE_COMPLETION;
255 }
256 
257 NTSTATUS
258 USBSTOR_SendCSWRequest(
259     PIRP_CONTEXT Context,
260     PIRP Irp)
261 {
262     return USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
263                                                Irp,
264                                                Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
265                                                USBD_TRANSFER_DIRECTION_IN,
266                                                sizeof(CSW),
267                                                &Context->csw,
268                                                NULL,
269                                                USBSTOR_CSWCompletionRoutine,
270                                                Context);
271 }
272 
273 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
274 
275 NTSTATUS
276 NTAPI
277 USBSTOR_DataCompletionRoutine(
278     PDEVICE_OBJECT DeviceObject,
279     PIRP Irp,
280     PVOID Ctx)
281 {
282     PIRP_CONTEXT Context;
283     PIO_STACK_LOCATION IoStack;
284     PSCSI_REQUEST_BLOCK Request;
285     PPDO_DEVICE_EXTENSION PDODeviceExtension;
286 
287     DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
288 
289     Context = (PIRP_CONTEXT)Ctx;
290     IoStack = IoGetCurrentIrpStackLocation(Irp);
291     Request = IoStack->Parameters.Scsi.Srb;
292     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
293 
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)
297     {
298         IoFreeMdl(Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL);
299     }
300 
301     if (NT_SUCCESS(Irp->IoStatus.Status))
302     {
303         if (Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength < Request->DataTransferLength)
304         {
305             Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
306         }
307         else
308         {
309             Request->SrbStatus = SRB_STATUS_SUCCESS;
310         }
311 
312         Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
313         USBSTOR_SendCSWRequest(Context, Irp);
314     }
315     else if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
316     {
317         ++Context->StallRetryCount;
318 
319         Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
320         Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
321 
322         // clear stall and resend cbw
323         USBSTOR_QueueResetPipe(Context->FDODeviceExtension, Context);
324     }
325     else
326     {
327         Irp->IoStatus.Information = 0;
328         Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
329         Request->SrbStatus = SRB_STATUS_BUS_RESET;
330 
331         USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
332         USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
333 
334         ExFreePoolWithTag(Context, USB_STOR_TAG);
335         return STATUS_CONTINUE_COMPLETION;
336     }
337 
338     return STATUS_MORE_PROCESSING_REQUIRED;
339 }
340 
341 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
342 
343 NTSTATUS
344 NTAPI
345 USBSTOR_CBWCompletionRoutine(
346     PDEVICE_OBJECT DeviceObject,
347     PIRP Irp,
348     PVOID Ctx)
349 {
350     PIRP_CONTEXT Context;
351     PIO_STACK_LOCATION IoStack;
352     PSCSI_REQUEST_BLOCK Request;
353     PPDO_DEVICE_EXTENSION PDODeviceExtension;
354     USBD_PIPE_HANDLE PipeHandle;
355     ULONG TransferFlags;
356     PMDL Mdl = NULL;
357     PVOID TransferBuffer = NULL;
358 
359     DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
360 
361     Context = (PIRP_CONTEXT)Ctx;
362     IoStack = IoGetCurrentIrpStackLocation(Irp);
363     Request = IoStack->Parameters.Scsi.Srb;
364     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
365 
366     if (!NT_SUCCESS(Irp->IoStatus.Status))
367     {
368         goto ResetRecovery;
369     }
370 
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)
374     {
375         Request->SrbStatus = SRB_STATUS_SUCCESS;
376         USBSTOR_SendCSWRequest(Context, Irp);
377         return STATUS_MORE_PROCESSING_REQUIRED;
378     }
379 
380     // a request with the data buffer
381 
382     if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN)
383     {
384         PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
385         TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
386     }
387     else if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT)
388     {
389         PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
390         TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
391     }
392     else
393     {
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");
396         goto ResetRecovery;
397     }
398 
399     // if it is not a Sense Request
400     if (Request == Context->FDODeviceExtension->ActiveSrb)
401     {
402         if (MmGetMdlVirtualAddress(Irp->MdlAddress) == Request->DataBuffer)
403         {
404             Mdl = Irp->MdlAddress;
405         }
406         else
407         {
408             Mdl = IoAllocateMdl(Request->DataBuffer,
409                                 Request->DataTransferLength,
410                                 FALSE,
411                                 FALSE,
412                                 NULL);
413 
414             if (Mdl)
415             {
416                 IoBuildPartialMdl(Irp->MdlAddress,
417                                   Mdl,
418                                   Request->DataBuffer,
419                                   Request->DataTransferLength);
420             }
421         }
422 
423         if (!Mdl)
424         {
425             DPRINT1("USBSTOR_CBWCompletionRoutine: Mdl - %p\n", Mdl);
426             goto ResetRecovery;
427         }
428     }
429     else
430     {
431         ASSERT(Request->DataBuffer);
432         TransferBuffer = Request->DataBuffer;
433     }
434 
435     USBSTOR_IssueBulkOrInterruptRequest(Context->FDODeviceExtension,
436                                         Irp,
437                                         PipeHandle,
438                                         TransferFlags,
439                                         Request->DataTransferLength,
440                                         TransferBuffer,
441                                         Mdl,
442                                         USBSTOR_DataCompletionRoutine,
443                                         Context);
444 
445     return STATUS_MORE_PROCESSING_REQUIRED;
446 
447 ResetRecovery:
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;
453 
454     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
455     USBSTOR_QueueResetDevice(Context->FDODeviceExtension);
456 
457     ExFreePoolWithTag(Context, USB_STOR_TAG);
458     return STATUS_CONTINUE_COMPLETION;
459 }
460 
461 VOID
462 DumpCBW(
463     PUCHAR Block)
464 {
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,
469         Block[30] & 0xFF);
470 }
471 
472 static
473 NTSTATUS
474 USBSTOR_SendCBWRequest(
475     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
476     IN PIRP Irp,
477     IN PIRP_CONTEXT Context)
478 {
479     PPDO_DEVICE_EXTENSION PDODeviceExtension;
480     PIO_STACK_LOCATION IoStack;
481     PSCSI_REQUEST_BLOCK Request;
482 
483     RtlZeroMemory(&Context->cbw, sizeof(CBW));
484     RtlZeroMemory(&Context->Urb, sizeof(URB));
485 
486     IoStack = IoGetCurrentIrpStackLocation(Irp);
487     PDODeviceExtension = IoStack->DeviceObject->DeviceExtension;
488     Request = IoStack->Parameters.Scsi.Srb;
489 
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;
496 
497     RtlCopyMemory(&Context->cbw.CommandBlock, Request->Cdb, Request->CdbLength);
498 
499     DPRINT("CBW for IRP %p\n", Irp);
500     DumpCBW((PUCHAR)&Context->cbw);
501 
502     // initialize rest of context
503     Context->Irp = Irp;
504     Context->FDODeviceExtension = FDODeviceExtension;
505     Context->StallRetryCount = 0;
506 
507     return USBSTOR_IssueBulkOrInterruptRequest(
508         FDODeviceExtension,
509         Irp,
510         FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
511         USBD_TRANSFER_DIRECTION_OUT,
512         sizeof(CBW),
513         &Context->cbw,
514         NULL,
515         USBSTOR_CBWCompletionRoutine,
516         Context);
517 }
518 
519 static
520 NTSTATUS
521 USBSTOR_IssueRequestSense(
522     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
523     IN PIRP Irp,
524     IN PIRP_CONTEXT Context)
525 {
526     PIO_STACK_LOCATION IoStack;
527     PSCSI_REQUEST_BLOCK CurrentSrb;
528     PSCSI_REQUEST_BLOCK SenseSrb;
529 
530     DPRINT("USBSTOR_IssueRequestSense: \n");
531 
532     CurrentSrb = FDODeviceExtension->ActiveSrb;
533     SenseSrb = &Context->SenseSrb;
534     IoStack = IoGetCurrentIrpStackLocation(Irp);
535     IoStack->Parameters.Scsi.Srb = SenseSrb;
536 
537     RtlZeroMemory(SenseSrb, sizeof(*SenseSrb));
538 
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;
545 
546     ASSERT(CurrentSrb->SenseInfoBufferLength);
547     ASSERT(CurrentSrb->SenseInfoBuffer);
548     DPRINT("SenseInfoBuffer %x, SenseInfoBufferLength %x\n", CurrentSrb->SenseInfoBuffer, CurrentSrb->SenseInfoBufferLength);
549 
550     SenseSrb->DataTransferLength = CurrentSrb->SenseInfoBufferLength;
551     SenseSrb->DataBuffer = CurrentSrb->SenseInfoBuffer;
552 
553     SrbGetCdb(SenseSrb)->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_SENSE;
554     SrbGetCdb(SenseSrb)->AsByte[4] = CurrentSrb->SenseInfoBufferLength;
555 
556     return USBSTOR_SendCBWRequest(FDODeviceExtension, Irp, Context);
557 }
558 
559 NTSTATUS
560 USBSTOR_HandleExecuteSCSI(
561     IN PDEVICE_OBJECT DeviceObject,
562     IN PIRP Irp)
563 {
564     NTSTATUS Status;
565     PIO_STACK_LOCATION IoStack;
566     PSCSI_REQUEST_BLOCK Request;
567     PPDO_DEVICE_EXTENSION PDODeviceExtension;
568     PIRP_CONTEXT Context;
569 
570     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
571     ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
572 
573     IoStack = IoGetCurrentIrpStackLocation(Irp);
574     Request = IoStack->Parameters.Scsi.Srb;
575 
576     DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x, Length %lu\n", SrbGetCdb(Request)->CDB10.OperationCode, Request->DataTransferLength);
577 
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);
581 
582     if (!Context)
583     {
584         Status = STATUS_INSUFFICIENT_RESOURCES;
585     }
586     else
587     {
588         Status = USBSTOR_SendCBWRequest(PDODeviceExtension->LowerDeviceObject->DeviceExtension, Irp, Context);
589     }
590 
591     return Status;
592 }
593