1 /* 2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: USB block storage device driver. 5 * COPYRIGHT: 2005-2006 James Tabor 6 * 2011-2012 Michael Martin (michael.martin@reactos.org) 7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org) 8 * 2017 Vadim Galyant 9 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org) 10 */ 11 12 #include "usbstor.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 18 static 19 NTSTATUS 20 USBSTOR_SrbStatusToNtStatus( 21 IN PSCSI_REQUEST_BLOCK Srb) 22 { 23 UCHAR SrbStatus; 24 25 SrbStatus = SRB_STATUS(Srb->SrbStatus); 26 27 switch (SrbStatus) 28 { 29 case SRB_STATUS_SUCCESS: 30 return STATUS_SUCCESS; 31 32 case SRB_STATUS_DATA_OVERRUN: 33 return STATUS_BUFFER_OVERFLOW; 34 35 case SRB_STATUS_BAD_FUNCTION: 36 case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: 37 return STATUS_INVALID_DEVICE_REQUEST; 38 39 case SRB_STATUS_INVALID_LUN: 40 case SRB_STATUS_INVALID_TARGET_ID: 41 case SRB_STATUS_NO_HBA: 42 case SRB_STATUS_NO_DEVICE: 43 return STATUS_DEVICE_DOES_NOT_EXIST; 44 45 case SRB_STATUS_TIMEOUT: 46 return STATUS_IO_TIMEOUT; 47 48 case SRB_STATUS_BUS_RESET: 49 case SRB_STATUS_COMMAND_TIMEOUT: 50 case SRB_STATUS_SELECTION_TIMEOUT: 51 return STATUS_DEVICE_NOT_CONNECTED; 52 53 default: 54 return STATUS_IO_DEVICE_ERROR; 55 } 56 } 57 58 static 59 NTSTATUS 60 USBSTOR_IssueBulkOrInterruptRequest( 61 IN PFDO_DEVICE_EXTENSION FDODeviceExtension, 62 IN PIRP Irp, 63 IN USBD_PIPE_HANDLE PipeHandle, 64 IN ULONG TransferFlags, 65 IN ULONG TransferBufferLength, 66 IN PVOID TransferBuffer, 67 IN PMDL TransferBufferMDL, 68 IN PIO_COMPLETION_ROUTINE CompletionRoutine) 69 { 70 PIO_STACK_LOCATION NextStack; 71 PIRP_CONTEXT Context = &FDODeviceExtension->CurrentIrpContext; 72 73 RtlZeroMemory(&Context->Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER)); 74 75 Context->Urb.UrbHeader.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER); 76 Context->Urb.UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; 77 78 Context->Urb.UrbBulkOrInterruptTransfer.PipeHandle = PipeHandle; 79 Context->Urb.UrbBulkOrInterruptTransfer.TransferFlags = TransferFlags; 80 Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength = TransferBufferLength; 81 Context->Urb.UrbBulkOrInterruptTransfer.TransferBuffer = TransferBuffer; 82 Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL = TransferBufferMDL; 83 84 NextStack = IoGetNextIrpStackLocation(Irp); 85 NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 86 NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; 87 NextStack->Parameters.Others.Argument1 = &Context->Urb; 88 89 IoSetCompletionRoutine(Irp, 90 CompletionRoutine, 91 FDODeviceExtension, 92 TRUE, 93 TRUE, 94 TRUE); 95 96 return IoCallDriver(FDODeviceExtension->LowerDeviceObject, Irp); 97 } 98 99 static 100 BOOLEAN 101 USBSTOR_IsCSWValid( 102 PIRP_CONTEXT Context) 103 { 104 if (Context->csw.Signature != CSW_SIGNATURE) 105 { 106 DPRINT1("[USBSTOR] Expected Signature %x but got %x\n", CSW_SIGNATURE, Context->csw.Signature); 107 return FALSE; 108 } 109 110 if (Context->csw.Tag != PtrToUlong(Context->Irp)) 111 { 112 DPRINT1("[USBSTOR] Expected Tag %Ix but got %x\n", PtrToUlong(Context->Irp), Context->csw.Tag); 113 return FALSE; 114 } 115 116 return TRUE; 117 } 118 119 static 120 NTSTATUS 121 USBSTOR_IssueRequestSense( 122 IN PFDO_DEVICE_EXTENSION FDODeviceExtension, 123 IN PIRP Irp); 124 125 IO_COMPLETION_ROUTINE USBSTOR_CSWCompletionRoutine; 126 127 NTSTATUS 128 NTAPI 129 USBSTOR_CSWCompletionRoutine( 130 PDEVICE_OBJECT DeviceObject, 131 PIRP Irp, 132 PVOID Ctx) 133 { 134 PIRP_CONTEXT Context; 135 PIO_STACK_LOCATION IoStack; 136 PPDO_DEVICE_EXTENSION PDODeviceExtension; 137 PFDO_DEVICE_EXTENSION FDODeviceExtension; 138 PSCSI_REQUEST_BLOCK Request; 139 140 DPRINT("USBSTOR_CSWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); 141 142 IoStack = IoGetCurrentIrpStackLocation(Irp); 143 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 144 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx; 145 Context = &FDODeviceExtension->CurrentIrpContext; 146 Request = IoStack->Parameters.Scsi.Srb; 147 ASSERT(Request); 148 149 // first check for Irp errors 150 if (!NT_SUCCESS(Irp->IoStatus.Status)) 151 { 152 if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID)) 153 { 154 if (Context->StallRetryCount < 2) 155 { 156 ++Context->StallRetryCount; 157 158 // clear stall and resend cbw 159 USBSTOR_QueueResetPipe(FDODeviceExtension); 160 161 return STATUS_MORE_PROCESSING_REQUIRED; 162 } 163 } 164 else 165 { 166 DPRINT1("USBSTOR_CSWCompletionRoutine: Urb.Hdr.Status - %x\n", Context->Urb.UrbHeader.Status); 167 } 168 169 goto ResetRecovery; 170 } 171 172 // now check the CSW packet validity 173 if (!USBSTOR_IsCSWValid(Context) || Context->csw.Status == CSW_STATUS_PHASE_ERROR) 174 { 175 goto ResetRecovery; 176 } 177 178 // finally check for CSW errors 179 if (Context->csw.Status == CSW_STATUS_COMMAND_PASSED) 180 { 181 // should happen only when a sense request was sent 182 if (Request != FDODeviceExtension->ActiveSrb) 183 { 184 ASSERT(IoStack->Parameters.Scsi.Srb == &Context->SenseSrb); 185 FDODeviceExtension->ActiveSrb->SenseInfoBufferLength = Request->DataTransferLength; 186 Request = FDODeviceExtension->ActiveSrb; 187 IoStack->Parameters.Scsi.Srb = Request; 188 Request->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 189 } 190 191 Irp->IoStatus.Status = USBSTOR_SrbStatusToNtStatus(Request); 192 } 193 else if (Context->csw.Status == CSW_STATUS_COMMAND_FAILED) 194 { 195 // the command is correct but with failed status - issue request sense 196 DPRINT("USBSTOR_CSWCompletionRoutine: CSW_STATUS_COMMAND_FAILED\n"); 197 198 ASSERT(FDODeviceExtension->ActiveSrb == Request); 199 200 // setting a generic error status, additional information 201 // should be read by higher-level driver from SenseInfoBuffer 202 Request->SrbStatus = SRB_STATUS_ERROR; 203 Request->ScsiStatus = 2; 204 Request->DataTransferLength = 0; 205 206 DPRINT("Flags: %x SBL: %x, buf: %p\n", Request->SrbFlags, Request->SenseInfoBufferLength, Request->SenseInfoBuffer); 207 208 if (!(Request->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && 209 Request->SenseInfoBufferLength && 210 Request->SenseInfoBuffer) 211 { 212 USBSTOR_IssueRequestSense(FDODeviceExtension, Irp); 213 return STATUS_MORE_PROCESSING_REQUIRED; 214 } 215 216 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 217 } 218 219 Irp->IoStatus.Information = Request->DataTransferLength; 220 221 // terminate current request 222 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 223 USBSTOR_QueueNextRequest(PDODeviceExtension->LowerDeviceObject); 224 225 return STATUS_CONTINUE_COMPLETION; 226 227 ResetRecovery: 228 229 Request = FDODeviceExtension->ActiveSrb; 230 IoStack->Parameters.Scsi.Srb = Request; 231 Irp->IoStatus.Information = 0; 232 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 233 Request->SrbStatus = SRB_STATUS_BUS_RESET; 234 235 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 236 USBSTOR_QueueResetDevice(FDODeviceExtension); 237 238 return STATUS_CONTINUE_COMPLETION; 239 } 240 241 NTSTATUS 242 USBSTOR_SendCSWRequest( 243 PFDO_DEVICE_EXTENSION FDODeviceExtension, 244 PIRP Irp) 245 { 246 return USBSTOR_IssueBulkOrInterruptRequest(FDODeviceExtension, 247 Irp, 248 FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle, 249 USBD_TRANSFER_DIRECTION_IN, 250 sizeof(CSW), 251 &FDODeviceExtension->CurrentIrpContext.csw, 252 NULL, 253 USBSTOR_CSWCompletionRoutine); 254 } 255 256 IO_COMPLETION_ROUTINE USBSTOR_DataCompletionRoutine; 257 258 NTSTATUS 259 NTAPI 260 USBSTOR_DataCompletionRoutine( 261 PDEVICE_OBJECT DeviceObject, 262 PIRP Irp, 263 PVOID Ctx) 264 { 265 PIRP_CONTEXT Context; 266 PIO_STACK_LOCATION IoStack; 267 PSCSI_REQUEST_BLOCK Request; 268 PFDO_DEVICE_EXTENSION FDODeviceExtension; 269 PPDO_DEVICE_EXTENSION PDODeviceExtension; 270 271 DPRINT("USBSTOR_DataCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); 272 273 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx; 274 Context = &FDODeviceExtension->CurrentIrpContext; 275 IoStack = IoGetCurrentIrpStackLocation(Irp); 276 Request = IoStack->Parameters.Scsi.Srb; 277 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 278 279 // for Sense Request a partial MDL was already freed (if existed) 280 if (Request == FDODeviceExtension->ActiveSrb && 281 Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL != Irp->MdlAddress) 282 { 283 IoFreeMdl(Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferMDL); 284 } 285 286 if (NT_SUCCESS(Irp->IoStatus.Status)) 287 { 288 if (Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength < Request->DataTransferLength) 289 { 290 Request->SrbStatus = SRB_STATUS_DATA_OVERRUN; 291 } 292 else 293 { 294 Request->SrbStatus = SRB_STATUS_SUCCESS; 295 } 296 297 Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength; 298 USBSTOR_SendCSWRequest(FDODeviceExtension, Irp); 299 } 300 else if (USBD_STATUS(Context->Urb.UrbHeader.Status) == USBD_STATUS(USBD_STATUS_STALL_PID)) 301 { 302 ++Context->StallRetryCount; 303 304 Request->SrbStatus = SRB_STATUS_DATA_OVERRUN; 305 Request->DataTransferLength = Context->Urb.UrbBulkOrInterruptTransfer.TransferBufferLength; 306 307 // clear stall and resend cbw 308 USBSTOR_QueueResetPipe(FDODeviceExtension); 309 } 310 else 311 { 312 Irp->IoStatus.Information = 0; 313 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 314 Request->SrbStatus = SRB_STATUS_BUS_RESET; 315 316 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 317 USBSTOR_QueueResetDevice(FDODeviceExtension); 318 319 return STATUS_CONTINUE_COMPLETION; 320 } 321 322 return STATUS_MORE_PROCESSING_REQUIRED; 323 } 324 325 IO_COMPLETION_ROUTINE USBSTOR_CBWCompletionRoutine; 326 327 NTSTATUS 328 NTAPI 329 USBSTOR_CBWCompletionRoutine( 330 PDEVICE_OBJECT DeviceObject, 331 PIRP Irp, 332 PVOID Ctx) 333 { 334 PIO_STACK_LOCATION IoStack; 335 PSCSI_REQUEST_BLOCK Request; 336 PPDO_DEVICE_EXTENSION PDODeviceExtension; 337 PFDO_DEVICE_EXTENSION FDODeviceExtension; 338 USBD_PIPE_HANDLE PipeHandle; 339 ULONG TransferFlags; 340 PMDL Mdl = NULL; 341 PVOID TransferBuffer = NULL; 342 343 DPRINT("USBSTOR_CBWCompletionRoutine Irp %p Ctx %p Status %x\n", Irp, Ctx, Irp->IoStatus.Status); 344 345 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)Ctx; 346 IoStack = IoGetCurrentIrpStackLocation(Irp); 347 Request = IoStack->Parameters.Scsi.Srb; 348 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 349 350 if (!NT_SUCCESS(Irp->IoStatus.Status)) 351 { 352 goto ResetRecovery; 353 } 354 355 // a request without the buffer AND not a sense request 356 // for a sense request we provide just a TransferBuffer, an Mdl will be allocated by usbport (see below) 357 if (!Irp->MdlAddress && Request == FDODeviceExtension->ActiveSrb) 358 { 359 Request->SrbStatus = SRB_STATUS_SUCCESS; 360 USBSTOR_SendCSWRequest(FDODeviceExtension, Irp); 361 return STATUS_MORE_PROCESSING_REQUIRED; 362 } 363 364 // a request with the data buffer 365 366 if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_IN) 367 { 368 PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle; 369 TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; 370 } 371 else if ((Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_DATA_OUT) 372 { 373 PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle; 374 TransferFlags = USBD_TRANSFER_DIRECTION_OUT; 375 } 376 else 377 { 378 // we check the validity of a request in disk.c so we should never be here 379 DPRINT1("Warning: shouldn't be here\n"); 380 goto ResetRecovery; 381 } 382 383 // if it is not a Sense Request 384 if (Request == FDODeviceExtension->ActiveSrb) 385 { 386 if (MmGetMdlVirtualAddress(Irp->MdlAddress) == Request->DataBuffer) 387 { 388 Mdl = Irp->MdlAddress; 389 } 390 else 391 { 392 Mdl = IoAllocateMdl(Request->DataBuffer, 393 Request->DataTransferLength, 394 FALSE, 395 FALSE, 396 NULL); 397 398 if (Mdl) 399 { 400 IoBuildPartialMdl(Irp->MdlAddress, 401 Mdl, 402 Request->DataBuffer, 403 Request->DataTransferLength); 404 } 405 } 406 407 if (!Mdl) 408 { 409 DPRINT1("USBSTOR_CBWCompletionRoutine: Mdl - %p\n", Mdl); 410 goto ResetRecovery; 411 } 412 } 413 else 414 { 415 ASSERT(Request->DataBuffer); 416 TransferBuffer = Request->DataBuffer; 417 } 418 419 USBSTOR_IssueBulkOrInterruptRequest(FDODeviceExtension, 420 Irp, 421 PipeHandle, 422 TransferFlags, 423 Request->DataTransferLength, 424 TransferBuffer, 425 Mdl, 426 USBSTOR_DataCompletionRoutine); 427 428 return STATUS_MORE_PROCESSING_REQUIRED; 429 430 ResetRecovery: 431 Request = FDODeviceExtension->ActiveSrb; 432 IoStack->Parameters.Scsi.Srb = Request; 433 Irp->IoStatus.Information = 0; 434 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; 435 Request->SrbStatus = SRB_STATUS_BUS_RESET; 436 437 USBSTOR_QueueTerminateRequest(PDODeviceExtension->LowerDeviceObject, Irp); 438 USBSTOR_QueueResetDevice(FDODeviceExtension); 439 440 return STATUS_CONTINUE_COMPLETION; 441 } 442 443 VOID 444 DumpCBW( 445 PUCHAR Block) 446 { 447 DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 448 Block[0] & 0xFF, Block[1] & 0xFF, Block[2] & 0xFF, Block[3] & 0xFF, Block[4] & 0xFF, Block[5] & 0xFF, Block[6] & 0xFF, Block[7] & 0xFF, Block[8] & 0xFF, Block[9] & 0xFF, 449 Block[10] & 0xFF, Block[11] & 0xFF, Block[12] & 0xFF, Block[13] & 0xFF, Block[14] & 0xFF, Block[15] & 0xFF, Block[16] & 0xFF, Block[17] & 0xFF, Block[18] & 0xFF, Block[19] & 0xFF, 450 Block[20] & 0xFF, Block[21] & 0xFF, Block[22] & 0xFF, Block[23] & 0xFF, Block[24] & 0xFF, Block[25] & 0xFF, Block[26] & 0xFF, Block[27] & 0xFF, Block[28] & 0xFF, Block[29] & 0xFF, 451 Block[30] & 0xFF); 452 } 453 454 static 455 NTSTATUS 456 USBSTOR_SendCBWRequest( 457 IN PFDO_DEVICE_EXTENSION FDODeviceExtension, 458 IN PIRP Irp) 459 { 460 PPDO_DEVICE_EXTENSION PDODeviceExtension; 461 PIO_STACK_LOCATION IoStack; 462 PSCSI_REQUEST_BLOCK Request; 463 PIRP_CONTEXT Context = &FDODeviceExtension->CurrentIrpContext; 464 465 RtlZeroMemory(&Context->cbw, sizeof(CBW)); 466 RtlZeroMemory(&Context->Urb, sizeof(URB)); 467 468 IoStack = IoGetCurrentIrpStackLocation(Irp); 469 PDODeviceExtension = IoStack->DeviceObject->DeviceExtension; 470 Request = IoStack->Parameters.Scsi.Srb; 471 472 // Make a CBW structure from SCSI request block 473 Context->cbw.Signature = CBW_SIGNATURE; 474 Context->cbw.Tag = PtrToUlong(Irp); 475 Context->cbw.DataTransferLength = Request->DataTransferLength; 476 Context->cbw.Flags = ((UCHAR)Request->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) << 1; 477 Context->cbw.LUN = PDODeviceExtension->LUN; 478 Context->cbw.CommandBlockLength = Request->CdbLength; 479 480 RtlCopyMemory(&Context->cbw.CommandBlock, Request->Cdb, Request->CdbLength); 481 482 DPRINT("CBW for IRP %p\n", Irp); 483 DumpCBW((PUCHAR)&Context->cbw); 484 485 // initialize rest of context 486 Context->Irp = Irp; 487 Context->StallRetryCount = 0; 488 489 return USBSTOR_IssueBulkOrInterruptRequest( 490 FDODeviceExtension, 491 Irp, 492 FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle, 493 USBD_TRANSFER_DIRECTION_OUT, 494 sizeof(CBW), 495 &Context->cbw, 496 NULL, 497 USBSTOR_CBWCompletionRoutine); 498 } 499 500 static 501 NTSTATUS 502 USBSTOR_IssueRequestSense( 503 IN PFDO_DEVICE_EXTENSION FDODeviceExtension, 504 IN PIRP Irp) 505 { 506 PIO_STACK_LOCATION IoStack; 507 PSCSI_REQUEST_BLOCK CurrentSrb; 508 PSCSI_REQUEST_BLOCK SenseSrb; 509 510 DPRINT("USBSTOR_IssueRequestSense: \n"); 511 512 CurrentSrb = FDODeviceExtension->ActiveSrb; 513 SenseSrb = &FDODeviceExtension->CurrentIrpContext.SenseSrb; 514 IoStack = IoGetCurrentIrpStackLocation(Irp); 515 IoStack->Parameters.Scsi.Srb = SenseSrb; 516 517 RtlZeroMemory(SenseSrb, sizeof(*SenseSrb)); 518 519 SenseSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; 520 SenseSrb->Length = sizeof(*SenseSrb); 521 SenseSrb->CdbLength = CDB6GENERIC_LENGTH; 522 SenseSrb->SrbFlags = SRB_FLAGS_DATA_IN | 523 SRB_FLAGS_NO_QUEUE_FREEZE | 524 SRB_FLAGS_DISABLE_AUTOSENSE; 525 526 ASSERT(CurrentSrb->SenseInfoBufferLength); 527 ASSERT(CurrentSrb->SenseInfoBuffer); 528 DPRINT("SenseInfoBuffer %x, SenseInfoBufferLength %x\n", CurrentSrb->SenseInfoBuffer, CurrentSrb->SenseInfoBufferLength); 529 530 SenseSrb->DataTransferLength = CurrentSrb->SenseInfoBufferLength; 531 SenseSrb->DataBuffer = CurrentSrb->SenseInfoBuffer; 532 533 SrbGetCdb(SenseSrb)->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_SENSE; 534 SrbGetCdb(SenseSrb)->AsByte[4] = CurrentSrb->SenseInfoBufferLength; 535 536 return USBSTOR_SendCBWRequest(FDODeviceExtension, Irp); 537 } 538 539 NTSTATUS 540 USBSTOR_HandleExecuteSCSI( 541 IN PDEVICE_OBJECT DeviceObject, 542 IN PIRP Irp) 543 { 544 PIO_STACK_LOCATION IoStack; 545 PSCSI_REQUEST_BLOCK Request; 546 PPDO_DEVICE_EXTENSION PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 547 548 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 549 550 IoStack = IoGetCurrentIrpStackLocation(Irp); 551 Request = IoStack->Parameters.Scsi.Srb; 552 553 DPRINT("USBSTOR_HandleExecuteSCSI Operation Code %x, Length %lu\n", SrbGetCdb(Request)->CDB10.OperationCode, Request->DataTransferLength); 554 555 // check that we're sending to the right LUN 556 ASSERT(SrbGetCdb(Request)->CDB10.LogicalUnitNumber == PDODeviceExtension->LUN); 557 558 return USBSTOR_SendCBWRequest(PDODeviceExtension->LowerDeviceObject->DeviceExtension, Irp); 559 } 560