📄 isr.c
字号:
}
case SERIAL_IIR_MS: {
READ_MODEM_STATUS(Extension->Controller);
break;
}
default: {
ASSERT(FALSE);
break;
}
}
} while (!((InterruptIdReg =
READ_INTERRUPT_ID_REG(Extension->Controller))
& SERIAL_IIR_NO_INTERRUPT_PENDING));
} else {
ServicedAnInterrupt = TRUE;
do {
//
// We only care about bits that can denote an interrupt.
//
InterruptIdReg &= SERIAL_IIR_RLS | SERIAL_IIR_RDA |
SERIAL_IIR_CTI | SERIAL_IIR_THR |
SERIAL_IIR_MS;
//
// We have an interrupt. We look for interrupt causes
// in priority order. The presence of a higher interrupt
// will mask out causes of a lower priority. When we service
// and quiet a higher priority interrupt we then need to check
// the interrupt causes to see if a new interrupt cause is
// present.
//
switch (InterruptIdReg) {
case SERIAL_IIR_RLS: {
SerialProcessLSR(Extension);
break;
}
case SERIAL_IIR_RDA:
case SERIAL_IIR_CTI:
{
//
// Reading the receive buffer will quiet this interrupt.
//
// It may also reveal a new interrupt cause.
//
UCHAR ReceivedChar;
do {
ReceivedChar =
READ_RECEIVE_BUFFER(Extension->Controller);
Extension->PerfStats.ReceivedCount++;
Extension->WmiPerfData.ReceivedCount++;
ReceivedChar &= Extension->ValidDataMask;
if (!ReceivedChar &&
(Extension->HandFlow.FlowReplace &
SERIAL_NULL_STRIPPING)) {
//
// If what we got is a null character
// and we're doing null stripping, then
// we simply act as if we didn't see it.
//
goto ReceiveDoLineStatus;
}
if ((Extension->HandFlow.FlowReplace &
SERIAL_AUTO_TRANSMIT) &&
((ReceivedChar ==
Extension->SpecialChars.XonChar) ||
(ReceivedChar ==
Extension->SpecialChars.XoffChar))) {
//
// No matter what happens this character
// will never get seen by the app.
//
if (ReceivedChar ==
Extension->SpecialChars.XoffChar) {
Extension->TXHolding |= SERIAL_TX_XOFF;
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
}
} else {
if (Extension->TXHolding & SERIAL_TX_XOFF) {
//
// We got the xon char **AND*** we
// were being held up on transmission
// by xoff. Clear that we are holding
// due to xoff. Transmission will
// automatically restart because of
// the code outside the main loop that
// catches problems chips like the
// SMC and the Winbond.
//
Extension->TXHolding &= ~SERIAL_TX_XOFF;
}
}
goto ReceiveDoLineStatus;
}
//
// Check to see if we should note
// the receive character or special
// character event.
//
if (Extension->IsrWaitMask) {
if (Extension->IsrWaitMask &
SERIAL_EV_RXCHAR) {
Extension->HistoryMask |= SERIAL_EV_RXCHAR;
}
if ((Extension->IsrWaitMask &
SERIAL_EV_RXFLAG) &&
(Extension->SpecialChars.EventChar ==
ReceivedChar)) {
Extension->HistoryMask |= SERIAL_EV_RXFLAG;
}
if (Extension->IrpMaskLocation &&
Extension->HistoryMask) {
*Extension->IrpMaskLocation =
Extension->HistoryMask;
Extension->IrpMaskLocation = NULL;
Extension->HistoryMask = 0;
Extension->CurrentWaitIrp->
IoStatus.Information = sizeof(ULONG);
SerialInsertQueueDpc(
&Extension->CommWaitDpc,
NULL,
NULL,
Extension
);
}
}
SerialPutChar(
Extension,
ReceivedChar
);
//
// If we're doing line status and modem
// status insertion then we need to insert
// a zero following the character we just
// placed into the buffer to mark that this
// was reception of what we are using to
// escape.
//
if (Extension->EscapeChar &&
(Extension->EscapeChar ==
ReceivedChar)) {
SerialPutChar(
Extension,
SERIAL_LSRMST_ESCAPE
);
}
ReceiveDoLineStatus: ;
if (!((tempLSR = SerialProcessLSR(Extension)) &
SERIAL_LSR_DR)) {
//
// No more characters, get out of the
// loop.
//
break;
}
if ((tempLSR & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT |
SERIAL_LSR_DR)) &&
Extension->EscapeChar) {
//
// An error was indicated and inserted into the
// stream, get out of the loop.
//
break;
}
} while (TRUE);
break;
}
case SERIAL_IIR_THR: {
doTrasmitStuff:;
Extension->HoldingEmpty = TRUE;
if (Extension->WriteLength ||
Extension->TransmitImmediate ||
Extension->SendXoffChar ||
Extension->SendXonChar) {
//
// Even though all of the characters being
// sent haven't all been sent, this variable
// will be checked when the transmit queue is
// empty. If it is still true and there is a
// wait on the transmit queue being empty then
// we know we finished transmitting all characters
// following the initiation of the wait since
// the code that initiates the wait will set
// this variable to false.
//
// One reason it could be false is that
// the writes were cancelled before they
// actually started, or that the writes
// failed due to timeouts. This variable
// basically says a character was written
// by the isr at some point following the
// initiation of the wait.
//
Extension->EmptiedTransmit = TRUE;
//
// If we have output flow control based on
// the modem status lines, then we have to do
// all the modem work before we output each
// character. (Otherwise we might miss a
// status line change.)
//
if (Extension->HandFlow.ControlHandShake &
SERIAL_OUT_HANDSHAKEMASK) {
SerialHandleModemUpdate(
Extension,
TRUE
);
}
//
// We can only send the xon character if
// the only reason we are holding is because
// of the xoff. (Hardware flow control or
// sending break preclude putting a new character
// on the wire.)
//
if (Extension->SendXonChar &&
!(Extension->TXHolding & ~SERIAL_TX_XOFF)) {
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XonChar
);
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XonChar
);
}
Extension->SendXonChar = FALSE;
Extension->HoldingEmpty = FALSE;
//
// If we send an xon, by definition we
// can't be holding by Xoff.
//
Extension->TXHolding &= ~SERIAL_TX_XOFF;
//
// If we are sending an xon char then
// by definition we can't be "holding"
// up reception by Xoff.
//
Extension->RXHolding &= ~SERIAL_RX_XOFF;
} else if (Extension->SendXoffChar &&
!Extension->TXHolding) {
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XoffChar
);
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XoffChar
);
}
//
// We can't be sending an Xoff character
// if the transmission is already held
// up because of Xoff. Therefore, if we
// are holding then we can't send the char.
//
//
// If the application has set xoff continue
// mode then we don't actually stop sending
// characters if we send an xoff to the other
// side.
//
if (!(Extension->HandFlow.FlowReplace &
SERIAL_XOFF_CONTINUE)) {
Extension->TXHolding |= SERIAL_TX_XOFF;
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
}
}
Extension->SendXoffChar = FALSE;
Extension->HoldingEmpty = FALSE;
//
// Even if transmission is being held
// up, we should still transmit an immediate
// character if all that is holding us
// up is xon/xoff (OS/2 rules).
//
} else if (Extension->TransmitImmediate &&
(!Extension->TXHolding ||
(Extension->TXHolding == SERIAL_TX_XOFF)
)) {
Extension->TransmitImmediate = FALSE;
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -