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