ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

obsolete.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.