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/queue.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 VOID 18 USBSTOR_QueueInitialize( 19 PFDO_DEVICE_EXTENSION FDODeviceExtension) 20 { 21 // 22 // sanity check 23 // 24 ASSERT(FDODeviceExtension->Common.IsFDO); 25 26 // 27 // initialize queue lock 28 // 29 KeInitializeSpinLock(&FDODeviceExtension->IrpListLock); 30 31 // 32 // initialize irp list head 33 // 34 InitializeListHead(&FDODeviceExtension->IrpListHead); 35 36 // 37 // initialize event 38 // 39 KeInitializeEvent(&FDODeviceExtension->NoPendingRequests, NotificationEvent, TRUE); 40 } 41 42 VOID 43 NTAPI 44 USBSTOR_CancelIo( 45 IN PDEVICE_OBJECT DeviceObject, 46 IN PIRP Irp) 47 { 48 PFDO_DEVICE_EXTENSION FDODeviceExtension; 49 50 // 51 // get FDO device extension 52 // 53 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 54 55 // 56 // sanity check 57 // 58 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 59 ASSERT(FDODeviceExtension->Common.IsFDO); 60 61 // 62 // this IRP isn't in our list here 63 // 64 65 // 66 // now release the cancel lock 67 // 68 IoReleaseCancelSpinLock(Irp->CancelIrql); 69 70 // 71 // set cancel status 72 // 73 Irp->IoStatus.Status = STATUS_CANCELLED; 74 75 // 76 // now cancel the irp 77 // 78 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 79 IoCompleteRequest(Irp, IO_NO_INCREMENT); 80 81 // 82 // start the next one 83 // 84 USBSTOR_QueueNextRequest(DeviceObject); 85 } 86 87 VOID 88 NTAPI 89 USBSTOR_Cancel( 90 IN PDEVICE_OBJECT DeviceObject, 91 IN PIRP Irp) 92 { 93 PFDO_DEVICE_EXTENSION FDODeviceExtension; 94 95 // 96 // get FDO device extension 97 // 98 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 99 100 // 101 // sanity check 102 // 103 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 104 ASSERT(FDODeviceExtension->Common.IsFDO); 105 106 // 107 // acquire irp list lock 108 // 109 KeAcquireSpinLockAtDpcLevel(&FDODeviceExtension->IrpListLock); 110 111 // 112 // remove the irp from the list 113 // 114 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 115 116 // 117 // release irp list lock 118 // 119 KeReleaseSpinLockFromDpcLevel(&FDODeviceExtension->IrpListLock); 120 121 // 122 // now release the cancel lock 123 // 124 IoReleaseCancelSpinLock(Irp->CancelIrql); 125 126 // 127 // set cancel status 128 // 129 Irp->IoStatus.Status = STATUS_CANCELLED; 130 131 // 132 // now cancel the irp 133 // 134 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 135 IoCompleteRequest(Irp, IO_NO_INCREMENT); 136 137 // 138 // start the next one 139 // 140 USBSTOR_QueueNextRequest(DeviceObject); 141 } 142 143 BOOLEAN 144 USBSTOR_QueueAddIrp( 145 IN PDEVICE_OBJECT DeviceObject, 146 IN PIRP Irp) 147 { 148 PDRIVER_CANCEL OldDriverCancel; 149 KIRQL OldLevel; 150 PFDO_DEVICE_EXTENSION FDODeviceExtension; 151 BOOLEAN IrpListFreeze; 152 BOOLEAN SrbProcessing; 153 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 154 PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 155 156 // 157 // get FDO device extension 158 // 159 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 160 161 // 162 // sanity check 163 // 164 ASSERT(FDODeviceExtension->Common.IsFDO); 165 166 // 167 // mark irp pending 168 // 169 IoMarkIrpPending(Irp); 170 171 // 172 // acquire lock 173 // 174 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 175 176 // 177 // check if there are irp pending 178 // 179 SrbProcessing = FDODeviceExtension->IrpPendingCount != 0; 180 181 if (SrbProcessing) 182 { 183 // 184 // add irp to queue 185 // 186 InsertTailList(&FDODeviceExtension->IrpListHead, &Irp->Tail.Overlay.ListEntry); 187 } 188 189 // 190 // increment pending count 191 // 192 FDODeviceExtension->IrpPendingCount++; 193 194 195 // 196 // clear the no requests pending event 197 // 198 KeClearEvent(&FDODeviceExtension->NoPendingRequests); 199 200 // 201 // check if queue is freezed 202 // 203 IrpListFreeze = FDODeviceExtension->IrpListFreeze; 204 205 // 206 // release list lock 207 // 208 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 209 210 // 211 // synchronize with cancellations by holding the cancel lock 212 // 213 IoAcquireCancelSpinLock(&Irp->CancelIrql); 214 215 // 216 // now set the driver cancel routine 217 // 218 if (SrbProcessing) 219 { 220 ASSERT(FDODeviceExtension->ActiveSrb != NULL); 221 222 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_Cancel); 223 } 224 else 225 { 226 ASSERT(FDODeviceExtension->ActiveSrb == NULL); 227 228 FDODeviceExtension->ActiveSrb = Request; 229 OldDriverCancel = IoSetCancelRoutine(Irp, USBSTOR_CancelIo); 230 } 231 232 // 233 // check if the irp has already been cancelled 234 // 235 if (Irp->Cancel && OldDriverCancel == NULL) 236 { 237 // 238 // cancel irp 239 // 240 Irp->CancelRoutine(DeviceObject, Irp); 241 242 // 243 // irp was cancelled 244 // 245 return FALSE; 246 } 247 248 // 249 // release the cancel lock 250 // 251 IoReleaseCancelSpinLock(Irp->CancelIrql); 252 253 // 254 // if list is freezed, dont start this packet 255 // 256 DPRINT("IrpListFreeze: %lu IrpPendingCount %lu\n", IrpListFreeze, FDODeviceExtension->IrpPendingCount); 257 258 return (IrpListFreeze || SrbProcessing); 259 } 260 261 PIRP 262 USBSTOR_RemoveIrp( 263 IN PDEVICE_OBJECT DeviceObject) 264 { 265 KIRQL OldLevel; 266 PFDO_DEVICE_EXTENSION FDODeviceExtension; 267 PLIST_ENTRY Entry; 268 PIRP Irp = NULL; 269 270 // 271 // get FDO device extension 272 // 273 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 274 275 // 276 // sanity check 277 // 278 ASSERT(FDODeviceExtension->Common.IsFDO); 279 280 // 281 // acquire lock 282 // 283 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 284 285 // 286 // check if list is empty 287 // 288 if (!IsListEmpty(&FDODeviceExtension->IrpListHead)) 289 { 290 // 291 // remove entry 292 // 293 Entry = RemoveHeadList(&FDODeviceExtension->IrpListHead); 294 295 // 296 // get offset to start of irp 297 // 298 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 299 } 300 301 // 302 // release list lock 303 // 304 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 305 306 // 307 // return result 308 // 309 return Irp; 310 } 311 312 VOID 313 USBSTOR_QueueWaitForPendingRequests( 314 IN PDEVICE_OBJECT DeviceObject) 315 { 316 PFDO_DEVICE_EXTENSION FDODeviceExtension; 317 318 // 319 // get FDO device extension 320 // 321 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 322 323 // 324 // perform the wait 325 // 326 KeWaitForSingleObject(&FDODeviceExtension->NoPendingRequests, 327 Executive, 328 KernelMode, 329 FALSE, 330 NULL); 331 } 332 333 VOID 334 USBSTOR_QueueTerminateRequest( 335 IN PDEVICE_OBJECT FDODeviceObject, 336 IN PIRP Irp) 337 { 338 KIRQL OldLevel; 339 PFDO_DEVICE_EXTENSION FDODeviceExtension; 340 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 341 PSCSI_REQUEST_BLOCK Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 342 343 // 344 // get FDO device extension 345 // 346 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)FDODeviceObject->DeviceExtension; 347 348 // 349 // sanity check 350 // 351 ASSERT(FDODeviceExtension->Common.IsFDO); 352 353 // 354 // acquire lock 355 // 356 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 357 358 // 359 // decrement pending irp count 360 // 361 FDODeviceExtension->IrpPendingCount--; 362 363 // 364 // check if this was our current active SRB 365 // 366 if (FDODeviceExtension->ActiveSrb == Request) 367 { 368 // 369 // indicate processing is completed 370 // 371 FDODeviceExtension->ActiveSrb = NULL; 372 } 373 374 // 375 // Set the event if nothing else is pending 376 // 377 if (FDODeviceExtension->IrpPendingCount == 0 && 378 FDODeviceExtension->ActiveSrb == NULL) 379 { 380 KeSetEvent(&FDODeviceExtension->NoPendingRequests, IO_NO_INCREMENT, FALSE); 381 } 382 383 // 384 // release lock 385 // 386 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 387 388 } 389 390 VOID 391 USBSTOR_QueueNextRequest( 392 IN PDEVICE_OBJECT DeviceObject) 393 { 394 PFDO_DEVICE_EXTENSION FDODeviceExtension; 395 PIRP Irp; 396 PIO_STACK_LOCATION IoStack; 397 PSCSI_REQUEST_BLOCK Request; 398 399 // 400 // get pdo device extension 401 // 402 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 403 404 // 405 // sanity check 406 // 407 ASSERT(FDODeviceExtension->Common.IsFDO); 408 409 // 410 // check first if there's already a request pending or the queue is frozen 411 // 412 if (FDODeviceExtension->ActiveSrb != NULL || 413 FDODeviceExtension->IrpListFreeze) 414 { 415 // 416 // no work to do yet 417 // 418 return; 419 } 420 421 // 422 // remove first irp from list 423 // 424 Irp = USBSTOR_RemoveIrp(DeviceObject); 425 426 // 427 // is there an irp pending 428 // 429 if (!Irp) 430 { 431 // 432 // no work to do 433 // 434 IoStartNextPacket(DeviceObject, TRUE); 435 return; 436 } 437 438 // 439 // get current stack location 440 // 441 IoStack = IoGetCurrentIrpStackLocation(Irp); 442 443 // 444 // get srb 445 // 446 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 447 448 // 449 // sanity check 450 // 451 ASSERT(Request); 452 453 // 454 // set the active SRB 455 // 456 FDODeviceExtension->ActiveSrb = Request; 457 458 // 459 // start next packet 460 // 461 IoStartPacket(DeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo); 462 463 // 464 // start next request 465 // 466 IoStartNextPacket(DeviceObject, TRUE); 467 } 468 469 VOID 470 USBSTOR_QueueRelease( 471 IN PDEVICE_OBJECT DeviceObject) 472 { 473 PFDO_DEVICE_EXTENSION FDODeviceExtension; 474 PIRP Irp; 475 KIRQL OldLevel; 476 PIO_STACK_LOCATION IoStack; 477 PSCSI_REQUEST_BLOCK Request; 478 479 // 480 // get FDO device extension 481 // 482 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 483 484 // 485 // sanity check 486 // 487 ASSERT(FDODeviceExtension->Common.IsFDO); 488 489 // 490 // acquire lock 491 // 492 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 493 494 // 495 // clear freezed status 496 // 497 FDODeviceExtension->IrpListFreeze = FALSE; 498 499 // 500 // release irp list lock 501 // 502 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 503 504 // 505 // grab newest irp 506 // 507 Irp = USBSTOR_RemoveIrp(DeviceObject); 508 509 // 510 // is there an irp 511 // 512 if (!Irp) 513 { 514 // 515 // no irp 516 // 517 return; 518 } 519 520 // 521 // get current irp stack location 522 // 523 IoStack = IoGetCurrentIrpStackLocation(Irp); 524 525 // 526 // get srb 527 // 528 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1; 529 530 // 531 // start new packet 532 // 533 IoStartPacket(DeviceObject, 534 Irp, 535 &Request->QueueSortKey, 536 USBSTOR_CancelIo); 537 } 538 539 540 VOID 541 NTAPI 542 USBSTOR_StartIo( 543 PDEVICE_OBJECT DeviceObject, 544 PIRP Irp) 545 { 546 PIO_STACK_LOCATION IoStack; 547 PFDO_DEVICE_EXTENSION FDODeviceExtension; 548 PPDO_DEVICE_EXTENSION PDODeviceExtension; 549 KIRQL OldLevel; 550 BOOLEAN ResetInProgress; 551 552 DPRINT("USBSTOR_StartIo\n"); 553 554 // 555 // get FDO device extension 556 // 557 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 558 559 // 560 // sanity check 561 // 562 ASSERT(FDODeviceExtension->Common.IsFDO); 563 564 // 565 // acquire cancel spinlock 566 // 567 IoAcquireCancelSpinLock(&OldLevel); 568 569 // 570 // set cancel routine to zero 571 // 572 IoSetCancelRoutine(Irp, NULL); 573 574 // 575 // check if the irp has been cancelled 576 // 577 if (Irp->Cancel) 578 { 579 // 580 // irp has been cancelled, release cancel spinlock 581 // 582 IoReleaseCancelSpinLock(OldLevel); 583 584 // 585 // irp is cancelled 586 // 587 Irp->IoStatus.Status = STATUS_CANCELLED; 588 Irp->IoStatus.Information = 0; 589 590 // 591 // terminate request 592 // 593 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 594 595 // 596 // complete request 597 // 598 IoCompleteRequest(Irp, IO_NO_INCREMENT); 599 600 // 601 // queue next request 602 // 603 USBSTOR_QueueNextRequest(DeviceObject); 604 605 // 606 // done 607 // 608 return; 609 } 610 611 // 612 // release cancel spinlock 613 // 614 IoReleaseCancelSpinLock(OldLevel); 615 616 // 617 // acquire lock 618 // 619 KeAcquireSpinLock(&FDODeviceExtension->IrpListLock, &OldLevel); 620 621 // 622 // check reset is in progress 623 // 624 ResetInProgress = FDODeviceExtension->ResetInProgress; 625 ASSERT(ResetInProgress == FALSE); 626 627 // 628 // release lock 629 // 630 KeReleaseSpinLock(&FDODeviceExtension->IrpListLock, OldLevel); 631 632 // 633 // get current irp stack location 634 // 635 IoStack = IoGetCurrentIrpStackLocation(Irp); 636 637 // 638 // get pdo device extension 639 // 640 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 641 642 // 643 // sanity check 644 // 645 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 646 647 // 648 // is a reset in progress 649 // 650 if (ResetInProgress) 651 { 652 // 653 // hard reset is in progress 654 // 655 Irp->IoStatus.Information = 0; 656 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 657 USBSTOR_QueueTerminateRequest(DeviceObject, Irp); 658 IoCompleteRequest(Irp, IO_NO_INCREMENT); 659 return; 660 } 661 662 // 663 // execute scsi 664 // 665 USBSTOR_HandleExecuteSCSI(IoStack->DeviceObject, Irp, 0); 666 667 // 668 // FIXME: handle error 669 // 670 } 671