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