xref: /reactos/drivers/usb/usbstor/scsi.c (revision 2540c3b1)
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
USBSTOR_SrbStatusToNtStatus(IN PSCSI_REQUEST_BLOCK Srb)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
USBSTOR_IssueBulkOrInterruptRequest(IN PFDO_DEVICE_EXTENSION FDODeviceExtension,IN PIRP Irp,IN USBD_PIPE_HANDLE PipeHandle,IN ULONG TransferFlags,IN ULONG TransferBufferLength,IN PVOID TransferBuffer,IN PMDL TransferBufferMDL,IN PIO_COMPLETION_ROUTINE CompletionRoutine)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 {
70     PIO_STACK_LOCATION NextStack;
71     PIRP_CONTEXT Context = &FDODeviceExtension->CurrentIrpContext;
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                            FDODeviceExtension,
92                            TRUE,
93                            TRUE,
94                            TRUE);
95 
96     return IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp);
97 }
98 
99 static
100 BOOLEAN
USBSTOR_IsCSWValid(PIRP_CONTEXT Context)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->Irp))
111     {
112         DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", PtrToUlong(Context->Irp), 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 
125 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
126 
127 NTSTATUS
128 NTAPI
USBSTOR_CSWCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Ctx)129 USBSTOR_CSWCompletionRoutine(
130     PDEVICE_OBJECT DeviceObject,
131     PIRP Irp,
132     PVOID Ctx)
133 {
134     PIRP_CONTEXT Context;
135     PIO_STACK_LOCATION IoStack;
136     PPDO_DEVICE_EXTENSION PDODeviceExtension;
137     PFDO_DEVICE_EXTENSION FDODeviceExtension;
138     PSCSI_REQUEST_BLOCK Request;
139 
140     DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
141 
142     IoStack = IoGetCurrentIrpStackLocation(Irp);
143     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
144     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx;
145     Context = &FDODeviceExtension->CurrentIrpContext;
146     Request = IoStack->Parameters.Scsi.Srb;
147     ASSERT(Request);
148 
149     // first check for Irp errors
150     if (!NT_SUCCESS(Irp->IoStatus.Status))
151     {
152         if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
153         {
154             if (Context->StallRetryCount < 2)
155             {
156                 ++Context->StallRetryCount;
157 
158                 // clear stall and resend cbw
159                 USBSTOR_QueueResetPipe(FDODeviceExtension);
160 
161                 return STATUS_MORE_PROCESSING_REQUIRED;
162             }
163         }
164         else
165         {
166             DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status);
167         }
168 
169         goto ResetRecovery;
170     }
171 
172     // now check the CSW packet validity
173     if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR)
174     {
175         goto ResetRecovery;
176     }
177 
178     // finally check for CSW errors
179     if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED)
180     {
181         // should happen only when a sense request was sent
182         if (Request != FDODeviceExtension->ActiveSrb)
183         {
184             ASSERT(IoStack->Parameters.Scsi.Srb == &Context->SenseSrb);
185             FDODeviceExtension->ActiveSrb->SenseInfoBufferLength = Request->DataTransferLength;
186             Request = FDODeviceExtension->ActiveSrb;
187             IoStack->Parameters.Scsi.Srb = Request;
188             Request->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
189         }
190 
191         Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request);
192     }
193     else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED)
194     {
195         // the command is correct but with failed status - issue request sense
196         DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n");
197 
198         ASSERT(FDODeviceExtension->ActiveSrb == Request);
199 
200         // setting a generic error status, additional information
201         // should be read by higher-level driver from SenseInfoBuffer
202         Request->SrbStatus = SRB_STATUS_ERROR;
203         Request->ScsiStatus = 2;
204         Request->DataTransferLength = 0;
205 
206         DPRINT("Flags: %x SBL: %x, buf: %p\n", Request->SrbFlags, Request->SenseInfoBufferLength, Request->SenseInfoBuffer);
207 
208         if (!(Request->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
209               Request->SenseInfoBufferLength &&
210               Request->SenseInfoBuffer)
211         {
212             USBSTOR_IssueRequestSense(FDODeviceExtension, Irp);
213             return STATUS_MORE_PROCESSING_REQUIRED;
214         }
215 
216         Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
217     }
218 
219     Irp->IoStatus.Information = Request->DataTransferLength;
220 
221     // terminate current request
222     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
223     USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
224 
225     return STATUS_CONTINUE_COMPLETION;
226 
227 ResetRecovery:
228 
229     Request = FDODeviceExtension->ActiveSrb;
230     IoStack->Parameters.Scsi.Srb = Request;
231     Irp->IoStatus.Information = 0;
232     Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
233     Request->SrbStatus = SRB_STATUS_BUS_RESET;
234 
235     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
236     USBSTOR_QueueResetDevice(FDODeviceExtension);
237 
238     return STATUS_CONTINUE_COMPLETION;
239 }
240 
241 NTSTATUS
USBSTOR_SendCSWRequest(PFDO_DEVICE_EXTENSION FDODeviceExtension,PIRP Irp)242 USBSTOR_SendCSWRequest(
243     PFDO_DEVICE_EXTENSION FDODeviceExtension,
244     PIRP Irp)
245 {
246     return USBSTOR_IssueBulkOrInterruptRequest(FDODeviceExtension,
247                                                Irp,
248                                                FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle,
249                                                USBD_TRANSFER_DIRECTION_IN,
250                                                sizeof(CSW),
251                                                &FDODeviceExtension->CurrentIrpContext.csw,
252                                                NULL,
253                                                USBSTOR_CSWCompletionRoutine);
254 }
255 
256 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
257 
258 NTSTATUS
259 NTAPI
USBSTOR_DataCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Ctx)260 USBSTOR_DataCompletionRoutine(
261     PDEVICE_OBJECT DeviceObject,
262     PIRP Irp,
263     PVOID Ctx)
264 {
265     PIRP_CONTEXT Context;
266     PIO_STACK_LOCATION IoStack;
267     PSCSI_REQUEST_BLOCK Request;
268     PFDO_DEVICE_EXTENSION FDODeviceExtension;
269     PPDO_DEVICE_EXTENSION PDODeviceExtension;
270 
271     DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
272 
273     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx;
274     Context = &FDODeviceExtension->CurrentIrpContext;
275     IoStack = IoGetCurrentIrpStackLocation(Irp);
276     Request = IoStack->Parameters.Scsi.Srb;
277     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
278 
279     // for Sense Request a partial MDL was already freed (if existed)
280     if (Request == FDODeviceExtension->ActiveSrb &&
281         Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL != Irp->MdlAddress)
282     {
283         IoFreeMdl(Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL);
284     }
285 
286     if (NT_SUCCESS(Irp->IoStatus.Status))
287     {
288         if (Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength < Request->DataTransferLength)
289         {
290             Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
291         }
292         else
293         {
294             Request->SrbStatus = SRB_STATUS_SUCCESS;
295         }
296 
297         Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
298         USBSTOR_SendCSWRequest(FDODeviceExtension, Irp);
299     }
300     else if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID))
301     {
302         ++Context->StallRetryCount;
303 
304         Request->SrbStatus = SRB_STATUS_DATA_OVERRUN;
305         Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength;
306 
307         // clear stall and resend cbw
308         USBSTOR_QueueResetPipe(FDODeviceExtension);
309     }
310     else
311     {
312         Irp->IoStatus.Information = 0;
313         Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
314         Request->SrbStatus = SRB_STATUS_BUS_RESET;
315 
316         USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
317         USBSTOR_QueueResetDevice(FDODeviceExtension);
318 
319         return STATUS_CONTINUE_COMPLETION;
320     }
321 
322     return STATUS_MORE_PROCESSING_REQUIRED;
323 }
324 
325 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
326 
327 NTSTATUS
328 NTAPI
USBSTOR_CBWCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Ctx)329 USBSTOR_CBWCompletionRoutine(
330     PDEVICE_OBJECT DeviceObject,
331     PIRP Irp,
332     PVOID Ctx)
333 {
334     PIO_STACK_LOCATION IoStack;
335     PSCSI_REQUEST_BLOCK Request;
336     PPDO_DEVICE_EXTENSION PDODeviceExtension;
337     PFDO_DEVICE_EXTENSION FDODeviceExtension;
338     USBD_PIPE_HANDLE PipeHandle;
339     ULONG TransferFlags;
340     PMDL Mdl = NULL;
341     PVOID TransferBuffer = NULL;
342 
343     DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
344 
345     FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx;
346     IoStack = IoGetCurrentIrpStackLocation(Irp);
347     Request = IoStack->Parameters.Scsi.Srb;
348     PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
349 
350     if (!NT_SUCCESS(Irp->IoStatus.Status))
351     {
352         goto ResetRecovery;
353     }
354 
355     // a request without the buffer AND not a sense request
356     // for a sense request we provide just a TransferBuffer, an Mdl will be allocated by usbport (see below)
357     if (!Irp->MdlAddress && Request == FDODeviceExtension->ActiveSrb)
358     {
359         Request->SrbStatus = SRB_STATUS_SUCCESS;
360         USBSTOR_SendCSWRequest(FDODeviceExtension, Irp);
361         return STATUS_MORE_PROCESSING_REQUIRED;
362     }
363 
364     // a request with the data buffer
365 
366     if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN)
367     {
368         PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle;
369         TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
370     }
371     else if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT)
372     {
373         PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
374         TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
375     }
376     else
377     {
378         // we check the validity of a request in disk.c so we should never be here
379         DPRINT1("Warning: shouldn't be here\n");
380         goto ResetRecovery;
381     }
382 
383     // if it is not a Sense Request
384     if (Request == FDODeviceExtension->ActiveSrb)
385     {
386         if (MmGetMdlVirtualAddress(Irp->MdlAddress) == Request->DataBuffer)
387         {
388             Mdl = Irp->MdlAddress;
389         }
390         else
391         {
392             Mdl = IoAllocateMdl(Request->DataBuffer,
393                                 Request->DataTransferLength,
394                                 FALSE,
395                                 FALSE,
396                                 NULL);
397 
398             if (Mdl)
399             {
400                 IoBuildPartialMdl(Irp->MdlAddress,
401                                   Mdl,
402                                   Request->DataBuffer,
403                                   Request->DataTransferLength);
404             }
405         }
406 
407         if (!Mdl)
408         {
409             DPRINT1("USBSTOR_CBWCompletionRoutine: Mdl - %p\n", Mdl);
410             goto ResetRecovery;
411         }
412     }
413     else
414     {
415         ASSERT(Request->DataBuffer);
416         TransferBuffer = Request->DataBuffer;
417     }
418 
419     USBSTOR_IssueBulkOrInterruptRequest(FDODeviceExtension,
420                                         Irp,
421                                         PipeHandle,
422                                         TransferFlags,
423                                         Request->DataTransferLength,
424                                         TransferBuffer,
425                                         Mdl,
426                                         USBSTOR_DataCompletionRoutine);
427 
428     return STATUS_MORE_PROCESSING_REQUIRED;
429 
430 ResetRecovery:
431     Request = FDODeviceExtension->ActiveSrb;
432     IoStack->Parameters.Scsi.Srb = Request;
433     Irp->IoStatus.Information = 0;
434     Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
435     Request->SrbStatus = SRB_STATUS_BUS_RESET;
436 
437     USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
438     USBSTOR_QueueResetDevice(FDODeviceExtension);
439 
440     return STATUS_CONTINUE_COMPLETION;
441 }
442 
443 VOID
DumpCBW(PUCHAR Block)444 DumpCBW(
445     PUCHAR Block)
446 {
447     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",
448         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,
449         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,
450         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,
451         Block[30] & 0xFF);
452 }
453 
454 static
455 NTSTATUS
USBSTOR_SendCBWRequest(IN PFDO_DEVICE_EXTENSION FDODeviceExtension,IN PIRP Irp)456 USBSTOR_SendCBWRequest(
457     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
458     IN PIRP Irp)
459 {
460     PPDO_DEVICE_EXTENSION PDODeviceExtension;
461     PIO_STACK_LOCATION IoStack;
462     PSCSI_REQUEST_BLOCK Request;
463     PIRP_CONTEXT Context = &FDODeviceExtension->CurrentIrpContext;
464 
465     RtlZeroMemory(&Context->cbw, sizeof(CBW));
466     RtlZeroMemory(&Context->Urb, sizeof(URB));
467 
468     IoStack = IoGetCurrentIrpStackLocation(Irp);
469     PDODeviceExtension = IoStack->DeviceObject->DeviceExtension;
470     Request = IoStack->Parameters.Scsi.Srb;
471 
472     // Make a CBW structure from SCSI request block
473     Context->cbw.Signature = CBW_SIGNATURE;
474     Context->cbw.Tag = PtrToUlong(Irp);
475     Context->cbw.DataTransferLength = Request->DataTransferLength;
476     Context->cbw.Flags = ((UCHAR)Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) << 1;
477     Context->cbw.LUN = PDODeviceExtension->LUN;
478     Context->cbw.CommandBlockLength = Request->CdbLength;
479 
480     RtlCopyMemory(&Context->cbw.CommandBlock, Request->Cdb, Request->CdbLength);
481 
482     DPRINT("CBW for IRP %p\n", Irp);
483     DumpCBW((PUCHAR)&Context->cbw);
484 
485     // initialize rest of context
486     Context->Irp = Irp;
487     Context->StallRetryCount = 0;
488 
489     return USBSTOR_IssueBulkOrInterruptRequest(
490         FDODeviceExtension,
491         Irp,
492         FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
493         USBD_TRANSFER_DIRECTION_OUT,
494         sizeof(CBW),
495         &Context->cbw,
496         NULL,
497         USBSTOR_CBWCompletionRoutine);
498 }
499 
500 static
501 NTSTATUS
USBSTOR_IssueRequestSense(IN PFDO_DEVICE_EXTENSION FDODeviceExtension,IN PIRP Irp)502 USBSTOR_IssueRequestSense(
503     IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
504     IN PIRP Irp)
505 {
506     PIO_STACK_LOCATION IoStack;
507     PSCSI_REQUEST_BLOCK CurrentSrb;
508     PSCSI_REQUEST_BLOCK SenseSrb;
509 
510     DPRINT("USBSTOR_IssueRequestSense: \n");
511 
512     CurrentSrb = FDODeviceExtension->ActiveSrb;
513     SenseSrb = &FDODeviceExtension->CurrentIrpContext.SenseSrb;
514     IoStack = IoGetCurrentIrpStackLocation(Irp);
515     IoStack->Parameters.Scsi.Srb = SenseSrb;
516 
517     RtlZeroMemory(SenseSrb, sizeof(*SenseSrb));
518 
519     SenseSrb->Function = SRB_FUNCTION_EXECUTE_SCSI;
520     SenseSrb->Length = sizeof(*SenseSrb);
521     SenseSrb->CdbLength = CDB6GENERIC_LENGTH;
522     SenseSrb->SrbFlags = SRB_FLAGS_DATA_IN |
523                          SRB_FLAGS_NO_QUEUE_FREEZE |
524                          SRB_FLAGS_DISABLE_AUTOSENSE;
525 
526     ASSERT(CurrentSrb->SenseInfoBufferLength);
527     ASSERT(CurrentSrb->SenseInfoBuffer);
528     DPRINT("SenseInfoBuffer %x, SenseInfoBufferLength %x\n", CurrentSrb->SenseInfoBuffer, CurrentSrb->SenseInfoBufferLength);
529 
530     SenseSrb->DataTransferLength = CurrentSrb->SenseInfoBufferLength;
531     SenseSrb->DataBuffer = CurrentSrb->SenseInfoBuffer;
532 
533     SrbGetCdb(SenseSrb)->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_SENSE;
534     SrbGetCdb(SenseSrb)->AsByte[4] = CurrentSrb->SenseInfoBufferLength;
535 
536     return USBSTOR_SendCBWRequest(FDODeviceExtension, Irp);
537 }
538 
539 NTSTATUS
USBSTOR_HandleExecuteSCSI(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)540 USBSTOR_HandleExecuteSCSI(
541     IN PDEVICE_OBJECT DeviceObject,
542     IN PIRP Irp)
543 {
544     PIO_STACK_LOCATION IoStack;
545     PSCSI_REQUEST_BLOCK Request;
546     PPDO_DEVICE_EXTENSION PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
547 
548     ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
549 
550     IoStack = IoGetCurrentIrpStackLocation(Irp);
551     Request = IoStack->Parameters.Scsi.Srb;
552 
553     DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x, Length %lu\n", SrbGetCdb(Request)->CDB10.OperationCode, Request->DataTransferLength);
554 
555     // check that we're sending to the right LUN
556     ASSERT(SrbGetCdb(Request)->CDB10.LogicalUnitNumber == PDODeviceExtension->LUN);
557 
558     return USBSTOR_SendCBWRequest(PDODeviceExtension->LowerDeviceObject->DeviceExtension, Irp);
559 }
560