📄 utils.c
字号:
--*/
{
LONG pendingCnt;
pendingCnt = InterlockedDecrement(&PDevExt->PendingIRPCnt);
ASSERT(pendingCnt >= 0);
if (pendingCnt == 0) {
KeSetEvent(&PDevExt->PendingIRPEvent, IO_NO_INCREMENT, FALSE);
}
}
BOOLEAN
SerialInsertQueueDpc(IN PRKDPC PDpc, IN PVOID Sarg1, IN PVOID Sarg2,
IN PDEVICE_EXTENSION PDevExt)
/*++
Routine Description:
This function must be called to queue DPC's for the serial driver.
Arguments:
PDpc thru Sarg2 - Standard args to KeInsertQueueDpc()
PDevExt - Pointer to the device extension for the device that needs to
queue a DPC
Return Value:
Kicks up return value from KeInsertQueueDpc()
--*/
{
BOOLEAN queued;
InterlockedIncrement(&PDevExt->DpcCount);
//LOGENTRY(LOG_CNT, 'DpI1', PDpc, PDevExt->DpcCount, 0);
queued = KeInsertQueueDpc(PDpc, Sarg1, Sarg2);
if (!queued) {
ULONG pendingCnt;
pendingCnt = InterlockedDecrement(&PDevExt->DpcCount);
// LOGENTRY(LOG_CNT, 'DpD1', PDpc, PDevExt->DpcCount, 0);
if (pendingCnt == 0) {
KeSetEvent(&PDevExt->PendingIRPEvent, IO_NO_INCREMENT, FALSE);
//LOGENTRY(LOG_CNT, 'DpF1', PDpc, PDevExt->DpcCount, 0);
}
}
#if 0 // DBG
if (queued) {
int i;
for (i = 0; i < MAX_DPC_QUEUE; i++) {
if (PDevExt->DpcQueued[i].Dpc == PDpc) {
PDevExt->DpcQueued[i].QueuedCount++;
break;
}
}
ASSERT(i < MAX_DPC_QUEUE);
}
#endif
return queued;
}
BOOLEAN
SerialSetTimer(IN PKTIMER Timer, IN LARGE_INTEGER DueTime,
IN PKDPC Dpc OPTIONAL, IN PDEVICE_EXTENSION PDevExt)
/*++
Routine Description:
This function must be called to set timers for the serial driver.
Arguments:
Timer - pointer to timer dispatcher object
DueTime - time at which the timer should expire
Dpc - option Dpc
PDevExt - Pointer to the device extension for the device that needs to
set a timer
Return Value:
Kicks up return value from KeSetTimer()
--*/
{
BOOLEAN set;
InterlockedIncrement(&PDevExt->DpcCount);
//LOGENTRY(LOG_CNT, 'DpI2', Dpc, PDevExt->DpcCount, 0);
set = KeSetTimer(Timer, DueTime, Dpc);
if (set) {
InterlockedDecrement(&PDevExt->DpcCount);
// LOGENTRY(LOG_CNT, 'DpD2', Dpc, PDevExt->DpcCount, 0);
}
#if 0 // DBG
if (set) {
int i;
for (i = 0; i < MAX_DPC_QUEUE; i++) {
if (PDevExt->DpcQueued[i].Dpc == Dpc) {
PDevExt->DpcQueued[i].QueuedCount++;
break;
}
}
ASSERT(i < MAX_DPC_QUEUE);
}
#endif
return set;
}
BOOLEAN
SerialCancelTimer(IN PKTIMER Timer, IN PDEVICE_EXTENSION PDevExt)
/*++
Routine Description:
This function must be called to cancel timers for the serial driver.
Arguments:
Timer - pointer to timer dispatcher object
PDevExt - Pointer to the device extension for the device that needs to
set a timer
Return Value:
True if timer was cancelled
--*/
{
BOOLEAN cancelled;
cancelled = KeCancelTimer(Timer);
if (cancelled) {
SerialDpcEpilogue(PDevExt, Timer->Dpc);
}
return cancelled;
}
VOID
SerialDpcEpilogue(IN PDEVICE_EXTENSION PDevExt, PKDPC PDpc)
/*++
Routine Description:
This function must be called at the end of every dpc function.
Arguments:
PDevObj - Pointer to the device object we are tracking dpc's for.
Return Value:
None.
--*/
{
LONG pendingCnt;
#if 1 // !DBG
UNREFERENCED_PARAMETER(PDpc);
#endif
pendingCnt = InterlockedDecrement(&PDevExt->DpcCount);
// LOGENTRY(LOG_CNT, 'DpD3', PDpc, PDevExt->DpcCount, 0);
ASSERT(pendingCnt >= 0);
#if 0 //DBG
{
int i;
for (i = 0; i < MAX_DPC_QUEUE; i++) {
if (PDevExt->DpcQueued[i].Dpc == PDpc) {
PDevExt->DpcQueued[i].FlushCount++;
ASSERT(PDevExt->DpcQueued[i].QueuedCount >=
PDevExt->DpcQueued[i].FlushCount);
break;
}
}
ASSERT(i < MAX_DPC_QUEUE);
}
#endif
if (pendingCnt == 0) {
KeSetEvent(&PDevExt->PendingDpcEvent, IO_NO_INCREMENT, FALSE);
//LOGENTRY(LOG_CNT, 'DpF2', PDpc, PDevExt->DpcCount, 0);
}
}
VOID
SerialUnlockPages(IN PKDPC PDpc, IN PVOID PDeferredContext,
IN PVOID PSysContext1, IN PVOID PSysContext2)
/*++
Routine Description:
This function is a DPC routine queue from the ISR if he released the
last lock on pending DPC's.
Arguments:
PDpdc, PSysContext1, PSysContext2 -- not used
PDeferredContext -- Really the device extension
Return Value:
None.
--*/
{
PDEVICE_EXTENSION pDevExt
= (PDEVICE_EXTENSION)PDeferredContext;
UNREFERENCED_PARAMETER(PDpc);
UNREFERENCED_PARAMETER(PSysContext1);
UNREFERENCED_PARAMETER(PSysContext2);
KeSetEvent(&pDevExt->PendingDpcEvent, IO_NO_INCREMENT, FALSE);
}
NTSTATUS
SerialIoCallDriver(PDEVICE_EXTENSION PDevExt, PDEVICE_OBJECT PDevObj,
PIRP PIrp)
/*++
Routine Description:
This function must be called instead of IoCallDriver. It automatically
updates Irp tracking for PDevObj.
Arguments:
PDevExt - Device extension attached to PDevObj
PDevObj - Pointer to the device object we are tracking pending IRP's for.
PIrp - Pointer to the Irp we are passing to the next driver.
Return Value:
None.
--*/
{
NTSTATUS status;
status = IoCallDriver(PDevObj, PIrp);
SerialIRPEpilogue(PDevExt);
return status;
}
NTSTATUS
SerialPoCallDriver(PDEVICE_EXTENSION PDevExt, PDEVICE_OBJECT PDevObj,
PIRP PIrp)
/*++
Routine Description:
This function must be called instead of PoCallDriver. It automatically
updates Irp tracking for PDevObj.
Arguments:
PDevExt - Device extension attached to PDevObj
PDevObj - Pointer to the device object we are tracking pending IRP's for.
PIrp - Pointer to the Irp we are passing to the next driver.
Return Value:
None.
--*/
{
NTSTATUS status;
status = PoCallDriver(PDevObj, PIrp);
SerialIRPEpilogue(PDevExt);
return status;
}
VOID
SerialLogError(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN PHYSICAL_ADDRESS P1,
IN PHYSICAL_ADDRESS P2,
IN ULONG SequenceNumber,
IN UCHAR MajorFunctionCode,
IN UCHAR RetryCount,
IN ULONG UniqueErrorValue,
IN NTSTATUS FinalStatus,
IN NTSTATUS SpecificIOStatus,
IN ULONG LengthOfInsert1,
IN PWCHAR Insert1,
IN ULONG LengthOfInsert2,
IN PWCHAR Insert2
)
/*++
Routine Description:
This routine allocates an error log entry, copies the supplied data
to it, and requests that it be written to the error log file.
Arguments:
DriverObject - A pointer to the driver object for the device.
DeviceObject - A pointer to the device object associated with the
device that had the error, early in initialization, one may not
yet exist.
P1,P2 - If phyical addresses for the controller ports involved
with the error are available, put them through as dump data.
SequenceNumber - A ulong value that is unique to an IRP over the
life of the irp in this driver - 0 generally means an error not
associated with an irp.
MajorFunctionCode - If there is an error associated with the irp,
this is the major function code of that irp.
RetryCount - The number of times a particular operation has been
retried.
UniqueErrorValue - A unique long word that identifies the particular
call to this function.
FinalStatus - The final status given to the irp that was associated
with this error. If this log entry is being made during one of
the retries this value will be STATUS_SUCCESS.
SpecificIOStatus - The IO status for a particular error.
LengthOfInsert1 - The length in bytes (including the terminating NULL)
of the first insertion string.
Insert1 - The first insertion string.
LengthOfInsert2 - The length in bytes (including the terminating NULL)
of the second insertion string. NOTE, there must
be a first insertion string for their to be
a second insertion string.
Insert2 - The second insertion string.
Return Value:
None.
--*/
{
PIO_ERROR_LOG_PACKET errorLogEntry;
PVOID objectToUse;
SHORT dumpToAllocate = 0;
PUCHAR ptrToFirstInsert;
PUCHAR ptrToSecondInsert;
PAGED_CODE();
if (Insert1 == NULL) {
LengthOfInsert1 = 0;
}
if (Insert2 == NULL) {
LengthOfInsert2 = 0;
}
if (ARGUMENT_PRESENT(DeviceObject)) {
objectToUse = DeviceObject;
} else {
objectToUse = DriverObject;
}
/*
if (SerialMemCompare(
P1,
(ULONG)1,
SerialPhysicalZero,
(ULONG)1
) != AddressesAreEqual) {
dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS);
}
if (SerialMemCompare(
P2,
(ULONG)1,
SerialPhysicalZero,
(ULONG)1
) != AddressesAreEqual) {
dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS);
}
*/
errorLogEntry = IoAllocateErrorLogEntry(
objectToUse,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
dumpToAllocate
+ LengthOfInsert1 +
LengthOfInsert2)
);
if ( errorLogEntry != NULL ) {
errorLogEntry->ErrorCode = SpecificIOStatus;
errorLogEntry->SequenceNumber = SequenceNumber;
errorLogEntry->MajorFunctionCode = MajorFunctionCode;
errorLogEntry->RetryCount = RetryCount;
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
errorLogEntry->FinalStatus = FinalStatus;
errorLogEntry->DumpDataSize = dumpToAllocate;
if (dumpToAllocate) {
RtlCopyMemory(
&errorLogEntry->DumpData[0],
&P1,
sizeof(PHYSICAL_ADDRESS)
);
if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) {
RtlCopyMemory(
((PUCHAR)&errorLogEntry->DumpData[0])
+sizeof(PHYSICAL_ADDRESS),
&P2,
sizeof(PHYSICAL_ADDRESS)
);
ptrToFirstInsert =
((PUCHAR)&errorLogEntry->DumpData[0])+(2*sizeof(PHYSICAL_ADDRESS));
} else {
ptrToFirstInsert =
((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS);
}
} else {
ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0];
}
ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1;
if (LengthOfInsert1) {
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert -
(PUCHAR)errorLogEntry);
RtlCopyMemory(
ptrToFirstInsert,
Insert1,
LengthOfInsert1
);
if (LengthOfInsert2) {
errorLogEntry->NumberOfStrings = 2;
RtlCopyMemory(
ptrToSecondInsert,
Insert2,
LengthOfInsert2
);
}
}
IoWriteErrorLogEntry(errorLogEntry);
}
}
VOID
SerialMarkHardwareBroken(IN PDEVICE_EXTENSION PDevExt)
/*++
Routine Description:
Marks a UART as broken. This causes the driver stack to stop accepting
requests and eventually be removed.
Arguments:
PDevExt - Device extension attached to PDevObj
Return Value:
None.
--*/
{
/* PAGED_CODE();
//
// Mark as damaged goods
//
SerialSetFlags(PDevExt, SERIAL_FLAGS_BROKENHW);
//
// Write a log entry
//
SerialLogError(PDevExt->DriverObject, NULL, SerialPhysicalZero,
SerialPhysicalZero, 0, 0, 0, 88, STATUS_SUCCESS,
SERIAL_HARDWARE_FAILURE, PDevExt->DeviceName.Length
+ sizeof(WCHAR), PDevExt->DeviceName.Buffer, 0, NULL);
//
// Invalidate the device
//
IoInvalidateDeviceState(PDevExt->Pdo);
*/
}
VOID
SerialSetDeviceFlags(IN PDEVICE_EXTENSION PDevExt, OUT PULONG PFlags,
IN ULONG Value, IN BOOLEAN Set)
/*++
Routine Description:
Sets flags in a value protected by the flags spinlock. This is used
to set values that would stop IRP's from being accepted.
Arguments:
PDevExt - Device extension attached to PDevObj
PFlags - Pointer to the flags variable that needs changing
Value - Value to modify flags variable with
Set - TRUE if |= , FALSE if &=
Return Value:
None.
--*/
{
KIRQL oldIrql;
KeAcquireSpinLock(&PDevExt->FlagsLock, &oldIrql);
if (Set) {
*PFlags |= Value;
} else {
*PFlags &= ~Value;
}
KeReleaseSpinLock(&PDevExt->FlagsLock, oldIrql);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -