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

📄 utils.c

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

    if (deviceDescriptor->VendorIdOffset != 0 &&
        deviceDescriptor->VendorIdOffset != -1) {
        vendorId = ((PUCHAR)deviceDescriptor);
        vendorId += deviceDescriptor->VendorIdOffset;
    } else {
        vendorId = nullString;
    }
    if (deviceDescriptor->ProductIdOffset != 0 &&
        deviceDescriptor->ProductIdOffset != -1) {
        productId = ((PUCHAR)deviceDescriptor);
        productId += deviceDescriptor->ProductIdOffset;
    } else {
        productId = nullString;
    }
    if (deviceDescriptor->ProductRevisionOffset != 0 &&
        deviceDescriptor->ProductRevisionOffset != -1) {
        productRevision = ((PUCHAR)deviceDescriptor);
        productRevision += deviceDescriptor->ProductRevisionOffset;
    } else {
        productRevision = nullString;
    }

    //
    // loop while the device list is valid (not null-filled)
    //

    for (;(DeviceList->VendorId        != NULL ||
           DeviceList->ProductId       != NULL ||
           DeviceList->ProductRevision != NULL);DeviceList++) {

        if (ClasspMyStringMatches(DeviceList->VendorId,        vendorId) &&
            ClasspMyStringMatches(DeviceList->ProductId,       productId) &&
            ClasspMyStringMatches(DeviceList->ProductRevision, productRevision)
            ) {

            DebugPrint((1, "ClasspScanForSpecialByInquiry: Found matching "
                        "controller Ven: %s Prod: %s Rev: %s\n",
                        vendorId, productId, productRevision));

            //
            // pass the context to the call back routine and exit
            //

            (Function)(FdoExtension, DeviceList->Data);

            //
            // for CHK builds, try to prevent wierd stacks by having a debug
            // print here. it's a hack, but i know of no other way to prevent
            // the stack from being wrong.
            //

            DebugPrint((16, "ClasspScanForSpecialByInquiry: "
                        "completed callback\n"));
            return;

        } // else the strings did not match

    } // none of the devices matched.

    DebugPrint((1, "ClasspScanForSpecialByInquiry: no match found for %p\n",
                FdoExtension->DeviceObject));
    return;

} // end ClasspScanForSpecialByInquiry()


//
// In order to provide better performance without the need to reboot,
// we need to implement a self-adjusting method to set and clear the
// srb flags based upon current performance.
//
// whenever there is an error, immediately grab the spin lock.  the
// MP perf hit here is acceptable, since we're in an error path.  this
// is also neccessary because we are guaranteed to be modifying the
// SRB flags here, setting SuccessfulIO to zero, and incrementing the
// actual error count (which is always done within this spinlock).
//
// whenever there is no error, increment a counter.  if there have been
// errors on the device, and we've enabled dynamic perf, *and* we've
// just crossed the perf threshhold, then grab the spin lock and
// double check that the threshhold has, indeed been hit(*). then
// decrement the error count, and if it's dropped sufficiently, undo
// some of the safety changes made in the SRB flags due to the errors.
//
// * this works in all cases.  even if lots of ios occur after the
//   previous guy went in and cleared the successfulio counter, that
//   just means that we've hit the threshhold again, and so it's proper
//   to run the inner loop again.
//

VOID
ClasspPerfIncrementErrorCount(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
    KIRQL oldIrql;
    ULONG errors;

    KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);

    fdoData->Perf.SuccessfulIO = 0; // implicit interlock
    errors = InterlockedIncrement(&FdoExtension->ErrorCount);

    if (errors >= CLASS_ERROR_LEVEL_1) {

        //
        // If the error count has exceeded the error limit, then disable
        // any tagged queuing, multiple requests per lu queueing
        // and sychronous data transfers.
        //
        // Clearing the no queue freeze flag prevents the port driver
        // from sending multiple requests per logical unit.
        //

        CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
        CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);

        SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);

        DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
                    "Too many errors; disabling tagged queuing and "
                    "synchronous data tranfers.\n"));

    }

    if (errors >= CLASS_ERROR_LEVEL_2) {

        //
        // If a second threshold is reached, disable disconnects.
        //

        SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
        DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
                    "Too many errors; disabling disconnects.\n"));
    }

    KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
    return;
}

VOID
ClasspPerfIncrementSuccessfulIo(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
    KIRQL oldIrql;
    ULONG errors;
    ULONG succeeded = 0;

    //
    // don't take a hit from the interlocked op unless we're in
    // a degraded state and we've got a threshold to hit.
    //

    if (FdoExtension->ErrorCount == 0) {
        return;
    }

    if (fdoData->Perf.ReEnableThreshhold == 0) {
        return;
    }

    succeeded = InterlockedIncrement(&fdoData->Perf.SuccessfulIO);
    if (succeeded < fdoData->Perf.ReEnableThreshhold) {
        return;
    }

    //
    // if we hit the threshold, grab the spinlock and verify we've
    // actually done so.  this allows us to ignore the spinlock 99%
    // of the time.
    //

    KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);

    //
    // re-read the value, so we don't run this multiple times
    // for a single threshhold being hit.  this keeps errorcount
    // somewhat useful.
    //

    succeeded = fdoData->Perf.SuccessfulIO;

    if ((FdoExtension->ErrorCount != 0) &&
        (fdoData->Perf.ReEnableThreshhold <= succeeded)
        ) {

        fdoData->Perf.SuccessfulIO = 0; // implicit interlock

        ASSERT(FdoExtension->ErrorCount > 0);
        errors = InterlockedDecrement(&FdoExtension->ErrorCount);

        //
        // note: do in reverse order of the sets "just in case"
        //

        if (errors < CLASS_ERROR_LEVEL_2) {
            if (errors == CLASS_ERROR_LEVEL_2 - 1) {
                DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
                            "Error level 2 no longer required.\n"));
            }
            if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                           SRB_FLAGS_DISABLE_DISCONNECT)) {
                CLEAR_FLAG(FdoExtension->SrbFlags,
                           SRB_FLAGS_DISABLE_DISCONNECT);
            }
        }

        if (errors < CLASS_ERROR_LEVEL_1) {
            if (errors == CLASS_ERROR_LEVEL_1 - 1) {
                DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
                            "Error level 1 no longer required.\n"));
            }
            if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                           SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
                CLEAR_FLAG(FdoExtension->SrbFlags,
                           SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
            }
            if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                          SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
                SET_FLAG(FdoExtension->SrbFlags,
                         SRB_FLAGS_QUEUE_ACTION_ENABLE);
            }
            if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                          SRB_FLAGS_NO_QUEUE_FREEZE)) {
                SET_FLAG(FdoExtension->SrbFlags,
                         SRB_FLAGS_NO_QUEUE_FREEZE);
            }
        }
    } // end of threshhold definitely being hit for first time

    KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
    return;
}


PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
{
    PMDL mdl;

    mdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL);
    if (mdl){
        try {
            /*
             *  We are reading from the device.
             *  Therefore, the device is WRITING to the locked memory.
             *  So we request IoWriteAccess.
             */
            MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            NTSTATUS status = GetExceptionCode();

            DBGWARN(("BuildReadMdl: MmProbeAndLockPages failed with %xh.", status));
            IoFreeMdl(mdl);
            mdl = NULL;
        }
    }
    else {
        DBGWARN(("BuildReadMdl: IoAllocateMdl failed"));
    }

    return mdl;
}


VOID FreeDeviceInputMdl(PMDL Mdl)
{
    MmUnlockPages(Mdl);
    IoFreeMdl(Mdl);
}


#if 0
    VOID
    ClasspPerfResetCounters(
        IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
        )
    {
        PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
        KIRQL oldIrql;

        KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
        DebugPrint((ClassDebugError, "ClasspPerfResetCounters: "
                    "Resetting all perf counters.\n"));
        fdoData->Perf.SuccessfulIO = 0;
        FdoExtension->ErrorCount = 0;

        if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                       SRB_FLAGS_DISABLE_DISCONNECT)) {
            CLEAR_FLAG(FdoExtension->SrbFlags,
                       SRB_FLAGS_DISABLE_DISCONNECT);
        }
        if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                       SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
            CLEAR_FLAG(FdoExtension->SrbFlags,
                       SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
        }
        if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                      SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
            SET_FLAG(FdoExtension->SrbFlags,
                     SRB_FLAGS_QUEUE_ACTION_ENABLE);
        }
        if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
                      SRB_FLAGS_NO_QUEUE_FREEZE)) {
            SET_FLAG(FdoExtension->SrbFlags,
                     SRB_FLAGS_NO_QUEUE_FREEZE);
        }
        KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
        return;
    }
#endif


⌨️ 快捷键说明

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