⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obsolete.c

📁 This is the library for all storage drivers. It simplifies writing a storage driver by implementing
💻 C
📖 第 1 页 / 共 2 页
字号:

Arguments:

    FdoExtension - Supplies the device extension associated with this request.

    Irp - Supplies the request to be issued.

    Srb - Supplies an SRB to be used for the request.

Note:

    If the IRP is for a disk transfer, the byteoffset field
    will already have been adjusted to make it relative to
    the beginning of the disk.


Return Value:

    NT Status

--*/
{
    PIO_STACK_LOCATION  currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION  nextIrpStack = IoGetNextIrpStackLocation(Irp);

    LARGE_INTEGER       startingOffset = currentIrpStack->Parameters.Read.ByteOffset;

    PCDB                cdb;
    ULONG               logicalBlockAddress;
    USHORT              transferBlocks;

    // This function is obsolete, but still called by CDROM.SYS .
    // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));

    //
    // Prepare the SRB.
    //

    RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));

    //
    // Calculate relative sector address.
    //

    logicalBlockAddress =
        (ULONG)(Int64ShrlMod32(startingOffset.QuadPart,
                               FdoExtension->SectorShift));

    //
    // Write length to SRB.
    //

    Srb->Length = sizeof(SCSI_REQUEST_BLOCK);

    //
    // Set up IRP Address.
    //

    Srb->OriginalRequest = Irp;

    //
    // Set up target ID and logical unit number.
    //

    Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
    Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);

    //
    // Save byte count of transfer in SRB Extension.
    //

    Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;

    //
    // Initialize the queue actions field.
    //

    Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;

    //
    // Queue sort key is Relative Block Address.
    //

    Srb->QueueSortKey = logicalBlockAddress;

    //
    // Indicate auto request sense by specifying buffer and size.
    //

    Srb->SenseInfoBuffer = FdoExtension->SenseData;
    Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;

    //
    // Set timeout value of one unit per 64k bytes of data.
    //

    Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) *
                        FdoExtension->TimeOutValue;

    //
    // Zero statuses.
    //

    Srb->SrbStatus = Srb->ScsiStatus = 0;
    Srb->NextSrb = 0;

    //
    // Indicate that 10-byte CDB's will be used.
    //

    Srb->CdbLength = 10;

    //
    // Fill in CDB fields.
    //

    cdb = (PCDB)Srb->Cdb;

    transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >>
                              FdoExtension->SectorShift);

    //
    // Move little endian values into CDB in big endian format.
    //

    cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
    cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
    cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
    cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;

    cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
    cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;

    //
    // Set transfer direction flag and Cdb command.
    //

    if (currentIrpStack->MajorFunction == IRP_MJ_READ) {

        DebugPrint((3, "ClassBuildRequest: Read Command\n"));

        SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN);
        cdb->CDB10.OperationCode = SCSIOP_READ;

    } else {

        DebugPrint((3, "ClassBuildRequest: Write Command\n"));

        SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT);
        cdb->CDB10.OperationCode = SCSIOP_WRITE;
    }

    //
    // If this is not a write-through request, then allow caching.
    //

    if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {

        SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);

    } else {

        //
        // If write caching is enable then force media access in the
        // cdb.
        //

        if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) {
            cdb->CDB10.ForceUnitAccess = TRUE;
        }
    }

    if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) {
        SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
    }

    //
    // OR in the default flags from the device object.
    //

    SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags);

    //
    // Set up major SCSI function.
    //

    nextIrpStack->MajorFunction = IRP_MJ_SCSI;

    //
    // Save SRB address in next stack for port driver.
    //

    nextIrpStack->Parameters.Scsi.Srb = Srb;

    //
    // Save retry count in current IRP stack.
    //

    currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;

    //
    // Set up IoCompletion routine address.
    //

    IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);

}


VOID ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry)
{
    PCSCAN_LIST_ENTRY t;

    DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));

    //
    // Iterate through the list.  Insert this entry in the sorted list in
    // order (after other requests for the same block).  At each stop if
    // blockNumber(Entry) >= blockNumber(t) then move on.
    //

    for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink;
        t != (PCSCAN_LIST_ENTRY) ListHead;
        t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) {

        if(Entry->BlockNumber < t->BlockNumber) {

            //
            // Set the pointers in entry to the right location.
            //

            Entry->Entry.Flink = &(t->Entry);
            Entry->Entry.Blink = t->Entry.Blink;

            //
            // Set the pointers in the surrounding elements to refer to us.
            //

            t->Entry.Blink->Flink = &(Entry->Entry);
            t->Entry.Blink = &(Entry->Entry);
            return;
        }
    }

    //
    // Insert this entry at the tail of the list.  If the list was empty this
    // will also be the head of the list.
    //

    InsertTailList(ListHead, &(Entry->Entry));

}


VOID ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority)
/*++

Routine Description:

    This routine inserts an entry into the CScan list based on it's block number
    and priority.  It is assumed that the caller is providing synchronization
    to the access of the list.

    Low priority requests are always scheduled to run on the next sweep across
    the disk.  Normal priority requests will be inserted into the current or
    next sweep based on the standard C-SCAN algorithm.

Arguments:

    List - the list to insert into

    Irp - the irp to be inserted.

    BlockNumber - the block number for this request.

    LowPriority - indicates that the request is lower priority and should be
                  done on the next sweep across the disk.

Return Value:

    none

--*/
{
    PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext;

    DBGWARN(("ClassInsertCScanList is OBSOLETE !"));

    //
    // Set the block number in the entry.  We need this to keep the list sorted.
    //
    entry->BlockNumber = BlockNumber;

    //
    // If it's a normal priority request and further down the disk than our
    // current position then insert this entry into the current sweep.
    //

    if((LowPriority != TRUE) && (BlockNumber > List->BlockNumber)) {
        ClasspInsertCScanList(&(List->CurrentSweep), entry);
    } else {
        ClasspInsertCScanList(&(List->NextSweep), entry);
    }
    return;
}




VOID ClassFreeOrReuseSrb(   IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
                            IN PSCSI_REQUEST_BLOCK Srb)
/*++

Routine Description:

    This routine will attempt to reuse the provided SRB to start a blocked
    read/write request.
    If there is no need to reuse the request it will be returned
    to the SRB lookaside list.

Arguments:

    Fdo - the device extension

    Srb - the SRB which is to be reused or freed.

Return Value:

    none.

--*/

{
    PCLASS_PRIVATE_FDO_DATA privateData = FdoExtension->PrivateFdoData;
    PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension;
    KIRQL oldIrql;
    PIRP blockedIrp;

    // This function is obsolete, but still called by DISK.SYS .
    // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));

    //
    // safety net.  this should never occur.  if it does, it's a potential
    // memory leak.
    //
    ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));

    if (commonExt->IsSrbLookasideListInitialized){
        /*
         *  Put the SRB back in our lookaside list.
         *
         *  Note:   Some class drivers use ClassIoComplete
         *            to complete SRBs that they themselves allocated.
         *            So we may be putting a "foreign" SRB
         *            (e.g. with a different pool tag) into our lookaside list.
         */
        ClasspFreeSrb(FdoExtension, Srb);
    }
    else {
        DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));;
        ExFreePool(Srb);
    }
}


/*++////////////////////////////////////////////////////////////////////////////

ClassDeleteSrbLookasideList()

Routine Description:

    This routine deletes a lookaside listhead for srbs, and should be called
    only during the final removal.

    If called at other times, the caller is responsible for
    synchronization and removal issues.

Arguments:

    CommonExtension - Pointer to the CommonExtension containing the listhead.

Return Value:

    None

--*/
VOID ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension)
{
    PAGED_CODE();

    // This function is obsolete, but is still called by some of our code.
    // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));

    if (CommonExtension->IsSrbLookasideListInitialized){
        CommonExtension->IsSrbLookasideListInitialized = FALSE;
        ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList);
    }
    else {
        DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
    }
}


/*++////////////////////////////////////////////////////////////////////////////

ClassInitializeSrbLookasideList()

Routine Description:

    This routine sets up a lookaside listhead for srbs, and should be called
    only from the ClassInitDevice() routine to prevent race conditions.

    If called from other locations, the caller is responsible for
    synchronization and removal issues.

Arguments:

    CommonExtension - Pointer to the CommonExtension containing the listhead.

    NumberElements  - Supplies the maximum depth of the lookaside list.


Note:

    The Windows 2000 version of classpnp did not return any status value from
    this call.

--*/

VOID ClassInitializeSrbLookasideList(   IN PCOMMON_DEVICE_EXTENSION CommonExtension,
                                        IN ULONG NumberElements)
{
    PAGED_CODE();

    // This function is obsolete, but still called by DISK.SYS .
    // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));

    ASSERT(!CommonExtension->IsSrbLookasideListInitialized);
    if (!CommonExtension->IsSrbLookasideListInitialized){

        ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList,
                                        NULL,
                                        NULL,
                                        NonPagedPool,
                                        sizeof(SCSI_REQUEST_BLOCK),
                                        '$scS',
                                        (USHORT)NumberElements);

        CommonExtension->IsSrbLookasideListInitialized = TRUE;
    }

}




VOID ClasspInitializeCScanList(IN PCSCAN_LIST List)
{
    PAGED_CODE();
    RtlZeroMemory(List, sizeof(CSCAN_LIST));
    InitializeListHead(&(List->CurrentSweep));
    InitializeListHead(&(List->NextSweep));
}



VOID ClasspStartNextSweep(PCSCAN_LIST List)
{
    ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE);

    //
    // If the next sweep is empty then there's nothing to do.
    //

    if(IsListEmpty(&(List->NextSweep))) {
        return;
    }

    //
    // Copy the next sweep list head into the current sweep list head.
    //

    List->CurrentSweep = List->NextSweep;

    //
    // Unlink the next sweep list from the list head now that we have a copy
    // of it.
    //

    InitializeListHead(&(List->NextSweep));

    //
    // Update the next sweep list to point back to the current sweep list head.
    //

    List->CurrentSweep.Flink->Blink = &(List->CurrentSweep);
    List->CurrentSweep.Blink->Flink = &(List->CurrentSweep);

    return;
}



PIRP ClassRemoveCScanList(IN PCSCAN_LIST List)
{
    PCSCAN_LIST_ENTRY entry;

    //
    // If the current sweep is empty then promote the next sweep.
    //

    if(IsListEmpty(&(List->CurrentSweep))) {
        ClasspStartNextSweep(List);
    }

    //
    // If the current sweep is still empty then we're done.
    //

    if(IsListEmpty(&(List->CurrentSweep))) {
        return NULL;
    }

    //
    // Remove the head entry from the current sweep.  Record it's block number
    // so that nothing before it on the disk gets into the current sweep.
    //

    entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep));

    List->BlockNumber = entry->BlockNumber;

    return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -