📄 utils.c
字号:
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 + -