1 /*++ 2 3 Copyright (C) Microsoft Corporation, 1991 - 1999 4 5 Module Name: 6 7 obsolete.c 8 9 Abstract: 10 11 THESE ARE EXPORTED CLASSPNP FUNCTIONS (and their subroutines) 12 WHICH ARE NOW OBSOLETE. 13 BUT WE NEED TO KEEP THEM AROUND FOR LEGACY REASONS. 14 15 Environment: 16 17 kernel mode only 18 19 Notes: 20 21 22 Revision History: 23 24 --*/ 25 26 #include "classp.h" 27 28 PIRP NTAPI ClassRemoveCScanList(IN PCSCAN_LIST List); 29 VOID NTAPI ClasspInitializeCScanList(IN PCSCAN_LIST List); 30 31 #ifdef ALLOC_PRAGMA 32 #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList) 33 #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList) 34 #endif 35 36 typedef struct _CSCAN_LIST_ENTRY { 37 LIST_ENTRY Entry; 38 ULONGLONG BlockNumber; 39 } CSCAN_LIST_ENTRY, *PCSCAN_LIST_ENTRY; 40 41 /* 42 * ClassSplitRequest 43 * 44 * This is a legacy exported function. 45 * It is called by storage miniport driver that have their own 46 * StartIo routine when the transfer size is too large for the hardware. 47 * We map it to our new read/write handler. 48 */ 49 VOID NTAPI ClassSplitRequest(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN ULONG MaximumBytes) 50 { 51 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension; 52 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; 53 54 if (MaximumBytes > fdoData->HwMaxXferLen) { 55 DBGERR(("ClassSplitRequest - driver requesting split to size that " 56 "hardware is unable to handle!\n")); 57 } 58 59 if (MaximumBytes < fdoData->HwMaxXferLen){ 60 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen " 61 "than required")); 62 fdoData->HwMaxXferLen = MAX(MaximumBytes, PAGE_SIZE); 63 } 64 65 ServiceTransferRequest(Fdo, Irp); 66 } 67 68 /*++//////////////////////////////////////////////////////////////////////////// 69 70 ClassIoCompleteAssociated() 71 72 Routine Description: 73 74 This routine executes when the port driver has completed a request. 75 It looks at the SRB status in the completing SRB and if not success 76 it checks for valid request sense buffer information. If valid, the 77 info is used to update status with more precise message of type of 78 error. This routine deallocates the SRB. This routine is used for 79 requests which were build by split request. After it has processed 80 the request it decrements the Irp count in the master Irp. If the 81 count goes to zero then the master Irp is completed. 82 83 Arguments: 84 85 Fdo - Supplies the functional device object which represents the target. 86 87 Irp - Supplies the Irp which has completed. 88 89 Context - Supplies a pointer to the SRB. 90 91 Return Value: 92 93 NT status 94 95 --*/ 96 NTSTATUS 97 NTAPI 98 ClassIoCompleteAssociated( 99 IN PDEVICE_OBJECT Fdo, 100 IN PIRP Irp, 101 IN PVOID Context 102 ) 103 { 104 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 105 106 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 107 PSCSI_REQUEST_BLOCK srb = Context; 108 109 PIRP originalIrp = Irp->AssociatedIrp.MasterIrp; 110 LONG irpCount; 111 112 NTSTATUS status; 113 BOOLEAN retry; 114 115 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !")); 116 117 // 118 // Check SRB status for success of completing request. 119 // 120 121 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 122 123 ULONG retryInterval; 124 125 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb)); 126 127 // 128 // Release the queue if it is frozen. 129 // 130 131 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 132 ClassReleaseQueue(Fdo); 133 } 134 135 retry = ClassInterpretSenseInfo( 136 Fdo, 137 srb, 138 irpStack->MajorFunction, 139 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? 140 irpStack->Parameters.DeviceIoControl.IoControlCode : 141 0, 142 MAXIMUM_RETRIES - 143 ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4), 144 &status, 145 &retryInterval); 146 147 // 148 // If the status is verified required and the this request 149 // should bypass verify required then retry the request. 150 // 151 152 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 153 status == STATUS_VERIFY_REQUIRED) { 154 155 status = STATUS_IO_DEVICE_ERROR; 156 retry = TRUE; 157 } 158 159 if (retry && ((*(PCHAR*)&irpStack->Parameters.Others.Argument4)--)) { 160 161 // 162 // Retry request. If the class driver has supplied a StartIo, 163 // call it directly for retries. 164 // 165 166 DebugPrint((1, "Retry request %p\n", Irp)); 167 168 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) { 169 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb); 170 } 171 172 RetryRequest(Fdo, Irp, srb, TRUE, retryInterval); 173 174 return STATUS_MORE_PROCESSING_REQUIRED; 175 } 176 177 } else { 178 179 // 180 // Set status for successful request. 181 // 182 183 status = STATUS_SUCCESS; 184 185 } // end if (SRB_STATUS(srb->SrbStatus) ... 186 187 // 188 // Return SRB to list. 189 // 190 191 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) { 192 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb); 193 } 194 195 ClassFreeOrReuseSrb(fdoExtension, srb); 196 197 // 198 // Set status in completing IRP. 199 // 200 201 Irp->IoStatus.Status = status; 202 203 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp)); 204 205 // 206 // Get next stack location. This original request is unused 207 // except to keep track of the completing partial IRPs so the 208 // stack location is valid. 209 // 210 211 irpStack = IoGetNextIrpStackLocation(originalIrp); 212 213 // 214 // Update status only if error so that if any partial transfer 215 // completes with error, then the original IRP will return with 216 // error. If any of the asynchronous partial transfer IRPs fail, 217 // with an error then the original IRP will return 0 bytes transfered. 218 // This is an optimization for successful transfers. 219 // 220 221 if (!NT_SUCCESS(status)) { 222 223 originalIrp->IoStatus.Status = status; 224 originalIrp->IoStatus.Information = 0; 225 226 // 227 // Set the hard error if necessary. 228 // 229 230 if (IoIsErrorUserInduced(status)) { 231 232 // 233 // Store DeviceObject for filesystem. 234 // 235 236 IoSetHardErrorOrVerifyDevice(originalIrp, Fdo); 237 } 238 } 239 240 // 241 // Decrement and get the count of remaining IRPs. 242 // 243 244 irpCount = InterlockedDecrement( 245 (PLONG)&irpStack->Parameters.Others.Argument1); 246 247 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n", 248 irpCount)); 249 250 // 251 // Ensure that the irpCount doesn't go negative. This was happening once 252 // because classpnp would get confused if it ran out of resources when 253 // splitting the request. 254 // 255 256 ASSERT(irpCount >= 0); 257 258 if (irpCount == 0) { 259 260 // 261 // All partial IRPs have completed. 262 // 263 264 DebugPrint((2, 265 "ClassIoCompleteAssociated: All partial IRPs complete %p\n", 266 originalIrp)); 267 268 if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) { 269 270 // 271 // Acquire a separate copy of the remove lock so the debugging code 272 // works okay and we don't have to hold up the completion of this 273 // irp until after we start the next packet(s). 274 // 275 276 KIRQL oldIrql; 277 UCHAR uniqueAddress; 278 ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress); 279 ClassReleaseRemoveLock(Fdo, originalIrp); 280 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT); 281 282 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 283 IoStartNextPacket(Fdo, FALSE); 284 KeLowerIrql(oldIrql); 285 286 ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress); 287 288 } else { 289 290 // 291 // just complete this request 292 // 293 294 ClassReleaseRemoveLock(Fdo, originalIrp); 295 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT); 296 297 } 298 299 } 300 301 // 302 // Deallocate IRP and indicate the I/O system should not attempt any more 303 // processing. 304 // 305 306 IoFreeIrp(Irp); 307 return STATUS_MORE_PROCESSING_REQUIRED; 308 309 } // end ClassIoCompleteAssociated() 310 311 /*++//////////////////////////////////////////////////////////////////////////// 312 313 RetryRequest() 314 315 Routine Description: 316 317 This is a wrapper around the delayed retry DPC routine, RetryRequestDPC. 318 This reinitializes the necessary fields, queues the request, and sets 319 a timer to call the DPC if someone hasn't already done so. 320 321 Arguments: 322 323 DeviceObject - Supplies the device object associated with this request. 324 325 Irp - Supplies the request to be retried. 326 327 Srb - Supplies a Pointer to the SCSI request block to be retied. 328 329 Associated - Indicates this is an associated Irp created by split request. 330 331 RetryInterval - How long, in seconds, before retrying the request. 332 333 Return Value: 334 335 None 336 337 --*/ 338 VOID 339 NTAPI 340 RetryRequest( 341 PDEVICE_OBJECT DeviceObject, 342 PIRP Irp, 343 PSCSI_REQUEST_BLOCK Srb, 344 BOOLEAN Associated, 345 ULONG RetryInterval 346 ) 347 { 348 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 349 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 350 ULONG transferByteCount; 351 352 // This function is obsolete but is still used by some of our class drivers. 353 // DBGWARN(("RetryRequest is OBSOLETE !")); 354 355 // 356 // Determine the transfer count of the request. If this is a read or a 357 // write then the transfer count is in the Irp stack. Otherwise assume 358 // the MDL contains the correct length. If there is no MDL then the 359 // transfer length must be zero. 360 // 361 362 if (currentIrpStack->MajorFunction == IRP_MJ_READ || 363 currentIrpStack->MajorFunction == IRP_MJ_WRITE) { 364 365 transferByteCount = currentIrpStack->Parameters.Read.Length; 366 367 } else if (Irp->MdlAddress != NULL) { 368 369 // 370 // Note this assumes that only read and write requests are spilt and 371 // other request do not need to be. If the data buffer address in 372 // the MDL and the SRB don't match then transfer length is most 373 // likely incorrect. 374 // 375 376 ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress)); 377 transferByteCount = Irp->MdlAddress->ByteCount; 378 379 } else { 380 381 transferByteCount = 0; 382 } 383 384 // 385 // this is a safety net. this should not normally be hit, since we are 386 // not guaranteed to be an fdoExtension 387 // 388 389 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); 390 391 // 392 // Reset byte count of transfer in SRB Extension. 393 // 394 395 Srb->DataTransferLength = transferByteCount; 396 397 // 398 // Zero SRB statuses. 399 // 400 401 Srb->SrbStatus = Srb->ScsiStatus = 0; 402 403 // 404 // Set the no disconnect flag, disable synchronous data transfers and 405 // disable tagged queuing. This fixes some errors. 406 // NOTE: Cannot clear these flags, just add to them 407 // 408 409 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT); 410 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); 411 CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE); 412 413 Srb->QueueTag = SP_UNTAGGED; 414 415 // 416 // Set up major SCSI function. 417 // 418 419 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 420 421 // 422 // Save SRB address in next stack for port driver. 423 // 424 425 nextIrpStack->Parameters.Scsi.Srb = Srb; 426 427 428 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); 429 430 { 431 LARGE_INTEGER retry100ns; 432 retry100ns.QuadPart = RetryInterval; // seconds 433 retry100ns.QuadPart *= (LONGLONG)1000 * 1000 * 10; 434 435 ClassRetryRequest(DeviceObject, Irp, retry100ns); 436 } 437 return; 438 } // end RetryRequest() 439 440 /*++ 441 442 ClassBuildRequest() 443 444 Routine Description: 445 446 This routine allocates an SRB for the specified request then calls 447 ClasspBuildRequestEx to create a SCSI operation to read or write the device. 448 449 If no SRB is available then the request will be queued to be issued later 450 when requests are available. Drivers which do not want the queueing 451 behavior should allocate the SRB themselves and call ClasspBuildRequestEx 452 to issue it. 453 454 Arguments: 455 456 Fdo - Supplies the functional device object associated with this request. 457 458 Irp - Supplies the request to be retried. 459 460 Note: 461 462 If the IRP is for a disk transfer, the byteoffset field 463 will already have been adjusted to make it relative to 464 the beginning of the disk. 465 466 467 Return Value: 468 469 NT Status 470 471 --*/ 472 NTSTATUS 473 NTAPI 474 ClassBuildRequest( 475 PDEVICE_OBJECT Fdo, 476 PIRP Irp 477 ) 478 { 479 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 480 481 PSCSI_REQUEST_BLOCK srb; 482 483 // This function is obsolete, but still called by CDROM.SYS . 484 // DBGWARN(("ClassBuildRequest is OBSOLETE !")); 485 486 // 487 // Allocate an Srb. 488 // 489 490 srb = ClasspAllocateSrb(fdoExtension); 491 492 if(srb == NULL) { 493 return STATUS_INSUFFICIENT_RESOURCES; 494 } 495 496 ClasspBuildRequestEx(fdoExtension, Irp, srb); 497 return STATUS_SUCCESS; 498 499 } // end ClassBuildRequest() 500 501 VOID 502 NTAPI 503 ClasspBuildRequestEx( 504 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 505 IN PIRP Irp, 506 IN PSCSI_REQUEST_BLOCK Srb 507 ) 508 509 /*++ 510 511 ClasspBuildRequestEx() 512 513 Routine Description: 514 515 This routine allocates and builds an Srb for a read or write request. 516 The block address and length are supplied by the Irp. The retry count 517 is stored in the current stack for use by ClassIoComplete which 518 processes these requests when they complete. The Irp is ready to be 519 passed to the port driver when this routine returns. 520 521 Arguments: 522 523 FdoExtension - Supplies the device extension associated with this request. 524 525 Irp - Supplies the request to be issued. 526 527 Srb - Supplies an SRB to be used for the request. 528 529 Note: 530 531 If the IRP is for a disk transfer, the byteoffset field 532 will already have been adjusted to make it relative to 533 the beginning of the disk. 534 535 536 Return Value: 537 538 NT Status 539 540 --*/ 541 { 542 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 543 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 544 545 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; 546 547 PCDB cdb; 548 ULONG logicalBlockAddress; 549 USHORT transferBlocks; 550 551 // This function is obsolete, but still called by CDROM.SYS . 552 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !")); 553 554 // 555 // Prepare the SRB. 556 // 557 558 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); 559 560 // 561 // Calculate relative sector address. 562 // 563 564 logicalBlockAddress = 565 (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, 566 FdoExtension->SectorShift)); 567 568 // 569 // Write length to SRB. 570 // 571 572 Srb->Length = sizeof(SCSI_REQUEST_BLOCK); 573 574 // 575 // Set up IRP Address. 576 // 577 578 Srb->OriginalRequest = Irp; 579 580 // 581 // Set up target ID and logical unit number. 582 // 583 584 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 585 Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); 586 587 // 588 // Save byte count of transfer in SRB Extension. 589 // 590 591 Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; 592 593 // 594 // Initialize the queue actions field. 595 // 596 597 Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; 598 599 // 600 // Queue sort key is Relative Block Address. 601 // 602 603 Srb->QueueSortKey = logicalBlockAddress; 604 605 // 606 // Indicate auto request sense by specifying buffer and size. 607 // 608 609 Srb->SenseInfoBuffer = FdoExtension->SenseData; 610 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 611 612 // 613 // Set timeout value of one unit per 64k bytes of data. 614 // 615 616 Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) * 617 FdoExtension->TimeOutValue; 618 619 // 620 // Zero statuses. 621 // 622 623 Srb->SrbStatus = Srb->ScsiStatus = 0; 624 Srb->NextSrb = 0; 625 626 // 627 // Indicate that 10-byte CDB's will be used. 628 // 629 630 Srb->CdbLength = 10; 631 632 // 633 // Fill in CDB fields. 634 // 635 636 cdb = (PCDB)Srb->Cdb; 637 638 transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> 639 FdoExtension->SectorShift); 640 641 // 642 // Move little endian values into CDB in big endian format. 643 // 644 645 cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; 646 cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; 647 cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; 648 cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; 649 650 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; 651 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; 652 653 // 654 // Set transfer direction flag and Cdb command. 655 // 656 657 if (currentIrpStack->MajorFunction == IRP_MJ_READ) { 658 659 DebugPrint((3, "ClassBuildRequest: Read Command\n")); 660 661 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); 662 cdb->CDB10.OperationCode = SCSIOP_READ; 663 664 } else { 665 666 DebugPrint((3, "ClassBuildRequest: Write Command\n")); 667 668 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT); 669 cdb->CDB10.OperationCode = SCSIOP_WRITE; 670 } 671 672 // 673 // If this is not a write-through request, then allow caching. 674 // 675 676 if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) { 677 678 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); 679 680 } else { 681 682 // 683 // If write caching is enable then force media access in the 684 // cdb. 685 // 686 687 if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) { 688 cdb->CDB10.ForceUnitAccess = TRUE; 689 } 690 } 691 692 if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) { 693 SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING); 694 } 695 696 // 697 // OR in the default flags from the device object. 698 // 699 700 SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags); 701 702 // 703 // Set up major SCSI function. 704 // 705 706 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 707 708 // 709 // Save SRB address in next stack for port driver. 710 // 711 712 nextIrpStack->Parameters.Scsi.Srb = Srb; 713 714 // 715 // Save retry count in current IRP stack. 716 // 717 718 currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; 719 720 // 721 // Set up IoCompletion routine address. 722 // 723 724 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); 725 726 } 727 728 VOID NTAPI ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry) 729 { 730 PCSCAN_LIST_ENTRY t; 731 732 DBGWARN(("ClasspInsertCScanList is OBSOLETE !")); 733 734 // 735 // Iterate through the list. Insert this entry in the sorted list in 736 // order (after other requests for the same block). At each stop if 737 // blockNumber(Entry) >= blockNumber(t) then move on. 738 // 739 740 for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink; 741 t != (PCSCAN_LIST_ENTRY) ListHead; 742 t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) { 743 744 if(Entry->BlockNumber < t->BlockNumber) { 745 746 // 747 // Set the pointers in entry to the right location. 748 // 749 750 Entry->Entry.Flink = &(t->Entry); 751 Entry->Entry.Blink = t->Entry.Blink; 752 753 // 754 // Set the pointers in the surrounding elements to refer to us. 755 // 756 757 t->Entry.Blink->Flink = &(Entry->Entry); 758 t->Entry.Blink = &(Entry->Entry); 759 return; 760 } 761 } 762 763 // 764 // Insert this entry at the tail of the list. If the list was empty this 765 // will also be the head of the list. 766 // 767 768 InsertTailList(ListHead, &(Entry->Entry)); 769 770 } 771 772 VOID NTAPI ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority) 773 /*++ 774 775 Routine Description: 776 777 This routine inserts an entry into the CScan list based on it's block number 778 and priority. It is assumed that the caller is providing synchronization 779 to the access of the list. 780 781 Low priority requests are always scheduled to run on the next sweep across 782 the disk. Normal priority requests will be inserted into the current or 783 next sweep based on the standard C-SCAN algorithm. 784 785 Arguments: 786 787 List - the list to insert into 788 789 Irp - the irp to be inserted. 790 791 BlockNumber - the block number for this request. 792 793 LowPriority - indicates that the request is lower priority and should be 794 done on the next sweep across the disk. 795 796 Return Value: 797 798 none 799 800 --*/ 801 { 802 PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext; 803 804 DBGWARN(("ClassInsertCScanList is OBSOLETE !")); 805 806 // 807 // Set the block number in the entry. We need this to keep the list sorted. 808 // 809 entry->BlockNumber = BlockNumber; 810 811 // 812 // If it's a normal priority request and further down the disk than our 813 // current position then insert this entry into the current sweep. 814 // 815 816 if ((LowPriority == FALSE) && (BlockNumber > List->BlockNumber)) { 817 ClasspInsertCScanList(&(List->CurrentSweep), entry); 818 } else { 819 ClasspInsertCScanList(&(List->NextSweep), entry); 820 } 821 return; 822 } 823 824 VOID NTAPI ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 825 IN PSCSI_REQUEST_BLOCK Srb) 826 /*++ 827 828 Routine Description: 829 830 This routine will attempt to reuse the provided SRB to start a blocked 831 read/write request. 832 If there is no need to reuse the request it will be returned 833 to the SRB lookaside list. 834 835 Arguments: 836 837 Fdo - the device extension 838 839 Srb - the SRB which is to be reused or freed. 840 841 Return Value: 842 843 none. 844 845 --*/ 846 847 { 848 PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension; 849 //KIRQL oldIrql; 850 //PIRP blockedIrp; 851 852 // This function is obsolete, but still called by DISK.SYS . 853 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !")); 854 855 // 856 // safety net. this should never occur. if it does, it's a potential 857 // memory leak. 858 // 859 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); 860 861 if (commonExt->IsSrbLookasideListInitialized){ 862 /* 863 * Put the SRB back in our lookaside list. 864 * 865 * BUGBUG - Some class drivers use ClassIoComplete 866 * to complete SRBs that they themselves allocated. 867 * So we may be putting a "foreign" SRB 868 * (e.g. with a different pool tag) into our lookaside list. 869 */ 870 ClasspFreeSrb(FdoExtension, Srb); 871 } 872 else { 873 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!")); 874 ExFreePool(Srb); 875 } 876 } 877 878 /*++//////////////////////////////////////////////////////////////////////////// 879 880 ClassDeleteSrbLookasideList() 881 882 Routine Description: 883 884 This routine deletes a lookaside listhead for srbs, and should be called 885 only during the final removal. 886 887 If called at other times, the caller is responsible for 888 synchronization and removal issues. 889 890 Arguments: 891 892 CommonExtension - Pointer to the CommonExtension containing the listhead. 893 894 Return Value: 895 896 None 897 898 --*/ 899 VOID NTAPI ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension) 900 { 901 PAGED_CODE(); 902 903 // This function is obsolete, but is still called by some of our code. 904 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !")); 905 906 if (CommonExtension->IsSrbLookasideListInitialized){ 907 CommonExtension->IsSrbLookasideListInitialized = FALSE; 908 ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList); 909 } 910 else { 911 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist")); 912 } 913 } 914 915 /*++//////////////////////////////////////////////////////////////////////////// 916 917 ClassInitializeSrbLookasideList() 918 919 Routine Description: 920 921 This routine sets up a lookaside listhead for srbs, and should be called 922 only from the ClassInitDevice() routine to prevent race conditions. 923 924 If called from other locations, the caller is responsible for 925 synchronization and removal issues. 926 927 Arguments: 928 929 CommonExtension - Pointer to the CommonExtension containing the listhead. 930 931 NumberElements - Supplies the maximum depth of the lookaside list. 932 933 934 Note: 935 936 The Windows 2000 version of classpnp did not return any status value from 937 this call. 938 939 --*/ 940 941 VOID NTAPI ClassInitializeSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension, 942 IN ULONG NumberElements) 943 { 944 PAGED_CODE(); 945 946 // This function is obsolete, but still called by DISK.SYS . 947 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !")); 948 949 ASSERT(!CommonExtension->IsSrbLookasideListInitialized); 950 if (!CommonExtension->IsSrbLookasideListInitialized){ 951 952 ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList, 953 NULL, 954 NULL, 955 NonPagedPool, 956 sizeof(SCSI_REQUEST_BLOCK), 957 '$scS', 958 (USHORT)NumberElements); 959 960 CommonExtension->IsSrbLookasideListInitialized = TRUE; 961 } 962 963 } 964 965 VOID NTAPI ClasspInitializeCScanList(IN PCSCAN_LIST List) 966 { 967 PAGED_CODE(); 968 RtlZeroMemory(List, sizeof(CSCAN_LIST)); 969 InitializeListHead(&(List->CurrentSweep)); 970 InitializeListHead(&(List->NextSweep)); 971 } 972 973 VOID NTAPI ClasspStartNextSweep(PCSCAN_LIST List) 974 { 975 ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE); 976 977 // 978 // If the next sweep is empty then there's nothing to do. 979 // 980 981 if(IsListEmpty(&(List->NextSweep))) { 982 return; 983 } 984 985 // 986 // Copy the next sweep list head into the current sweep list head. 987 // 988 989 List->CurrentSweep = List->NextSweep; 990 991 // 992 // Unlink the next sweep list from the list head now that we have a copy 993 // of it. 994 // 995 996 InitializeListHead(&(List->NextSweep)); 997 998 // 999 // Update the next sweep list to point back to the current sweep list head. 1000 // 1001 1002 List->CurrentSweep.Flink->Blink = &(List->CurrentSweep); 1003 List->CurrentSweep.Blink->Flink = &(List->CurrentSweep); 1004 1005 return; 1006 } 1007 1008 PIRP NTAPI ClassRemoveCScanList(IN PCSCAN_LIST List) 1009 { 1010 PCSCAN_LIST_ENTRY entry; 1011 1012 // 1013 // If the current sweep is empty then promote the next sweep. 1014 // 1015 1016 if(IsListEmpty(&(List->CurrentSweep))) { 1017 ClasspStartNextSweep(List); 1018 } 1019 1020 // 1021 // If the current sweep is still empty then we're done. 1022 // 1023 1024 if(IsListEmpty(&(List->CurrentSweep))) { 1025 return NULL; 1026 } 1027 1028 // 1029 // Remove the head entry from the current sweep. Record it's block number 1030 // so that nothing before it on the disk gets into the current sweep. 1031 // 1032 1033 entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep)); 1034 1035 List->BlockNumber = entry->BlockNumber; 1036 1037 return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext); 1038 } 1039