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