Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobsolete.c
Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (C) Microsoft Corporation, 1991 - 1999 00004 00005 Module Name: 00006 00007 obsolete.c 00008 00009 Abstract: 00010 00011 THESE ARE EXPORTED CLASSPNP FUNCTIONS (and their subroutines) 00012 WHICH ARE NOW OBSOLETE. 00013 BUT WE NEED TO KEEP THEM AROUND FOR LEGACY REASONS. 00014 00015 Environment: 00016 00017 kernel mode only 00018 00019 Notes: 00020 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include "classp.h" 00027 #include "debug.h" 00028 00029 PIRP ClassRemoveCScanList(IN PCSCAN_LIST List); 00030 VOID ClasspInitializeCScanList(IN PCSCAN_LIST List); 00031 00032 #ifdef ALLOC_PRAGMA 00033 #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList) 00034 #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList) 00035 #endif 00036 00037 typedef struct _CSCAN_LIST_ENTRY { 00038 LIST_ENTRY Entry; 00039 ULONGLONG BlockNumber; 00040 } CSCAN_LIST_ENTRY, *PCSCAN_LIST_ENTRY; 00041 00042 00043 00044 00045 00046 /* 00047 * ClassSplitRequest 00048 * 00049 * This is a legacy exported function. 00050 * It is called by storage miniport driver that have their own 00051 * StartIo routine when the transfer size is too large for the hardware. 00052 * We map it to our new read/write handler. 00053 */ 00054 VOID ClassSplitRequest(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN ULONG MaximumBytes) 00055 { 00056 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension; 00057 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; 00058 00059 if (MaximumBytes > fdoData->HwMaxXferLen) { 00060 DBGERR(("ClassSplitRequest - driver requesting split to size that " 00061 "hardware is unable to handle!\n")); 00062 } 00063 00064 if (MaximumBytes < fdoData->HwMaxXferLen){ 00065 DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen " 00066 "than required")); 00067 fdoData->HwMaxXferLen = MAX(MaximumBytes, PAGE_SIZE); 00068 } 00069 00070 ServiceTransferRequest(Fdo, Irp); 00071 } 00072 00073 00074 /*++//////////////////////////////////////////////////////////////////////////// 00075 00076 ClassIoCompleteAssociated() 00077 00078 Routine Description: 00079 00080 This routine executes when the port driver has completed a request. 00081 It looks at the SRB status in the completing SRB and if not success 00082 it checks for valid request sense buffer information. If valid, the 00083 info is used to update status with more precise message of type of 00084 error. This routine deallocates the SRB. This routine is used for 00085 requests which were build by split request. After it has processed 00086 the request it decrements the Irp count in the master Irp. If the 00087 count goes to zero then the master Irp is completed. 00088 00089 Arguments: 00090 00091 Fdo - Supplies the functional device object which represents the target. 00092 00093 Irp - Supplies the Irp which has completed. 00094 00095 Context - Supplies a pointer to the SRB. 00096 00097 Return Value: 00098 00099 NT status 00100 00101 --*/ 00102 NTSTATUS 00103 ClassIoCompleteAssociated( 00104 IN PDEVICE_OBJECT Fdo, 00105 IN PIRP Irp, 00106 IN PVOID Context 00107 ) 00108 { 00109 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 00110 00111 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 00112 PSCSI_REQUEST_BLOCK srb = Context; 00113 00114 PIRP originalIrp = Irp->AssociatedIrp.MasterIrp; 00115 LONG irpCount; 00116 00117 NTSTATUS status; 00118 BOOLEAN retry; 00119 00120 DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !")); 00121 00122 // 00123 // Check SRB status for success of completing request. 00124 // 00125 00126 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 00127 00128 ULONG retryInterval; 00129 00130 DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb)); 00131 00132 // 00133 // Release the queue if it is frozen. 00134 // 00135 00136 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 00137 ClassReleaseQueue(Fdo); 00138 } 00139 00140 retry = ClassInterpretSenseInfo( 00141 Fdo, 00142 srb, 00143 irpStack->MajorFunction, 00144 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? 00145 irpStack->Parameters.DeviceIoControl.IoControlCode : 00146 0, 00147 MAXIMUM_RETRIES - 00148 ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4), 00149 &status, 00150 &retryInterval); 00151 00152 // 00153 // If the status is verified required and the this request 00154 // should bypass verify required then retry the request. 00155 // 00156 00157 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 00158 status == STATUS_VERIFY_REQUIRED) { 00159 00160 status = STATUS_IO_DEVICE_ERROR; 00161 retry = TRUE; 00162 } 00163 00164 if (retry && ((*(PCHAR*)&irpStack->Parameters.Others.Argument4)--)) { 00165 00166 // 00167 // Retry request. If the class driver has supplied a StartIo, 00168 // call it directly for retries. 00169 // 00170 00171 DebugPrint((1, "Retry request %p\n", Irp)); 00172 00173 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) { 00174 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb); 00175 } 00176 00177 RetryRequest(Fdo, Irp, srb, TRUE, retryInterval); 00178 00179 return STATUS_MORE_PROCESSING_REQUIRED; 00180 } 00181 00182 } else { 00183 00184 // 00185 // Set status for successful request. 00186 // 00187 00188 status = STATUS_SUCCESS; 00189 00190 } // end if (SRB_STATUS(srb->SrbStatus) ... 00191 00192 // 00193 // Return SRB to list. 00194 // 00195 00196 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) { 00197 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb); 00198 } 00199 00200 ClassFreeOrReuseSrb(fdoExtension, srb); 00201 00202 // 00203 // Set status in completing IRP. 00204 // 00205 00206 Irp->IoStatus.Status = status; 00207 00208 DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp)); 00209 00210 // 00211 // Get next stack location. This original request is unused 00212 // except to keep track of the completing partial IRPs so the 00213 // stack location is valid. 00214 // 00215 00216 irpStack = IoGetNextIrpStackLocation(originalIrp); 00217 00218 // 00219 // Update status only if error so that if any partial transfer 00220 // completes with error, then the original IRP will return with 00221 // error. If any of the asynchronous partial transfer IRPs fail, 00222 // with an error then the original IRP will return 0 bytes transfered. 00223 // This is an optimization for successful transfers. 00224 // 00225 00226 if (!NT_SUCCESS(status)) { 00227 00228 originalIrp->IoStatus.Status = status; 00229 originalIrp->IoStatus.Information = 0; 00230 00231 // 00232 // Set the hard error if necessary. 00233 // 00234 00235 if (IoIsErrorUserInduced(status)) { 00236 00237 // 00238 // Store DeviceObject for filesystem. 00239 // 00240 00241 IoSetHardErrorOrVerifyDevice(originalIrp, Fdo); 00242 } 00243 } 00244 00245 // 00246 // Decrement and get the count of remaining IRPs. 00247 // 00248 00249 irpCount = InterlockedDecrement( 00250 (PLONG)&irpStack->Parameters.Others.Argument1); 00251 00252 DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n", 00253 irpCount)); 00254 00255 // 00256 // Ensure that the irpCount doesn't go negative. This was happening once 00257 // because classpnp would get confused if it ran out of resources when 00258 // splitting the request. 00259 // 00260 00261 ASSERT(irpCount >= 0); 00262 00263 if (irpCount == 0) { 00264 00265 // 00266 // All partial IRPs have completed. 00267 // 00268 00269 DebugPrint((2, 00270 "ClassIoCompleteAssociated: All partial IRPs complete %p\n", 00271 originalIrp)); 00272 00273 if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) { 00274 00275 // 00276 // Acquire a separate copy of the remove lock so the debugging code 00277 // works okay and we don't have to hold up the completion of this 00278 // irp until after we start the next packet(s). 00279 // 00280 00281 KIRQL oldIrql; 00282 UCHAR uniqueAddress; 00283 ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress); 00284 ClassReleaseRemoveLock(Fdo, originalIrp); 00285 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT); 00286 00287 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 00288 IoStartNextPacket(Fdo, FALSE); 00289 KeLowerIrql(oldIrql); 00290 00291 ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress); 00292 00293 } else { 00294 00295 // 00296 // just complete this request 00297 // 00298 00299 ClassReleaseRemoveLock(Fdo, originalIrp); 00300 ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT); 00301 00302 } 00303 00304 } 00305 00306 // 00307 // Deallocate IRP and indicate the I/O system should not attempt any more 00308 // processing. 00309 // 00310 00311 IoFreeIrp(Irp); 00312 return STATUS_MORE_PROCESSING_REQUIRED; 00313 00314 } // end ClassIoCompleteAssociated() 00315 00316 00317 /*++//////////////////////////////////////////////////////////////////////////// 00318 00319 RetryRequest() 00320 00321 Routine Description: 00322 00323 This is a wrapper around the delayed retry DPC routine, RetryRequestDPC. 00324 This reinitalizes the necessary fields, queues the request, and sets 00325 a timer to call the DPC if someone hasn't already done so. 00326 00327 Arguments: 00328 00329 DeviceObject - Supplies the device object associated with this request. 00330 00331 Irp - Supplies the request to be retried. 00332 00333 Srb - Supplies a Pointer to the SCSI request block to be retied. 00334 00335 Assocaiated - Indicates this is an assocatied Irp created by split request. 00336 00337 RetryInterval - How long, in seconds, before retrying the request. 00338 00339 Return Value: 00340 00341 None 00342 00343 --*/ 00344 VOID 00345 RetryRequest( 00346 PDEVICE_OBJECT DeviceObject, 00347 PIRP Irp, 00348 PSCSI_REQUEST_BLOCK Srb, 00349 BOOLEAN Associated, 00350 ULONG RetryInterval 00351 ) 00352 { 00353 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 00354 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 00355 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 00356 ULONG transferByteCount; 00357 00358 // This function is obsolete but is still used by some of our class drivers. 00359 // DBGWARN(("RetryRequest is OBSOLETE !")); 00360 00361 // 00362 // Determine the transfer count of the request. If this is a read or a 00363 // write then the transfer count is in the Irp stack. Otherwise assume 00364 // the MDL contains the correct length. If there is no MDL then the 00365 // transfer length must be zero. 00366 // 00367 00368 if (currentIrpStack->MajorFunction == IRP_MJ_READ || 00369 currentIrpStack->MajorFunction == IRP_MJ_WRITE) { 00370 00371 transferByteCount = currentIrpStack->Parameters.Read.Length; 00372 00373 } else if (Irp->MdlAddress != NULL) { 00374 00375 // 00376 // Note this assumes that only read and write requests are spilt and 00377 // other request do not need to be. If the data buffer address in 00378 // the MDL and the SRB don't match then transfer length is most 00379 // likely incorrect. 00380 // 00381 00382 ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress)); 00383 transferByteCount = Irp->MdlAddress->ByteCount; 00384 00385 } else { 00386 00387 transferByteCount = 0; 00388 } 00389 00390 // 00391 // this is a safety net. this should not normally be hit, since we are 00392 // not guaranteed to be an fdoExtension 00393 // 00394 00395 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); 00396 00397 // 00398 // Reset byte count of transfer in SRB Extension. 00399 // 00400 00401 Srb->DataTransferLength = transferByteCount; 00402 00403 // 00404 // Zero SRB statuses. 00405 // 00406 00407 Srb->SrbStatus = Srb->ScsiStatus = 0; 00408 00409 // 00410 // Set the no disconnect flag, disable synchronous data transfers and 00411 // disable tagged queuing. This fixes some errors. 00412 // NOTE: Cannot clear these flags, just add to them 00413 // 00414 00415 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT); 00416 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); 00417 CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE); 00418 00419 Srb->QueueTag = SP_UNTAGGED; 00420 00421 // 00422 // Set up major SCSI function. 00423 // 00424 00425 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 00426 00427 // 00428 // Save SRB address in next stack for port driver. 00429 // 00430 00431 nextIrpStack->Parameters.Scsi.Srb = Srb; 00432 00433 00434 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); 00435 00436 { 00437 LARGE_INTEGER retry100ns; 00438 retry100ns.QuadPart = RetryInterval; // seconds 00439 retry100ns.QuadPart *= (LONGLONG)1000 * 1000 * 10; 00440 00441 ClassRetryRequest(DeviceObject, Irp, retry100ns); 00442 } 00443 return; 00444 } // end RetryRequest() 00445 00446 00447 /*++ 00448 00449 ClassBuildRequest() 00450 00451 Routine Description: 00452 00453 This routine allocates an SRB for the specified request then calls 00454 ClasspBuildRequestEx to create a SCSI operation to read or write the device. 00455 00456 If no SRB is available then the request will be queued to be issued later 00457 when requests are available. Drivers which do not want the queueing 00458 behavior should allocate the SRB themselves and call ClasspBuildRequestEx 00459 to issue it. 00460 00461 Arguments: 00462 00463 Fdo - Supplies the functional device object associated with this request. 00464 00465 Irp - Supplies the request to be retried. 00466 00467 Note: 00468 00469 If the IRP is for a disk transfer, the byteoffset field 00470 will already have been adjusted to make it relative to 00471 the beginning of the disk. 00472 00473 00474 Return Value: 00475 00476 NT Status 00477 00478 --*/ 00479 NTSTATUS 00480 ClassBuildRequest( 00481 PDEVICE_OBJECT Fdo, 00482 PIRP Irp 00483 ) 00484 { 00485 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 00486 00487 PSCSI_REQUEST_BLOCK srb; 00488 00489 // This function is obsolete, but still called by CDROM.SYS . 00490 // DBGWARN(("ClassBuildRequest is OBSOLETE !")); 00491 00492 // 00493 // Allocate an Srb. 00494 // 00495 00496 srb = ClasspAllocateSrb(fdoExtension); 00497 00498 if(srb == NULL) { 00499 return STATUS_INSUFFICIENT_RESOURCES; 00500 } 00501 00502 ClasspBuildRequestEx(fdoExtension, Irp, srb); 00503 return STATUS_SUCCESS; 00504 00505 } // end ClassBuildRequest() 00506 00507 00508 VOID 00509 ClasspBuildRequestEx( 00510 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 00511 IN PIRP Irp, 00512 IN PSCSI_REQUEST_BLOCK Srb 00513 ) 00514 00515 /*++ 00516 00517 ClasspBuildRequestEx() 00518 00519 Routine Description: 00520 00521 This routine allocates and builds an Srb for a read or write request. 00522 The block address and length are supplied by the Irp. The retry count 00523 is stored in the current stack for use by ClassIoComplete which 00524 processes these requests when they complete. The Irp is ready to be 00525 passed to the port driver when this routine returns. 00526 00527 Arguments: 00528 00529 FdoExtension - Supplies the device extension associated with this request. 00530 00531 Irp - Supplies the request to be issued. 00532 00533 Srb - Supplies an SRB to be used for the request. 00534 00535 Note: 00536 00537 If the IRP is for a disk transfer, the byteoffset field 00538 will already have been adjusted to make it relative to 00539 the beginning of the disk. 00540 00541 00542 Return Value: 00543 00544 NT Status 00545 00546 --*/ 00547 { 00548 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); 00549 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 00550 00551 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; 00552 00553 PCDB cdb; 00554 ULONG logicalBlockAddress; 00555 USHORT transferBlocks; 00556 00557 // This function is obsolete, but still called by CDROM.SYS . 00558 // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !")); 00559 00560 // 00561 // Prepare the SRB. 00562 // 00563 00564 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); 00565 00566 // 00567 // Calculate relative sector address. 00568 // 00569 00570 logicalBlockAddress = 00571 (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, 00572 FdoExtension->SectorShift)); 00573 00574 // 00575 // Write length to SRB. 00576 // 00577 00578 Srb->Length = sizeof(SCSI_REQUEST_BLOCK); 00579 00580 // 00581 // Set up IRP Address. 00582 // 00583 00584 Srb->OriginalRequest = Irp; 00585 00586 // 00587 // Set up target ID and logical unit number. 00588 // 00589 00590 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 00591 Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); 00592 00593 // 00594 // Save byte count of transfer in SRB Extension. 00595 // 00596 00597 Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; 00598 00599 // 00600 // Initialize the queue actions field. 00601 // 00602 00603 Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; 00604 00605 // 00606 // Queue sort key is Relative Block Address. 00607 // 00608 00609 Srb->QueueSortKey = logicalBlockAddress; 00610 00611 // 00612 // Indicate auto request sense by specifying buffer and size. 00613 // 00614 00615 Srb->SenseInfoBuffer = FdoExtension->SenseData; 00616 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 00617 00618 // 00619 // Set timeout value of one unit per 64k bytes of data. 00620 // 00621 00622 Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) * 00623 FdoExtension->TimeOutValue; 00624 00625 // 00626 // Zero statuses. 00627 // 00628 00629 Srb->SrbStatus = Srb->ScsiStatus = 0; 00630 Srb->NextSrb = 0; 00631 00632 // 00633 // Indicate that 10-byte CDB's will be used. 00634 // 00635 00636 Srb->CdbLength = 10; 00637 00638 // 00639 // Fill in CDB fields. 00640 // 00641 00642 cdb = (PCDB)Srb->Cdb; 00643 00644 transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> 00645 FdoExtension->SectorShift); 00646 00647 // 00648 // Move little endian values into CDB in big endian format. 00649 // 00650 00651 cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; 00652 cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; 00653 cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; 00654 cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; 00655 00656 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; 00657 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; 00658 00659 // 00660 // Set transfer direction flag and Cdb command. 00661 // 00662 00663 if (currentIrpStack->MajorFunction == IRP_MJ_READ) { 00664 00665 DebugPrint((3, "ClassBuildRequest: Read Command\n")); 00666 00667 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); 00668 cdb->CDB10.OperationCode = SCSIOP_READ; 00669 00670 } else { 00671 00672 DebugPrint((3, "ClassBuildRequest: Write Command\n")); 00673 00674 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT); 00675 cdb->CDB10.OperationCode = SCSIOP_WRITE; 00676 } 00677 00678 // 00679 // If this is not a write-through request, then allow caching. 00680 // 00681 00682 if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) { 00683 00684 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); 00685 00686 } else { 00687 00688 // 00689 // If write caching is enable then force media access in the 00690 // cdb. 00691 // 00692 00693 if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) { 00694 cdb->CDB10.ForceUnitAccess = TRUE; 00695 } 00696 } 00697 00698 if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) { 00699 SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING); 00700 } 00701 00702 // 00703 // OR in the default flags from the device object. 00704 // 00705 00706 SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags); 00707 00708 // 00709 // Set up major SCSI function. 00710 // 00711 00712 nextIrpStack->MajorFunction = IRP_MJ_SCSI; 00713 00714 // 00715 // Save SRB address in next stack for port driver. 00716 // 00717 00718 nextIrpStack->Parameters.Scsi.Srb = Srb; 00719 00720 // 00721 // Save retry count in current IRP stack. 00722 // 00723 00724 currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; 00725 00726 // 00727 // Set up IoCompletion routine address. 00728 // 00729 00730 IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); 00731 00732 } 00733 00734 00735 VOID ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry) 00736 { 00737 PCSCAN_LIST_ENTRY t; 00738 00739 DBGWARN(("ClasspInsertCScanList is OBSOLETE !")); 00740 00741 // 00742 // Iterate through the list. Insert this entry in the sorted list in 00743 // order (after other requests for the same block). At each stop if 00744 // blockNumber(Entry) >= blockNumber(t) then move on. 00745 // 00746 00747 for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink; 00748 t != (PCSCAN_LIST_ENTRY) ListHead; 00749 t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) { 00750 00751 if(Entry->BlockNumber < t->BlockNumber) { 00752 00753 // 00754 // Set the pointers in entry to the right location. 00755 // 00756 00757 Entry->Entry.Flink = &(t->Entry); 00758 Entry->Entry.Blink = t->Entry.Blink; 00759 00760 // 00761 // Set the pointers in the surrounding elements to refer to us. 00762 // 00763 00764 t->Entry.Blink->Flink = &(Entry->Entry); 00765 t->Entry.Blink = &(Entry->Entry); 00766 return; 00767 } 00768 } 00769 00770 // 00771 // Insert this entry at the tail of the list. If the list was empty this 00772 // will also be the head of the list. 00773 // 00774 00775 InsertTailList(ListHead, &(Entry->Entry)); 00776 00777 } 00778 00779 00780 VOID ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority) 00781 /*++ 00782 00783 Routine Description: 00784 00785 This routine inserts an entry into the CScan list based on it's block number 00786 and priority. It is assumed that the caller is providing synchronization 00787 to the access of the list. 00788 00789 Low priority requests are always scheduled to run on the next sweep across 00790 the disk. Normal priority requests will be inserted into the current or 00791 next sweep based on the standard C-SCAN algorithm. 00792 00793 Arguments: 00794 00795 List - the list to insert into 00796 00797 Irp - the irp to be inserted. 00798 00799 BlockNumber - the block number for this request. 00800 00801 LowPriority - indicates that the request is lower priority and should be 00802 done on the next sweep across the disk. 00803 00804 Return Value: 00805 00806 none 00807 00808 --*/ 00809 { 00810 PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext; 00811 00812 DBGWARN(("ClassInsertCScanList is OBSOLETE !")); 00813 00814 // 00815 // Set the block number in the entry. We need this to keep the list sorted. 00816 // 00817 entry->BlockNumber = BlockNumber; 00818 00819 // 00820 // If it's a normal priority request and further down the disk than our 00821 // current position then insert this entry into the current sweep. 00822 // 00823 00824 if((LowPriority != TRUE) && (BlockNumber > List->BlockNumber)) { 00825 ClasspInsertCScanList(&(List->CurrentSweep), entry); 00826 } else { 00827 ClasspInsertCScanList(&(List->NextSweep), entry); 00828 } 00829 return; 00830 } 00831 00832 00833 00834 00835 VOID ClassFreeOrReuseSrb( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, 00836 IN PSCSI_REQUEST_BLOCK Srb) 00837 /*++ 00838 00839 Routine Description: 00840 00841 This routine will attempt to reuse the provided SRB to start a blocked 00842 read/write request. 00843 If there is no need to reuse the request it will be returned 00844 to the SRB lookaside list. 00845 00846 Arguments: 00847 00848 Fdo - the device extension 00849 00850 Srb - the SRB which is to be reused or freed. 00851 00852 Return Value: 00853 00854 none. 00855 00856 --*/ 00857 00858 { 00859 PCLASS_PRIVATE_FDO_DATA privateData = FdoExtension->PrivateFdoData; 00860 PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension; 00861 KIRQL oldIrql; 00862 PIRP blockedIrp; 00863 00864 // This function is obsolete, but still called by DISK.SYS . 00865 // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !")); 00866 00867 // 00868 // safety net. this should never occur. if it does, it's a potential 00869 // memory leak. 00870 // 00871 ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); 00872 00873 if (commonExt->IsSrbLookasideListInitialized){ 00874 /* 00875 * Put the SRB back in our lookaside list. 00876 * 00877 * BUGBUG - Some class drivers use ClassIoComplete 00878 * to complete SRBs that they themselves allocated. 00879 * So we may be putting a "foreign" SRB 00880 * (e.g. with a different pool tag) into our lookaside list. 00881 */ 00882 ClasspFreeSrb(FdoExtension, Srb); 00883 } 00884 else { 00885 DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));; 00886 ExFreePool(Srb); 00887 } 00888 } 00889 00890 00891 /*++//////////////////////////////////////////////////////////////////////////// 00892 00893 ClassDeleteSrbLookasideList() 00894 00895 Routine Description: 00896 00897 This routine deletes a lookaside listhead for srbs, and should be called 00898 only during the final removal. 00899 00900 If called at other times, the caller is responsible for 00901 synchronization and removal issues. 00902 00903 Arguments: 00904 00905 CommonExtension - Pointer to the CommonExtension containing the listhead. 00906 00907 Return Value: 00908 00909 None 00910 00911 --*/ 00912 VOID ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension) 00913 { 00914 PAGED_CODE(); 00915 00916 // This function is obsolete, but is still called by some of our code. 00917 // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !")); 00918 00919 if (CommonExtension->IsSrbLookasideListInitialized){ 00920 CommonExtension->IsSrbLookasideListInitialized = FALSE; 00921 ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList); 00922 } 00923 else { 00924 DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist")); 00925 } 00926 } 00927 00928 00929 /*++//////////////////////////////////////////////////////////////////////////// 00930 00931 ClassInitializeSrbLookasideList() 00932 00933 Routine Description: 00934 00935 This routine sets up a lookaside listhead for srbs, and should be called 00936 only from the ClassInitDevice() routine to prevent race conditions. 00937 00938 If called from other locations, the caller is responsible for 00939 synchronization and removal issues. 00940 00941 Arguments: 00942 00943 CommonExtension - Pointer to the CommonExtension containing the listhead. 00944 00945 NumberElements - Supplies the maximum depth of the lookaside list. 00946 00947 00948 Note: 00949 00950 The Windows 2000 version of classpnp did not return any status value from 00951 this call. 00952 00953 --*/ 00954 00955 VOID ClassInitializeSrbLookasideList( IN PCOMMON_DEVICE_EXTENSION CommonExtension, 00956 IN ULONG NumberElements) 00957 { 00958 PAGED_CODE(); 00959 00960 // This function is obsolete, but still called by DISK.SYS . 00961 // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !")); 00962 00963 ASSERT(!CommonExtension->IsSrbLookasideListInitialized); 00964 if (!CommonExtension->IsSrbLookasideListInitialized){ 00965 00966 ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList, 00967 NULL, 00968 NULL, 00969 NonPagedPool, 00970 sizeof(SCSI_REQUEST_BLOCK), 00971 '$scS', 00972 (USHORT)NumberElements); 00973 00974 CommonExtension->IsSrbLookasideListInitialized = TRUE; 00975 } 00976 00977 } 00978 00979 00980 00981 00982 VOID ClasspInitializeCScanList(IN PCSCAN_LIST List) 00983 { 00984 PAGED_CODE(); 00985 RtlZeroMemory(List, sizeof(CSCAN_LIST)); 00986 InitializeListHead(&(List->CurrentSweep)); 00987 InitializeListHead(&(List->NextSweep)); 00988 } 00989 00990 00991 00992 VOID ClasspStartNextSweep(PCSCAN_LIST List) 00993 { 00994 ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE); 00995 00996 // 00997 // If the next sweep is empty then there's nothing to do. 00998 // 00999 01000 if(IsListEmpty(&(List->NextSweep))) { 01001 return; 01002 } 01003 01004 // 01005 // Copy the next sweep list head into the current sweep list head. 01006 // 01007 01008 List->CurrentSweep = List->NextSweep; 01009 01010 // 01011 // Unlink the next sweep list from the list head now that we have a copy 01012 // of it. 01013 // 01014 01015 InitializeListHead(&(List->NextSweep)); 01016 01017 // 01018 // Update the next sweep list to point back to the current sweep list head. 01019 // 01020 01021 List->CurrentSweep.Flink->Blink = &(List->CurrentSweep); 01022 List->CurrentSweep.Blink->Flink = &(List->CurrentSweep); 01023 01024 return; 01025 } 01026 01027 01028 01029 PIRP ClassRemoveCScanList(IN PCSCAN_LIST List) 01030 { 01031 PCSCAN_LIST_ENTRY entry; 01032 01033 // 01034 // If the current sweep is empty then promote the next sweep. 01035 // 01036 01037 if(IsListEmpty(&(List->CurrentSweep))) { 01038 ClasspStartNextSweep(List); 01039 } 01040 01041 // 01042 // If the current sweep is still empty then we're done. 01043 // 01044 01045 if(IsListEmpty(&(List->CurrentSweep))) { 01046 return NULL; 01047 } 01048 01049 // 01050 // Remove the head entry from the current sweep. Record it's block number 01051 // so that nothing before it on the disk gets into the current sweep. 01052 // 01053 01054 entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep)); 01055 01056 List->BlockNumber = entry->BlockNumber; 01057 01058 return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext); 01059 } 01060 Generated on Fri May 25 2012 04:26:16 for ReactOS by
1.7.6.1
|