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 FreeItem(Context->cbw); 730 FreeItem(Context); 731 return STATUS_INSUFFICIENT_RESOURCES; 732 } 733 734 // 735 // now build the partial mdl 736 // 737 IoBuildPartialMdl(OriginalRequest->MdlAddress, Context->TransferBufferMDL, Context->TransferData, Context->TransferDataLength); 738 } 739 } 740 741 if (!Context->TransferBufferMDL) 742 { 743 // 744 // I/O paging request 745 // 746 Context->TransferBufferMDL = OriginalRequest->MdlAddress; 747 } 748 } 749 else 750 { 751 // 752 // allocate mdl for buffer, buffer must be allocated from NonPagedPool 753 // 754 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL); 755 if (!Context->TransferBufferMDL) 756 { 757 // 758 // failed to allocate MDL 759 // 760 FreeItem(Context->cbw); 761 FreeItem(Context); 762 return STATUS_INSUFFICIENT_RESOURCES; 763 } 764 765 // 766 // build mdl for nonpaged pool 767 // 768 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL); 769 } 770 } 771 else 772 { 773 // 774 // allocate mdl for buffer, buffer must be allocated from NonPagedPool 775 // 776 Context->TransferBufferMDL = IoAllocateMdl(Context->TransferData, Context->TransferDataLength, FALSE, FALSE, NULL); 777 if (!Context->TransferBufferMDL) 778 { 779 // 780 // failed to allocate MDL 781 // 782 FreeItem(Context->cbw); 783 FreeItem(Context); 784 return STATUS_INSUFFICIENT_RESOURCES; 785 } 786 787 // 788 // build mdl for nonpaged pool 789 // 790 MmBuildMdlForNonPagedPool(Context->TransferBufferMDL); 791 } 792 } 793 794 // 795 // now allocate the request 796 // 797 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 798 if (!Irp) 799 { 800 FreeItem(Context->cbw); 801 FreeItem(Context); 802 return STATUS_INSUFFICIENT_RESOURCES; 803 } 804 805 if (OriginalRequest) 806 { 807 // 808 // mark orignal irp as pending 809 // 810 IoMarkIrpPending(OriginalRequest); 811 } 812 813 // 814 // send request 815 // 816 USBSTOR_SendCBW(Context, Irp); 817 818 // 819 // done 820 // 821 return STATUS_PENDING; 822 } 823 824 NTSTATUS 825 USBSTOR_SendFormatCapacity( 826 IN PDEVICE_OBJECT DeviceObject, 827 IN PIRP Irp, 828 IN ULONG RetryCount) 829 { 830 UFI_READ_FORMAT_CAPACITY Cmd; 831 PPDO_DEVICE_EXTENSION PDODeviceExtension; 832 PIO_STACK_LOCATION IoStack; 833 PSCSI_REQUEST_BLOCK Request; 834 835 // 836 // get current stack location 837 // 838 IoStack = IoGetCurrentIrpStackLocation(Irp); 839 840 // 841 // get PDO device extension 842 // 843 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 844 845 // 846 // get request block 847 // 848 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 849 850 // 851 // initialize inquiry cmd 852 // 853 RtlZeroMemory(&Cmd, sizeof(UFI_READ_FORMAT_CAPACITY)); 854 Cmd.Code = SCSIOP_READ_FORMATTED_CAPACITY; 855 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 856 Cmd.AllocationLengthMsb = HTONS(Request->DataTransferLength & 0xFFFF) >> 8; 857 Cmd.AllocationLengthLsb = HTONS(Request->DataTransferLength & 0xFFFF) & 0xFF; 858 859 // 860 // now send the request 861 // 862 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_FORMAT_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount); 863 } 864 865 NTSTATUS 866 USBSTOR_SendInquiry( 867 IN PDEVICE_OBJECT DeviceObject, 868 IN PIRP Irp, 869 IN ULONG RetryCount) 870 { 871 UFI_INQUIRY_CMD Cmd; 872 PPDO_DEVICE_EXTENSION PDODeviceExtension; 873 PIO_STACK_LOCATION IoStack; 874 PSCSI_REQUEST_BLOCK Request; 875 876 // 877 // get current stack location 878 // 879 IoStack = IoGetCurrentIrpStackLocation(Irp); 880 881 // 882 // get request block 883 // 884 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 885 886 // 887 // get PDO device extension 888 // 889 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 890 891 // 892 // initialize inquiry cmd 893 // 894 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); 895 Cmd.Code = SCSIOP_INQUIRY; 896 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 897 Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE); 898 899 // 900 // sanity check 901 // 902 ASSERT(Request->DataTransferLength >= sizeof(UFI_INQUIRY_RESPONSE)); 903 904 // 905 // now send the request 906 // 907 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount); 908 } 909 910 NTSTATUS 911 USBSTOR_SendCapacity( 912 IN PDEVICE_OBJECT DeviceObject, 913 IN PIRP Irp, 914 IN ULONG RetryCount) 915 { 916 UFI_CAPACITY_CMD Cmd; 917 PUFI_CAPACITY_RESPONSE Response; 918 PPDO_DEVICE_EXTENSION PDODeviceExtension; 919 920 // 921 // get PDO device extension 922 // 923 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 924 925 // 926 // allocate capacity response 927 // 928 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, PAGE_SIZE); 929 if (!Response) 930 { 931 // 932 // no memory 933 // 934 return STATUS_INSUFFICIENT_RESOURCES; 935 } 936 937 // 938 // initialize capacity cmd 939 // 940 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); 941 Cmd.Code = SCSIOP_READ_CAPACITY; 942 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 943 944 // 945 // send request, response will be freed in completion routine 946 // 947 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), (PUCHAR)Response, RetryCount); 948 } 949 950 NTSTATUS 951 USBSTOR_SendModeSense( 952 IN PDEVICE_OBJECT DeviceObject, 953 IN PIRP Irp, 954 IN ULONG RetryCount) 955 { 956 #if 0 957 UFI_SENSE_CMD Cmd; 958 NTSTATUS Status; 959 PVOID Response; 960 PCBW OutControl; 961 PCDB pCDB; 962 PUFI_MODE_PARAMETER_HEADER Header; 963 #endif 964 PPDO_DEVICE_EXTENSION PDODeviceExtension; 965 PIO_STACK_LOCATION IoStack; 966 PSCSI_REQUEST_BLOCK Request; 967 968 // 969 // get PDO device extension 970 // 971 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 972 973 // 974 // sanity check 975 // 976 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 977 978 // 979 // get current stack location 980 // 981 IoStack = IoGetCurrentIrpStackLocation(Irp); 982 983 // 984 // get request block 985 // 986 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 987 988 RtlZeroMemory(Request->DataBuffer, Request->DataTransferLength); 989 Request->SrbStatus = SRB_STATUS_SUCCESS; 990 Irp->IoStatus.Information = Request->DataTransferLength; 991 Irp->IoStatus.Status = STATUS_SUCCESS; 992 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 993 IoCompleteRequest(Irp, IO_NO_INCREMENT); 994 995 // 996 // start next request 997 // 998 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); 999 1000 return STATUS_SUCCESS; 1001 1002 #if 0 1003 // 1004 // get SCSI command data block 1005 // 1006 pCDB = (PCDB)Request->Cdb; 1007 1008 // 1009 // get PDO device extension 1010 // 1011 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1012 1013 // 1014 // allocate sense response from non paged pool 1015 // 1016 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength); 1017 if (!Response) 1018 { 1019 // 1020 // no memory 1021 // 1022 return STATUS_INSUFFICIENT_RESOURCES; 1023 } 1024 1025 // 1026 // sanity check 1027 // 1028 1029 1030 // Supported pages 1031 // MODE_PAGE_ERROR_RECOVERY 1032 // MODE_PAGE_FLEXIBILE 1033 // MODE_PAGE_LUN_MAPPING 1034 // MODE_PAGE_FAULT_REPORTING 1035 // MODE_SENSE_RETURN_ALL 1036 1037 // 1038 // initialize mode sense cmd 1039 // 1040 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD)); 1041 Cmd.Code = SCSIOP_MODE_SENSE; 1042 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 1043 Cmd.PageCode = pCDB->MODE_SENSE.PageCode; 1044 Cmd.PC = pCDB->MODE_SENSE.Pc; 1045 Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength); 1046 1047 DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode); 1048 DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc); 1049 1050 // 1051 // now send mode sense cmd 1052 // 1053 Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl); 1054 if (!NT_SUCCESS(Status)) 1055 { 1056 // 1057 // failed to send CBW 1058 // 1059 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status); 1060 FreeItem(Response); 1061 ASSERT(FALSE); 1062 return Status; 1063 } 1064 1065 // 1066 // now send data block response 1067 // 1068 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response); 1069 if (!NT_SUCCESS(Status)) 1070 { 1071 // 1072 // failed to send CBW 1073 // 1074 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status); 1075 FreeItem(Response); 1076 ASSERT(FALSE); 1077 return Status; 1078 } 1079 1080 Header = (PUFI_MODE_PARAMETER_HEADER)Response; 1081 1082 // 1083 // TODO: build layout 1084 // 1085 // first struct is the header 1086 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10 1087 // 1088 // followed by 1089 // MODE_PARAMETER_BLOCK 1090 // 1091 // 1092 UNIMPLEMENTED; 1093 1094 // 1095 // send csw 1096 // 1097 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW); 1098 1099 DPRINT1("------------------------\n"); 1100 DPRINT1("CSW %p\n", &CSW); 1101 DPRINT1("Signature %x\n", CSW.Signature); 1102 DPRINT1("Tag %x\n", CSW.Tag); 1103 DPRINT1("DataResidue %x\n", CSW.DataResidue); 1104 DPRINT1("Status %x\n", CSW.Status); 1105 1106 // 1107 // FIXME: handle error 1108 // 1109 ASSERT(CSW.Status == 0); 1110 ASSERT(CSW.DataResidue == 0); 1111 1112 // 1113 // calculate transfer length 1114 // 1115 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue; 1116 1117 // 1118 // copy buffer 1119 // 1120 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength); 1121 1122 // 1123 // free item 1124 // 1125 FreeItem(OutControl); 1126 1127 // 1128 // free response 1129 // 1130 FreeItem(Response); 1131 1132 // 1133 // done 1134 // 1135 return Status; 1136 #endif 1137 } 1138 1139 NTSTATUS 1140 USBSTOR_SendReadWrite( 1141 IN PDEVICE_OBJECT DeviceObject, 1142 IN PIRP Irp, 1143 IN ULONG RetryCount) 1144 { 1145 UFI_READ_WRITE_CMD Cmd; 1146 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1147 PCDB pCDB; 1148 ULONG BlockCount, Temp; 1149 PIO_STACK_LOCATION IoStack; 1150 PSCSI_REQUEST_BLOCK Request; 1151 1152 // 1153 // get current stack location 1154 // 1155 IoStack = IoGetCurrentIrpStackLocation(Irp); 1156 1157 // 1158 // get request block 1159 // 1160 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 1161 1162 // 1163 // get SCSI command data block 1164 // 1165 pCDB = (PCDB)Request->Cdb; 1166 1167 // 1168 // get PDO device extension 1169 // 1170 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1171 1172 // 1173 // informal debug print 1174 // 1175 DPRINT("USBSTOR_SendReadWrite DataTransferLength %lu, BlockLength %lu\n", Request->DataTransferLength, PDODeviceExtension->BlockLength); 1176 1177 // 1178 // sanity check 1179 // 1180 ASSERT(PDODeviceExtension->BlockLength); 1181 1182 // 1183 // block count 1184 // 1185 BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength; 1186 1187 // 1188 // initialize read cmd 1189 // 1190 RtlZeroMemory(&Cmd, sizeof(UFI_READ_WRITE_CMD)); 1191 Cmd.Code = pCDB->AsByte[0]; 1192 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 1193 Cmd.ContiguousLogicBlocksByte0 = pCDB->CDB10.TransferBlocksMsb; 1194 Cmd.ContiguousLogicBlocksByte1 = pCDB->CDB10.TransferBlocksLsb; 1195 Cmd.LogicalBlockByte0 = pCDB->CDB10.LogicalBlockByte0; 1196 Cmd.LogicalBlockByte1 = pCDB->CDB10.LogicalBlockByte1; 1197 Cmd.LogicalBlockByte2 = pCDB->CDB10.LogicalBlockByte2; 1198 Cmd.LogicalBlockByte3 = pCDB->CDB10.LogicalBlockByte3; 1199 1200 // 1201 // sanity check 1202 // 1203 Temp = (Cmd.ContiguousLogicBlocksByte0 << 8 | Cmd.ContiguousLogicBlocksByte1); 1204 ASSERT(Temp == BlockCount); 1205 1206 DPRINT("USBSTOR_SendReadWrite BlockAddress %x%x%x%x BlockCount %lu BlockLength %lu\n", Cmd.LogicalBlockByte0, Cmd.LogicalBlockByte1, Cmd.LogicalBlockByte2, Cmd.LogicalBlockByte3, BlockCount, PDODeviceExtension->BlockLength); 1207 1208 // 1209 // send request 1210 // 1211 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_READ_WRITE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, (PUCHAR)Request->DataBuffer, RetryCount); 1212 } 1213 1214 NTSTATUS 1215 USBSTOR_SendTestUnit( 1216 IN PDEVICE_OBJECT DeviceObject, 1217 IN OUT PIRP Irp, 1218 IN ULONG RetryCount) 1219 { 1220 UFI_TEST_UNIT_CMD Cmd; 1221 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1222 PIO_STACK_LOCATION IoStack; 1223 PSCSI_REQUEST_BLOCK Request; 1224 1225 // 1226 // get current stack location 1227 // 1228 IoStack = IoGetCurrentIrpStackLocation(Irp); 1229 1230 // 1231 // get request block 1232 // 1233 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 1234 1235 // 1236 // no transfer length 1237 // 1238 ASSERT(Request->DataTransferLength == 0); 1239 1240 // 1241 // get PDO device extension 1242 // 1243 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1244 1245 // 1246 // initialize test unit cmd 1247 // 1248 RtlZeroMemory(&Cmd, sizeof(UFI_TEST_UNIT_CMD)); 1249 Cmd.Code = SCSIOP_TEST_UNIT_READY; 1250 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN); 1251 1252 // 1253 // send the request 1254 // 1255 return USBSTOR_SendRequest(DeviceObject, Irp, UFI_TEST_UNIT_CMD_LEN, (PUCHAR)&Cmd, 0, NULL, RetryCount); 1256 } 1257 1258 NTSTATUS 1259 USBSTOR_SendUnknownRequest( 1260 IN PDEVICE_OBJECT DeviceObject, 1261 IN OUT PIRP Irp, 1262 IN ULONG RetryCount) 1263 { 1264 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1265 PIO_STACK_LOCATION IoStack; 1266 PSCSI_REQUEST_BLOCK Request; 1267 UFI_UNKNOWN_CMD Cmd; 1268 1269 // 1270 // get current stack location 1271 // 1272 IoStack = IoGetCurrentIrpStackLocation(Irp); 1273 1274 // 1275 // get request block 1276 // 1277 Request = IoStack->Parameters.Others.Argument1; 1278 1279 // 1280 // get PDO device extension 1281 // 1282 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1283 1284 // 1285 // check that we're sending to the right LUN 1286 // 1287 ASSERT(Request->Cdb[1] == (PDODeviceExtension->LUN & MAX_LUN)); 1288 1289 // 1290 // sanity check 1291 // 1292 ASSERT(Request->CdbLength <= sizeof(UFI_UNKNOWN_CMD)); 1293 1294 // 1295 // initialize test unit cmd 1296 // 1297 RtlCopyMemory(&Cmd, Request->Cdb, Request->CdbLength); 1298 1299 // 1300 // send the request 1301 // 1302 return USBSTOR_SendRequest(DeviceObject, Irp, Request->CdbLength, (PUCHAR)&Cmd, Request->DataTransferLength, Request->DataBuffer, RetryCount); 1303 } 1304 1305 NTSTATUS 1306 USBSTOR_HandleExecuteSCSI( 1307 IN PDEVICE_OBJECT DeviceObject, 1308 IN PIRP Irp, 1309 IN ULONG RetryCount) 1310 { 1311 PCDB pCDB; 1312 NTSTATUS Status; 1313 PIO_STACK_LOCATION IoStack; 1314 PSCSI_REQUEST_BLOCK Request; 1315 PPDO_DEVICE_EXTENSION PDODeviceExtension; 1316 1317 // 1318 // get PDO device extension 1319 // 1320 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 1321 1322 // 1323 // sanity check 1324 // 1325 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 1326 1327 // 1328 // get current stack location 1329 // 1330 IoStack = IoGetCurrentIrpStackLocation(Irp); 1331 1332 // 1333 // get request block 1334 // 1335 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 1336 1337 // 1338 // get SCSI command data block 1339 // 1340 pCDB = (PCDB)Request->Cdb; 1341 1342 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x\n", pCDB->AsByte[0]); 1343 1344 if (pCDB->AsByte[0] == SCSIOP_READ_CAPACITY) 1345 { 1346 // 1347 // sanity checks 1348 // 1349 ASSERT(Request->DataBuffer); 1350 1351 DPRINT("SCSIOP_READ_CAPACITY Length %lu\n", Request->DataTransferLength); 1352 Status = USBSTOR_SendCapacity(DeviceObject, Irp, RetryCount); 1353 } 1354 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) 1355 { 1356 DPRINT("SCSIOP_MODE_SENSE DataTransferLength %lu\n", Request->DataTransferLength); 1357 ASSERT(pCDB->MODE_SENSE.AllocationLength == Request->DataTransferLength); 1358 ASSERT(Request->DataBuffer); 1359 1360 // 1361 // send mode sense command 1362 // 1363 Status = USBSTOR_SendModeSense(DeviceObject, Irp, RetryCount); 1364 } 1365 else if (pCDB->AsByte[0] == SCSIOP_READ_FORMATTED_CAPACITY) 1366 { 1367 DPRINT("SCSIOP_READ_FORMATTED_CAPACITY DataTransferLength %lu\n", Request->DataTransferLength); 1368 1369 // 1370 // send read format capacity 1371 // 1372 Status = USBSTOR_SendFormatCapacity(DeviceObject, Irp, RetryCount); 1373 } 1374 else if (pCDB->AsByte[0] == SCSIOP_INQUIRY) 1375 { 1376 DPRINT("SCSIOP_INQUIRY DataTransferLength %lu\n", Request->DataTransferLength); 1377 1378 // 1379 // send read format capacity 1380 // 1381 Status = USBSTOR_SendInquiry(DeviceObject, Irp, RetryCount); 1382 } 1383 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_READ || pCDB->MODE_SENSE.OperationCode == SCSIOP_WRITE) 1384 { 1385 DPRINT("SCSIOP_READ / SCSIOP_WRITE DataTransferLength %lu\n", Request->DataTransferLength); 1386 1387 // 1388 // send read / write command 1389 // 1390 Status = USBSTOR_SendReadWrite(DeviceObject, Irp, RetryCount); 1391 } 1392 else if (pCDB->AsByte[0] == SCSIOP_MEDIUM_REMOVAL) 1393 { 1394 DPRINT("SCSIOP_MEDIUM_REMOVAL\n"); 1395 1396 // 1397 // just complete the request 1398 // 1399 Request->SrbStatus = SRB_STATUS_SUCCESS; 1400 Irp->IoStatus.Status = STATUS_SUCCESS; 1401 Irp->IoStatus.Information = Request->DataTransferLength; 1402 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 1403 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1404 1405 // 1406 // start next request 1407 // 1408 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); 1409 1410 return STATUS_SUCCESS; 1411 } 1412 else if (pCDB->MODE_SENSE.OperationCode == SCSIOP_TEST_UNIT_READY) 1413 { 1414 DPRINT("SCSIOP_TEST_UNIT_READY\n"); 1415 1416 // 1417 // send test unit command 1418 // 1419 Status = USBSTOR_SendTestUnit(DeviceObject, Irp, RetryCount); 1420 } 1421 else 1422 { 1423 // Unknown request. Simply forward 1424 DPRINT1("Forwarding unknown Operation Code %x\n", pCDB->AsByte[0]); 1425 Status = USBSTOR_SendUnknownRequest(DeviceObject, Irp, RetryCount); 1426 } 1427 1428 return Status; 1429 } 1430