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