📄 isr.c
字号:
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->ImmediateChar
);
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->ImmediateChar
);
}
Extension->HoldingEmpty = FALSE;
SerialInsertQueueDpc(
&Extension->CompleteImmediateDpc,
NULL,
NULL,
Extension
);
} else if (!Extension->TXHolding) {
ULONG amountToWrite;
if (Extension->FifoPresent) {
amountToWrite = (Extension->TxFifoAmount <
Extension->WriteLength)?
Extension->TxFifoAmount:
Extension->WriteLength;
} else {
amountToWrite = 1;
}
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
if (amountToWrite == 1) {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
*(Extension->WriteCurrentChar)
);
} else {
Extension->PerfStats.TransmittedCount +=
amountToWrite;
Extension->WmiPerfData.TransmittedCount +=
amountToWrite;
WRITE_TRANSMIT_FIFO_HOLDING(
Extension->Controller,
Extension->WriteCurrentChar,
amountToWrite
);
}
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
if (amountToWrite == 1) {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
*(Extension->WriteCurrentChar)
);
} else {
Extension->PerfStats.TransmittedCount +=
amountToWrite;
Extension->WmiPerfData.TransmittedCount +=
amountToWrite;
WRITE_TRANSMIT_FIFO_HOLDING(
Extension->Controller,
Extension->WriteCurrentChar,
amountToWrite
);
}
}
Extension->HoldingEmpty = FALSE;
Extension->WriteCurrentChar += amountToWrite;
Extension->WriteLength -= amountToWrite;
if (!Extension->WriteLength) {
PIO_STACK_LOCATION IrpSp;
//
// No More characters left. This
// write is complete. Take care
// when updating the information field,
// we could have an xoff counter masquerading
// as a write irp.
//
IrpSp = IoGetCurrentIrpStackLocation(
Extension->CurrentWriteIrp
);
Extension->CurrentWriteIrp->
IoStatus.Information =
(IrpSp->MajorFunction == IRP_MJ_WRITE)?
(IrpSp->Parameters.Write.Length):
(1);
SerialInsertQueueDpc(
&Extension->CompleteWriteDpc,
NULL,
NULL,
Extension
);
}
}
}
break;
}
case SERIAL_IIR_MS: {
SerialHandleModemUpdate(
Extension,
FALSE
);
break;
}
}
} while (!((InterruptIdReg =
READ_INTERRUPT_ID_REG(Extension->Controller))
& SERIAL_IIR_NO_INTERRUPT_PENDING));
//
// Besides catching the WINBOND and SMC chip problems this
// will also cause transmission to restart incase of an xon
// char being received. Don't remove.
//
if (SerialProcessLSR(Extension) & SERIAL_LSR_THRE) {
if (!Extension->TXHolding &&
(Extension->WriteLength ||
Extension->TransmitImmediate)) {
goto doTrasmitStuff;
}
}
}
//
// This will "unlock" the close and cause the event
// to fire if we didn't queue any DPC's
//
{
LONG pendingCnt;
//
// Increment once more. This is just a quick test to see if we
// have a chance of causing the event to fire... we don't want
// to run a DPC on every ISR if we don't have to....
//
retryDPCFiring:;
InterlockedIncrement(&Extension->DpcCount);
LOGENTRY(LOG_CNT, 'DpI4', 0, Extension->DpcCount, 0);
//
// Decrement and see if the lock above looks like the only one left.
//
pendingCnt = InterlockedDecrement(&Extension->DpcCount);
// LOGENTRY(LOG_CNT, 'DpD5', 0, Extension->DpcCount, 0);
if (pendingCnt == 1) {
KeInsertQueueDpc(&Extension->IsrUnlockPagesDpc, NULL, NULL);
} else {
if (InterlockedDecrement(&Extension->DpcCount) == 0) {
// LOGENTRY(LOG_CNT, 'DpD6', &Extension->IsrUnlockPagesDpc,
// Extension->DpcCount, 0);
//
// We missed it. Retry...
//
InterlockedIncrement(&Extension->DpcCount);
LOGENTRY(LOG_CNT, 'DpI5', &Extension->IsrUnlockPagesDpc,
Extension->DpcCount, 0);
goto retryDPCFiring;
}
}
}
return ServicedAnInterrupt;
}
VOID
SerialPutChar(
IN PSERIAL_DEVICE_EXTENSION Extension,
IN UCHAR CharToPut
)
/*++
Routine Description:
This routine, which only runs at device level, takes care of
placing a character into the typeahead (receive) buffer.
Arguments:
Extension - The serial device extension.
Return Value:
None.
--*/
{
SERIAL_LOCKED_PAGED_CODE();
//
// If we have dsr sensitivity enabled then
// we need to check the modem status register
// to see if it has changed.
//
if (Extension->HandFlow.ControlHandShake &
SERIAL_DSR_SENSITIVITY) {
SerialHandleModemUpdate(
Extension,
FALSE
);
if (Extension->RXHolding & SERIAL_RX_DSR) {
//
// We simply act as if we haven't
// seen the character if we have dsr
// sensitivity and the dsr line is low.
//
return;
}
}
//
// If the xoff counter is non-zero then decrement it.
// If the counter then goes to zero, complete that irp.
//
if (Extension->CountSinceXoff) {
Extension->CountSinceXoff--;
if (!Extension->CountSinceXoff) {
Extension->CurrentXoffIrp->IoStatus.Status = STATUS_SUCCESS;
Extension->CurrentXoffIrp->IoStatus.Information = 0;
SerialInsertQueueDpc(
&Extension->XoffCountCompleteDpc,
NULL,
NULL,
Extension
);
}
}
//
// Check to see if we are copying into the
// users buffer or into the interrupt buffer.
//
// If we are copying into the user buffer
// then we know there is always room for one more.
// (We know this because if there wasn't room
// then that read would have completed and we
// would be using the interrupt buffer.)
//
// If we are copying into the interrupt buffer
// then we will need to check if we have enough
// room.
//
if (Extension->ReadBufferBase !=
Extension->InterruptReadBuffer) {
//
// Increment the following value so
// that the interval timer (if one exists
// for this read) can know that a character
// has been read.
//
Extension->ReadByIsr++;
//
// We are in the user buffer. Place the
// character into the buffer. See if the
// read is complete.
//
*Extension->CurrentCharSlot = CharToPut;
if (Extension->CurrentCharSlot ==
Extension->LastCharSlot) {
//
// We've filled up the users buffer.
// Switch back to the interrupt buffer
// and send off a DPC to Complete the read.
//
// It is inherent that when we were using
// a user buffer that the interrupt buffer
// was empty.
//
Extension->ReadBufferBase =
Extension->InterruptReadBuffer;
Extension->CurrentCharSlot =
Extension->InterruptReadBuffer;
Extension->FirstReadableChar =
Extension->InterruptReadBuffer;
Extension->LastCharSlot =
Extension->InterruptReadBuffer +
(Extension->BufferSize - 1);
Extension->CharsInInterruptBuffer = 0;
Extension->CurrentReadIrp->IoStatus.Information =
IoGetCurrentIrpStackLocation(
Extension->CurrentReadIrp
)->Parameters.Read.Length;
SerialInsertQueueDpc(
&Extension->CompleteReadDpc,
NULL,
NULL,
Extension
);
} else {
//
// Not done with the users read.
//
Extension->CurrentCharSlot++;
}
} else {
//
// We need to see if we reached our flow
// control threshold. If we have then
// we turn on whatever flow control the
// owner has specified. If no flow
// control was specified, well..., we keep
// trying to receive characters and hope that
// we have enough room. Note that no matter
// what flow control protocol we are using, it
// will not prevent us from reading whatever
// characters are available.
//
if ((Extension->HandFlow.ControlHandShake
& SERIAL_DTR_MASK) ==
SERIAL_DTR_HANDSHAKE) {
//
// If we are already doing a
// dtr hold then we don't have
// to do anything else.
//
if (!(Extension->RXHolding &
SERIAL_RX_DTR)) {
if ((Extension->BufferSize -
Extension->HandFlow.XoffLimit)
<= (Extension->CharsInInterruptBuffer+1)) {
Extension->RXHolding |= SERIAL_RX_DTR;
SerialClrDTR(Extension);
}
}
}
if ((Extension->HandFlow.FlowReplace
& SERIAL_RTS_MASK) ==
SERIAL_RTS_HANDSHAKE) {
//
// If we are already doing a
// rts hold then we don't have
// to do anything else.
//
if (!(Extension->RXHolding &
SERIAL_RX_RTS)) {
if ((Extension->BufferSize -
Extension->HandFlow.XoffLimit)
<= (Extension->CharsInInterruptBuffer+1)) {
Extension->RXHolding |= SERIAL_RX_RTS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -