[MISC]: Cleanup a bunch of unused variables, in cases where it was obvious these...
[reactos.git] / reactos / drivers / usb / usbstor / scsi.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/pdo.c
5 * PURPOSE: USB block storage device driver.
6 * PROGRAMMERS:
7 * James Tabor
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbstor.h"
13
14 NTSTATUS
15 USBSTOR_BuildCBW(
16 IN ULONG Tag,
17 IN ULONG DataTransferLength,
18 IN UCHAR LUN,
19 IN UCHAR CommandBlockLength,
20 IN PUCHAR CommandBlock,
21 IN OUT PCBW Control)
22 {
23 //
24 // sanity check
25 //
26 ASSERT(CommandBlockLength <= 16);
27
28 //
29 // now initialize CBW
30 //
31 Control->Signature = CBW_SIGNATURE;
32 Control->Tag = Tag;
33 Control->DataTransferLength = DataTransferLength;
34 Control->Flags = (CommandBlock[0] != SCSIOP_WRITE) ? 0x80 : 0x00;
35 Control->LUN = (LUN & MAX_LUN);
36 Control->CommandBlockLength = CommandBlockLength;
37
38 //
39 // copy command block
40 //
41 RtlCopyMemory(Control->CommandBlock, CommandBlock, CommandBlockLength);
42
43 //
44 // done
45 //
46 return STATUS_SUCCESS;
47 }
48
49 PIRP_CONTEXT
50 USBSTOR_AllocateIrpContext()
51 {
52 PIRP_CONTEXT Context;
53
54 //
55 // allocate irp context
56 //
57 Context = (PIRP_CONTEXT)AllocateItem(NonPagedPool, sizeof(IRP_CONTEXT));
58 if (!Context)
59 {
60 //
61 // no memory
62 //
63 return NULL;
64 }
65
66 //
67 // allocate cbw block
68 //
69 Context->cbw = (PCBW)AllocateItem(NonPagedPool, 512);
70 if (!Context->cbw)
71 {
72 //
73 // no memory
74 //
75 FreeItem(Context);
76 return NULL;
77 }
78
79 //
80 // done
81 //
82 return Context;
83
84 }
85
86 BOOLEAN
87 USBSTOR_IsCSWValid(
88 PIRP_CONTEXT Context)
89 {
90 //
91 // sanity checks
92 //
93 if (Context->csw->Signature != CSW_SIGNATURE)
94 {
95 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw->Signature);
96 return FALSE;
97 }
98
99 if (Context->csw->Tag != (ULONG)Context->csw)
100 {
101 DPRINT1("[USBSTOR] Expected Tag %x but got %x\n", (ULONG)Context->csw, Context->csw->Tag);
102 return FALSE;
103 }
104
105 if (Context->csw->Status != 0x00)
106 {
107 DPRINT1("[USBSTOR] Expected Status 0x00 but got %x\n", Context->csw->Status);
108 return FALSE;
109 }
110
111 //
112 // CSW is valid
113 //
114 return TRUE;
115
116 }
117
118 NTSTATUS
119 USBSTOR_QueueWorkItem(
120 PIRP_CONTEXT Context,
121 PIRP Irp)
122 {
123 PERRORHANDLER_WORKITEM_DATA ErrorHandlerWorkItemData;
124
125 //
126 // Allocate Work Item Data
127 //
128 ErrorHandlerWorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERRORHANDLER_WORKITEM_DATA), USB_STOR_TAG);
129 if (!ErrorHandlerWorkItemData)
130 {
131 //
132 // no memory
133 //
134 return STATUS_INSUFFICIENT_RESOURCES;
135 }
136
137 //
138 // error handling started
139 //
140 Context->FDODeviceExtension->SrbErrorHandlingActive = TRUE;
141
142 //
143 // srb error handling finished
144 //
145 Context->FDODeviceExtension->TimerWorkQueueEnabled = FALSE;
146
147 //
148 // Initialize and queue the work item to handle the error
149 //
150 ExInitializeWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem,
151 ErrorHandlerWorkItemRoutine,
152 ErrorHandlerWorkItemData);
153
154 ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
155 ErrorHandlerWorkItemData->Context = Context;
156 ErrorHandlerWorkItemData->Irp = Irp;
157 ErrorHandlerWorkItemData->DeviceObject = Context->FDODeviceExtension->FunctionalDeviceObject;
158
159 DPRINT1("Queuing WorkItemROutine\n");
160 ExQueueWorkItem(&ErrorHandlerWorkItemData->WorkQueueItem, DelayedWorkQueue);
161 return STATUS_MORE_PROCESSING_REQUIRED;
162 }
163
164
165 //
166 // driver verifier
167 //
168 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine;
169
170 NTSTATUS
171 NTAPI
172 USBSTOR_CSWCompletionRoutine(
173 PDEVICE_OBJECT DeviceObject,
174 PIRP Irp,
175 PVOID Ctx)
176 {
177 PIRP_CONTEXT Context;
178 PIO_STACK_LOCATION IoStack;
179 PSCSI_REQUEST_BLOCK Request;
180 PCDB pCDB;
181 PREAD_CAPACITY_DATA_EX CapacityDataEx;
182 PREAD_CAPACITY_DATA CapacityData;
183 PUFI_CAPACITY_RESPONSE Response;
184 NTSTATUS Status;
185
186 //
187 // access context
188 //
189 Context = (PIRP_CONTEXT)Ctx;
190
191 //
192 // is there a mdl
193 //
194 if (Context->TransferBufferMDL)
195 {
196 //
197 // is there an irp associated
198 //
199 if (Context->Irp)
200 {
201 //
202 // did we allocate the mdl
203 //
204 if (Context->TransferBufferMDL != Context->Irp->MdlAddress)
205 {
206 //
207 // free mdl
208 //
209 IoFreeMdl(Context->TransferBufferMDL);
210 }
211 }
212 else
213 {
214 //
215 // free mdl
216 //
217 IoFreeMdl(Context->TransferBufferMDL);
218 }
219 }
220
221 DPRINT("USBSTOR_CSWCompletionRoutine Status %x\n", Irp->IoStatus.Status);
222
223 if (!NT_SUCCESS(Irp->IoStatus.Information))
224 {
225 if (Context->ErrorIndex == 0)
226 {
227 //
228 // increment error index
229 //
230 Context->ErrorIndex = 1;
231
232 //
233 // clear stall and resend cbw
234 //
235 Status = USBSTOR_QueueWorkItem(Context, Irp);
236 ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
237 return STATUS_MORE_PROCESSING_REQUIRED;
238 }
239
240 //
241 // perform reset recovery
242 //
243 Context->ErrorIndex = 2;
244 IoFreeIrp(Irp);
245 Status = USBSTOR_QueueWorkItem(Context, NULL);
246 ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
247 return STATUS_MORE_PROCESSING_REQUIRED;
248 }
249
250 if (!USBSTOR_IsCSWValid(Context))
251 {
252 //
253 // perform reset recovery
254 //
255 Context->ErrorIndex = 2;
256 IoFreeIrp(Irp);
257 Status = USBSTOR_QueueWorkItem(Context, NULL);
258 ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
259 return STATUS_MORE_PROCESSING_REQUIRED;
260 }
261
262
263 //
264 // get current stack location
265 //
266 IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
267
268 //
269 // get request block
270 //
271 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
272 ASSERT(Request);
273
274 Status = Irp->IoStatus.Status;
275
276 //
277 // get SCSI command data block
278 //
279 pCDB = (PCDB)Request->Cdb;
280 Request->SrbStatus = SRB_STATUS_SUCCESS;
281
282 //
283 // read capacity needs special work
284 //
285 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
286 {
287 //
288 // get output buffer
289 //
290 Response = (PUFI_CAPACITY_RESPONSE)Context->TransferData;
291
292 //
293 // store in pdo
294 //
295 Context->PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
296 Context->PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
297
298 if (Request->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX))
299 {
300 //
301 // get input buffer
302 //
303 CapacityDataEx = (PREAD_CAPACITY_DATA_EX)Request->DataBuffer;
304
305 //
306 // set result
307 //
308 CapacityDataEx->BytesPerBlock = Response->BlockLength;
309 CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress;
310 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA_EX);
311 }
312 else
313 {
314 //
315 // get input buffer
316 //
317 CapacityData = (PREAD_CAPACITY_DATA)Request->DataBuffer;
318
319 //
320 // set result
321 //
322 CapacityData->BytesPerBlock = Response->BlockLength;
323 CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress;
324 Irp->IoStatus.Information = sizeof(READ_CAPACITY_DATA);
325 }
326
327 //
328 // free response
329 //
330 FreeItem(Context->TransferData);
331 }
332
333 //
334 // free cbw
335 //
336 FreeItem(Context->cbw);
337
338 //
339 // FIXME: check status
340 //
341 Context->Irp->IoStatus.Status = Irp->IoStatus.Status;
342 Context->Irp->IoStatus.Information = Context->TransferDataLength;
343
344 //
345 // terminate current request
346 //
347 USBSTOR_QueueTerminateRequest(Context->PDODeviceExtension->LowerDeviceObject, Context->Irp);
348
349 //
350 // complete request
351 //
352 IoCompleteRequest(Context->Irp, IO_NO_INCREMENT);
353
354 //
355 // start next request
356 //
357 USBSTOR_QueueNextRequest(Context->PDODeviceExtension->LowerDeviceObject);
358
359 //
360 // free our allocated irp
361 //
362 IoFreeIrp(Irp);
363
364 //
365 // free context
366 //
367 FreeItem(Context);
368
369 //
370 // done
371 //
372 return STATUS_MORE_PROCESSING_REQUIRED;
373 }
374
375 VOID
376 USBSTOR_SendCSW(
377 PIRP_CONTEXT Context,
378 PIRP Irp)
379 {
380 PIO_STACK_LOCATION IoStack;
381
382 //
383 // get next irp stack location
384 //
385 IoStack = IoGetNextIrpStackLocation(Irp);
386
387 //
388 // now initialize the urb for sending the csw
389 //
390 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
391 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
392 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
393 Context->csw,
394 NULL,
395 512, //FIXME
396 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
397 NULL);
398
399 //
400 // initialize stack location
401 //
402 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
403 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
404 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
405 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
406 Irp->IoStatus.Status = STATUS_SUCCESS;
407
408
409 //
410 // setup completion routine
411 //
412 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
413
414 //
415 // call driver
416 //
417 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
418 }
419
420
421 //
422 // driver verifier
423 //
424 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine;
425
426 NTSTATUS
427 NTAPI
428 USBSTOR_DataCompletionRoutine(
429 PDEVICE_OBJECT DeviceObject,
430 PIRP Irp,
431 PVOID Ctx)
432 {
433 PIRP_CONTEXT Context;
434 NTSTATUS Status;
435
436
437 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
438
439 //
440 // access context
441 //
442 Context = (PIRP_CONTEXT)Ctx;
443
444 if (!NT_SUCCESS(Irp->IoStatus.Status))
445 {
446 //
447 // clear stall and resend cbw
448 //
449 Context->ErrorIndex = 1;
450 Status = USBSTOR_QueueWorkItem(Context, Irp);
451 ASSERT(Status == STATUS_MORE_PROCESSING_REQUIRED);
452 return STATUS_MORE_PROCESSING_REQUIRED;
453 }
454
455 //
456 // send csw
457 //
458 USBSTOR_SendCSW(Context, Irp);
459
460 //
461 // cancel completion
462 //
463 return STATUS_MORE_PROCESSING_REQUIRED;
464 }
465
466 //
467 // driver verifier
468 //
469 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine;
470
471 NTSTATUS
472 NTAPI
473 USBSTOR_CBWCompletionRoutine(
474 PDEVICE_OBJECT DeviceObject,
475 PIRP Irp,
476 PVOID Ctx)
477 {
478 PIRP_CONTEXT Context;
479 PIO_STACK_LOCATION IoStack;
480 UCHAR Code;
481 USBD_PIPE_HANDLE PipeHandle;
482
483 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status);
484
485 //
486 // access context
487 //
488 Context = (PIRP_CONTEXT)Ctx;
489
490 //
491 // get next stack location
492 //
493 IoStack = IoGetNextIrpStackLocation(Irp);
494
495 //
496 // is there data to be submitted
497 //
498 if (Context->TransferDataLength)
499 {
500 //
501 // get command code
502 //
503 Code = Context->cbw->CommandBlock[0];
504
505 if (Code == SCSIOP_WRITE)
506 {
507 //
508 // write request use bulk out pipe
509 //
510 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
511 }
512 else
513 {
514 //
515 // default bulk in pipe
516 //
517 PipeHandle = Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle;
518 }
519
520 //
521 // now initialize the urb for sending data
522 //
523 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
524 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
525 PipeHandle,
526 NULL,
527 Context->TransferBufferMDL,
528 Context->TransferDataLength,
529 ((Code == SCSIOP_WRITE) ? USBD_TRANSFER_DIRECTION_OUT : (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)),
530 NULL);
531
532 //
533 // setup completion routine
534 //
535 IoSetCompletionRoutine(Irp, USBSTOR_DataCompletionRoutine, Context, TRUE, TRUE, TRUE);
536 }
537 else
538 {
539 //
540 // now initialize the urb for sending the csw
541 //
542
543 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
544 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
545 Context->FDODeviceExtension->InterfaceInformation->Pipes[Context->FDODeviceExtension->BulkInPipeIndex].PipeHandle,
546 Context->csw,
547 NULL,
548 512, //FIXME
549 USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
550 NULL);
551
552 //
553 // setup completion routine
554 //
555 IoSetCompletionRoutine(Irp, USBSTOR_CSWCompletionRoutine, Context, TRUE, TRUE, TRUE);
556 }
557
558 //
559 // initialize stack location
560 //
561 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
562 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
563 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
564 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
565 Irp->IoStatus.Status = STATUS_SUCCESS;
566
567 //
568 // call driver
569 //
570 IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
571
572 return STATUS_MORE_PROCESSING_REQUIRED;
573 }
574
575 VOID
576 DumpCBW(
577 PUCHAR Block)
578 {
579 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",
580 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,
581 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,
582 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,
583 Block[30] & 0xFF);
584
585 }
586
587 NTSTATUS
588 USBSTOR_SendCBW(
589 PIRP_CONTEXT Context,
590 PIRP Irp)
591 {
592 PIO_STACK_LOCATION IoStack;
593
594 //
595 // get next stack location
596 //
597 IoStack = IoGetNextIrpStackLocation(Irp);
598
599 //
600 // initialize stack location
601 //
602 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
603 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
604 IoStack->Parameters.Others.Argument1 = (PVOID)&Context->Urb;
605 IoStack->Parameters.DeviceIoControl.InputBufferLength = Context->Urb.UrbHeader.Length;
606 Irp->IoStatus.Status = STATUS_SUCCESS;
607
608 //
609 // setup completion routine
610 //
611 IoSetCompletionRoutine(Irp, USBSTOR_CBWCompletionRoutine, Context, TRUE, TRUE, TRUE);
612
613 //
614 // call driver
615 //
616 return IoCallDriver(Context->FDODeviceExtension->LowerDeviceObject, Irp);
617 }
618
619 NTSTATUS
620 USBSTOR_SendRequest(
621 IN PDEVICE_OBJECT DeviceObject,
622 IN PIRP OriginalRequest,
623 IN UCHAR CommandLength,
624 IN PUCHAR Command,
625 IN ULONG TransferDataLength,
626 IN PUCHAR TransferData,
627 IN ULONG RetryCount)
628 {
629 PIRP_CONTEXT Context;
630 PPDO_DEVICE_EXTENSION PDODeviceExtension;
631 PFDO_DEVICE_EXTENSION FDODeviceExtension;
632 PIRP Irp;
633 PUCHAR MdlVirtualAddress;
634
635 //
636 // first allocate irp context
637 //
638 Context = USBSTOR_AllocateIrpContext();
639 if (!Context)
640 {
641 //
642 // no memory
643 //
644 return STATUS_INSUFFICIENT_RESOURCES;
645 }
646
647 //
648 // get PDO device extension
649 //
650 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
651
652 //
653 // get FDO device extension
654 //
655 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
656
657 //
658 // now build the cbw
659 //
660 USBSTOR_BuildCBW((ULONG)Context->cbw,
661 TransferDataLength,
662 PDODeviceExtension->LUN,
663 CommandLength,
664 Command,
665 Context->cbw);
666
667 DPRINT("CBW %p\n", Context->cbw);
668 DumpCBW((PUCHAR)Context->cbw);
669
670 //
671 // now initialize the urb
672 //
673 UsbBuildInterruptOrBulkTransferRequest(&Context->Urb,
674 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
675 FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle,
676 Context->cbw,
677 NULL,
678 sizeof(CBW),
679 USBD_TRANSFER_DIRECTION_OUT,
680 NULL);
681
682 //
683 // initialize rest of context
684 //
685 Context->Irp = OriginalRequest;
686 Context->TransferData = TransferData;
687 Context->TransferDataLength = TransferDataLength;
688 Context->FDODeviceExtension = FDODeviceExtension;
689 Context->PDODeviceExtension = PDODeviceExtension;
690 Context->RetryCount = RetryCount;
691
692 //
693 // is there transfer data
694 //
695 if (Context->TransferDataLength)
696 {
697 //
698 // check if the original request already does have an mdl associated
699 //
700 if (OriginalRequest)
701 {
702 if ((OriginalRequest->MdlAddress != NULL) &&
703 (Context->TransferData == NULL || Command[0] == SCSIOP_READ || Command[0] == SCSIOP_WRITE))
704 {
705 //
706 // Sanity check that the Mdl does describe the TransferData for read/write
707 //
708 if (CommandLength == UFI_READ_WRITE_CMD_LEN)
709 {
710 MdlVirtualAddress = MmGetMdlVirtualAddress(OriginalRequest->MdlAddress);
711
712 //
713 // is there an offset
714 //
715 if (MdlVirtualAddress != Context->TransferData)
716 {
717 //
718 // lets build an mdl
719 //
720 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, MmGetMdlByteCount(OriginalRequest->MdlAddress), FALSE, FALSE, NULL);
721 if (!Context->TransferBufferMDL)
722 {
723 //
724 // failed to allocate MDL
725 //
726 return STATUS_INSUFFICIENT_RESOURCES;
727 }
728
729 //
730 // now build the partial mdl
731 //
732 IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength);
733 }
734 }
735
736 if (!Context->TransferBufferMDL)
737 {
738 //
739 // I/O paging request
740 //
741 Context->TransferBufferMDL = OriginalRequest->MdlAddress;
742 }
743 }
744 else
745 {
746 //
747 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
748 //
749 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
750 if (!Context->TransferBufferMDL)
751 {
752 //
753 // failed to allocate MDL
754 //
755 return STATUS_INSUFFICIENT_RESOURCES;
756 }
757
758 //
759 // build mdl for nonpaged pool
760 //
761 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
762 }
763 }
764 else
765 {
766 //
767 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
768 //
769 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL);
770 if (!Context->TransferBufferMDL)
771 {
772 //
773 // failed to allocate MDL
774 //
775 return STATUS_INSUFFICIENT_RESOURCES;
776 }
777
778 //
779 // build mdl for nonpaged pool
780 //
781 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL);
782 }
783 }
784
785 //
786 // now allocate the request
787 //
788 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
789 if (!Irp)
790 {
791 FreeItem(Context->cbw);
792 FreeItem(Context);
793 return STATUS_INSUFFICIENT_RESOURCES;
794 }
795
796 if (OriginalRequest)
797 {
798 //
799 // mark orignal irp as pending
800 //
801 IoMarkIrpPending(OriginalRequest);
802 }
803
804 //
805 // send request
806 //
807 USBSTOR_SendCBW(Context, Irp);
808
809 //
810 // done
811 //
812 return STATUS_PENDING;
813 }
814
815 NTSTATUS
816 USBSTOR_SendFormatCapacity(
817 IN PDEVICE_OBJECT DeviceObject,
818 IN PIRP Irp,
819 IN ULONG RetryCount)
820 {
821 UFI_READ_FORMAT_CAPACITY Cmd;
822 PPDO_DEVICE_EXTENSION PDODeviceExtension;
823 PIO_STACK_LOCATION IoStack;
824 PSCSI_REQUEST_BLOCK Request;
825
826 //
827 // get current stack location
828 //
829 IoStack = IoGetCurrentIrpStackLocation(Irp);
830
831 //
832 // get PDO device extension
833 //
834 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
835
836 //
837 // get request block
838 //
839 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
840
841 //
842 // initialize inquiry cmd
843 //
844 RtlZeroMemory(&Cmd, sizeof(UFI_READ_FORMAT_CAPACITY));
845 Cmd.Code = SCSIOP_READ_FORMATTED_CAPACITY;
846 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
847 Cmd.AllocationLengthMsb = HTONS(Request->DataTransferLength & 0xFFFF) >> 8;
848 Cmd.AllocationLengthLsb = HTONS(Request->DataTransferLength & 0xFFFF) & 0xFF;
849
850 //
851 // now send the request
852 //
853 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_FORMAT_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
854 }
855
856 NTSTATUS
857 USBSTOR_SendInquiry(
858 IN PDEVICE_OBJECT DeviceObject,
859 IN PIRP Irp,
860 IN ULONG RetryCount)
861 {
862 UFI_INQUIRY_CMD Cmd;
863 PPDO_DEVICE_EXTENSION PDODeviceExtension;
864 PIO_STACK_LOCATION IoStack;
865 PSCSI_REQUEST_BLOCK Request;
866
867 //
868 // get current stack location
869 //
870 IoStack = IoGetCurrentIrpStackLocation(Irp);
871
872 //
873 // get request block
874 //
875 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
876
877 //
878 // get PDO device extension
879 //
880 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
881
882 //
883 // initialize inquiry cmd
884 //
885 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
886 Cmd.Code = SCSIOP_INQUIRY;
887 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
888 Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE);
889
890 //
891 // sanity check
892 //
893 ASSERT(Request->DataTransferLength >= sizeof(UFI_INQUIRY_RESPONSE));
894
895 //
896 // now send the request
897 //
898 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
899 }
900
901 NTSTATUS
902 USBSTOR_SendCapacity(
903 IN PDEVICE_OBJECT DeviceObject,
904 IN PIRP Irp,
905 IN ULONG RetryCount)
906 {
907 UFI_CAPACITY_CMD Cmd;
908 PUFI_CAPACITY_RESPONSE Response;
909 PPDO_DEVICE_EXTENSION PDODeviceExtension;
910
911 //
912 // get PDO device extension
913 //
914 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
915
916 //
917 // allocate capacity response
918 //
919 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, PAGE_SIZE);
920 if (!Response)
921 {
922 //
923 // no memory
924 //
925 return STATUS_INSUFFICIENT_RESOURCES;
926 }
927
928 //
929 // initialize capacity cmd
930 //
931 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
932 Cmd.Code = SCSIOP_READ_CAPACITY;
933 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
934
935 //
936 // send request, response will be freed in completion routine
937 //
938 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response, RetryCount);
939 }
940
941 NTSTATUS
942 USBSTOR_SendModeSense(
943 IN PDEVICE_OBJECT DeviceObject,
944 IN PIRP Irp,
945 IN ULONG RetryCount)
946 {
947 #if 0
948 UFI_SENSE_CMD Cmd;
949 NTSTATUS Status;
950 PVOID Response;
951 PCBW OutControl;
952 PCDB pCDB;
953 PUFI_MODE_PARAMETER_HEADER Header;
954 #endif
955 PPDO_DEVICE_EXTENSION PDODeviceExtension;
956 PIO_STACK_LOCATION IoStack;
957 PSCSI_REQUEST_BLOCK Request;
958
959 //
960 // get PDO device extension
961 //
962 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
963
964 //
965 // sanity check
966 //
967 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
968
969 //
970 // get current stack location
971 //
972 IoStack = IoGetCurrentIrpStackLocation(Irp);
973
974 //
975 // get request block
976 //
977 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
978
979 RtlZeroMemory(Request->DataBuffer, Request->DataTransferLength);
980 Request->SrbStatus = SRB_STATUS_SUCCESS;
981 Irp->IoStatus.Information = Request->DataTransferLength;
982 Irp->IoStatus.Status = STATUS_SUCCESS;
983 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
984 IoCompleteRequest(Irp, IO_NO_INCREMENT);
985
986 //
987 // start next request
988 //
989 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
990
991 return STATUS_SUCCESS;
992
993 #if 0
994 //
995 // get SCSI command data block
996 //
997 pCDB = (PCDB)Request->Cdb;
998
999 //
1000 // get PDO device extension
1001 //
1002 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1003
1004 //
1005 // allocate sense response from non paged pool
1006 //
1007 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
1008 if (!Response)
1009 {
1010 //
1011 // no memory
1012 //
1013 return STATUS_INSUFFICIENT_RESOURCES;
1014 }
1015
1016 //
1017 // sanity check
1018 //
1019
1020
1021 // Supported pages
1022 // MODE_PAGE_ERROR_RECOVERY
1023 // MODE_PAGE_FLEXIBILE
1024 // MODE_PAGE_LUN_MAPPING
1025 // MODE_PAGE_FAULT_REPORTING
1026 // MODE_SENSE_RETURN_ALL
1027
1028 //
1029 // initialize mode sense cmd
1030 //
1031 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
1032 Cmd.Code = SCSIOP_MODE_SENSE;
1033 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
1034 Cmd.PageCode = pCDB->MODE_SENSE.PageCode;
1035 Cmd.PC = pCDB->MODE_SENSE.Pc;
1036 Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength);
1037
1038 DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode);
1039 DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc);
1040
1041 //
1042 // now send mode sense cmd
1043 //
1044 Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
1045 if (!NT_SUCCESS(Status))
1046 {
1047 //
1048 // failed to send CBW
1049 //
1050 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
1051 FreeItem(Response);
1052 ASSERT(FALSE);
1053 return Status;
1054 }
1055
1056 //
1057 // now send data block response
1058 //
1059 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
1060 if (!NT_SUCCESS(Status))
1061 {
1062 //
1063 // failed to send CBW
1064 //
1065 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
1066 FreeItem(Response);
1067 ASSERT(FALSE);
1068 return Status;
1069 }
1070
1071 Header = (PUFI_MODE_PARAMETER_HEADER)Response;
1072
1073 //
1074 // TODO: build layout
1075 //
1076 // first struct is the header
1077 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
1078 //
1079 // followed by
1080 // MODE_PARAMETER_BLOCK
1081 //
1082 //
1083 UNIMPLEMENTED
1084
1085 //
1086 // send csw
1087 //
1088 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
1089
1090 DPRINT1("------------------------\n");
1091 DPRINT1("CSW %p\n", &CSW);
1092 DPRINT1("Signature %x\n", CSW.Signature);
1093 DPRINT1("Tag %x\n", CSW.Tag);
1094 DPRINT1("DataResidue %x\n", CSW.DataResidue);
1095 DPRINT1("Status %x\n", CSW.Status);
1096
1097 //
1098 // FIXME: handle error
1099 //
1100 ASSERT(CSW.Status == 0);
1101 ASSERT(CSW.DataResidue == 0);
1102
1103 //
1104 // calculate transfer length
1105 //
1106 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
1107
1108 //
1109 // copy buffer
1110 //
1111 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
1112
1113 //
1114 // free item
1115 //
1116 FreeItem(OutControl);
1117
1118 //
1119 // free response
1120 //
1121 FreeItem(Response);
1122
1123 //
1124 // done
1125 //
1126 return Status;
1127 #endif
1128 }
1129
1130 NTSTATUS
1131 USBSTOR_SendReadWrite(
1132 IN PDEVICE_OBJECT DeviceObject,
1133 IN PIRP Irp,
1134 IN ULONG RetryCount)
1135 {
1136 UFI_READ_WRITE_CMD Cmd;
1137 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1138 PCDB pCDB;
1139 ULONG BlockCount, Temp;
1140 PIO_STACK_LOCATION IoStack;
1141 PSCSI_REQUEST_BLOCK Request;
1142
1143 //
1144 // get current stack location
1145 //
1146 IoStack = IoGetCurrentIrpStackLocation(Irp);
1147
1148 //
1149 // get request block
1150 //
1151 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1152
1153 //
1154 // get SCSI command data block
1155 //
1156 pCDB = (PCDB)Request->Cdb;
1157
1158 //
1159 // get PDO device extension
1160 //
1161 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1162
1163 //
1164 // informal debug print
1165 //
1166 DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request->DataTransferLength, PDODeviceExtension->BlockLength);
1167
1168 //
1169 // sanity check
1170 //
1171 ASSERT(PDODeviceExtension->BlockLength);
1172
1173 //
1174 // block count
1175 //
1176 BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength;
1177
1178 //
1179 // initialize read cmd
1180 //
1181 RtlZeroMemory(&Cmd, sizeof(UFI_READ_WRITE_CMD));
1182 Cmd.Code = pCDB->AsByte[0];
1183 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
1184 Cmd.ContiguousLogicBlocksByte0 = pCDB->CDB10.TransferBlocksMsb;
1185 Cmd.ContiguousLogicBlocksByte1 = pCDB->CDB10.TransferBlocksLsb;
1186 Cmd.LogicalBlockByte0 = pCDB->CDB10.LogicalBlockByte0;
1187 Cmd.LogicalBlockByte1 = pCDB->CDB10.LogicalBlockByte1;
1188 Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2;
1189 Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3;
1190
1191 //
1192 // sanity check
1193 //
1194 Temp = (Cmd.ContiguousLogicBlocksByte0 << 8 | Cmd.ContiguousLogicBlocksByte1);
1195 ASSERT(NTOHL(Temp == BlockCount));
1196
1197 DPRINT("USBSTOR_SendReadWrite BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength);
1198
1199 //
1200 // send request
1201 //
1202 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount);
1203 }
1204
1205 NTSTATUS
1206 USBSTOR_SendTestUnit(
1207 IN PDEVICE_OBJECT DeviceObject,
1208 IN OUT PIRP Irp,
1209 IN ULONG RetryCount)
1210 {
1211 UFI_TEST_UNIT_CMD Cmd;
1212 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1213 PIO_STACK_LOCATION IoStack;
1214 PSCSI_REQUEST_BLOCK Request;
1215
1216 //
1217 // get current stack location
1218 //
1219 IoStack = IoGetCurrentIrpStackLocation(Irp);
1220
1221 //
1222 // get request block
1223 //
1224 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1225
1226 //
1227 // no transfer length
1228 //
1229 ASSERT(Request->DataTransferLength == 0);
1230
1231 //
1232 // get PDO device extension
1233 //
1234 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1235
1236 //
1237 // initialize test unit cmd
1238 //
1239 RtlZeroMemory(&Cmd, sizeof(UFI_TEST_UNIT_CMD));
1240 Cmd.Code = SCSIOP_TEST_UNIT_READY;
1241 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
1242
1243 //
1244 // send the request
1245 //
1246 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL, RetryCount);
1247 }
1248
1249 NTSTATUS
1250 USBSTOR_SendUnknownRequest(
1251 IN PDEVICE_OBJECT DeviceObject,
1252 IN OUT PIRP Irp,
1253 IN ULONG RetryCount)
1254 {
1255 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1256 PIO_STACK_LOCATION IoStack;
1257 PSCSI_REQUEST_BLOCK Request;
1258 UFI_UNKNOWN_CMD Cmd;
1259
1260 //
1261 // get current stack location
1262 //
1263 IoStack = IoGetCurrentIrpStackLocation(Irp);
1264
1265 //
1266 // get request block
1267 //
1268 Request = IoStack->Parameters.Others.Argument1;
1269
1270 //
1271 // get PDO device extension
1272 //
1273 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1274
1275 //
1276 // check that we're sending to the right LUN
1277 //
1278 ASSERT(Request->Cdb[1] == (PDODeviceExtension->LUN & MAX_LUN));
1279
1280 //
1281 // sanity check
1282 //
1283 ASSERT(Request->CdbLength <= sizeof(UFI_UNKNOWN_CMD));
1284
1285 //
1286 // initialize test unit cmd
1287 //
1288 RtlCopyMemory(&Cmd, Request->Cdb, Request->CdbLength);
1289
1290 //
1291 // send the request
1292 //
1293 return USBSTOR_SendRequest(DeviceObject, Irp, Request->CdbLength, (PUCHAR)&Cmd, Request->DataTransferLength, Request->DataBuffer, RetryCount);
1294 }
1295
1296 NTSTATUS
1297 USBSTOR_HandleExecuteSCSI(
1298 IN PDEVICE_OBJECT DeviceObject,
1299 IN PIRP Irp,
1300 IN ULONG RetryCount)
1301 {
1302 PCDB pCDB;
1303 NTSTATUS Status;
1304 PIO_STACK_LOCATION IoStack;
1305 PSCSI_REQUEST_BLOCK Request;
1306 PPDO_DEVICE_EXTENSION PDODeviceExtension;
1307
1308 //
1309 // get PDO device extension
1310 //
1311 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1312
1313 //
1314 // sanity check
1315 //
1316 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
1317
1318 //
1319 // get current stack location
1320 //
1321 IoStack = IoGetCurrentIrpStackLocation(Irp);
1322
1323 //
1324 // get request block
1325 //
1326 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
1327
1328 //
1329 // get SCSI command data block
1330 //
1331 pCDB = (PCDB)Request->Cdb;
1332
1333 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]);
1334
1335 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY)
1336 {
1337 //
1338 // sanity checks
1339 //
1340 ASSERT(Request->DataBuffer);
1341
1342 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength);
1343 Status = USBSTOR_SendCapacity(DeviceObject, Irp, RetryCount);
1344 }
1345 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE)
1346 {
1347 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength);
1348 ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength);
1349 ASSERT(Request->DataBuffer);
1350
1351 //
1352 // send mode sense command
1353 //
1354 Status = USBSTOR_SendModeSense(DeviceObject, Irp, RetryCount);
1355 }
1356 else if (pCDB->AsByte[0] == SCSIOP_READ_FORMATTED_CAPACITY)
1357 {
1358 DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request->DataTransferLength);
1359
1360 //
1361 // send read format capacity
1362 //
1363 Status = USBSTOR_SendFormatCapacity(DeviceObject, Irp, RetryCount);
1364 }
1365 else if (pCDB->AsByte[0] == SCSIOP_INQUIRY)
1366 {
1367 DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request->DataTransferLength);
1368
1369 //
1370 // send read format capacity
1371 //
1372 Status = USBSTOR_SendInquiry(DeviceObject, Irp, RetryCount);
1373 }
1374 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE)
1375 {
1376 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength);
1377
1378 //
1379 // send read / write command
1380 //
1381 Status = USBSTOR_SendReadWrite(DeviceObject, Irp, RetryCount);
1382 }
1383 else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL)
1384 {
1385 DPRINT("SCSIOP_MEDIUM_REMOVAL\n");
1386
1387 //
1388 // just complete the request
1389 //
1390 Request->SrbStatus = SRB_STATUS_SUCCESS;
1391 Irp->IoStatus.Status = STATUS_SUCCESS;
1392 Irp->IoStatus.Information = Request->DataTransferLength;
1393 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp);
1394 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1395
1396 //
1397 // start next request
1398 //
1399 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject);
1400
1401 return STATUS_SUCCESS;
1402 }
1403 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY)
1404 {
1405 DPRINT("SCSIOP_TEST_UNIT_READY\n");
1406
1407 //
1408 // send test unit command
1409 //
1410 Status = USBSTOR_SendTestUnit(DeviceObject, Irp, RetryCount);
1411 }
1412 else
1413 {
1414 // Unknown request. Simply forward
1415 DPRINT1("Forwarding unknown Operation Code %x\n", pCDB->AsByte[0]);
1416 Status = USBSTOR_SendUnknownRequest(DeviceObject, Irp, RetryCount);
1417 }
1418
1419 return Status;
1420 }