📄 isr.cpp
字号:
// the code outside the main loop that
// catches problems chips like the
// SMC and the Winbond.
m_TXHolding &= ~SERIAL_TX_XOFF;
}
}
goto ReceiveDoLineStatus;
}
// Check to see if we should note
// the receive character or special
// character event.
if (m_IsrWaitMask)
{
if (m_IsrWaitMask & SERIAL_EV_RXCHAR)
m_HistoryMask |= SERIAL_EV_RXCHAR;
if ((m_IsrWaitMask & SERIAL_EV_RXFLAG) &&
(m_SpecialChars.EventChar == ReceivedChar))
{
m_HistoryMask |= SERIAL_EV_RXFLAG;
}
if (m_IrpMaskLocation && m_HistoryMask)
{
*m_IrpMaskLocation = m_HistoryMask;
m_IrpMaskLocation = NULL;
m_HistoryMask = 0;
m_CurrentWaitIrp.Information() = sizeof(ULONG);
m_KdDpc_CommWait.InsertQueue();
}
}
PutChar(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 (m_EscapeChar &&(m_EscapeChar==ReceivedChar))
PutChar(SERIAL_LSRMST_ESCAPE);
ReceiveDoLineStatus: ;
if (!(ProcessLSR() &
SERIAL_LSR_DR))
{
// No more characters, get out of the
// loop.
break;
}
} while (TRUE);
break;
case SERIAL_IIR_THR:
doTrasmitStuff:;
m_HoldingEmpty = TRUE;
if (m_WriteLength || m_TransmitImmediate ||
m_SendXoffChar || m_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.
m_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 (m_HandFlow.ControlHandShake &
SERIAL_OUT_HANDSHAKEMASK)
{
HandleModemUpdate(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 (m_SendXonChar &&
!(m_TXHolding & ~SERIAL_TX_XOFF))
{
if ((m_HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
{
// We have to raise if we're sending
// this character.
SetRTS();
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_SpecialChars.XonChar);
m_KdDpc_StartTimerLowerRTSDpc.InsertQueue()
? m_CountOfTryingToLowerRTS++ : 0;
}
else
{
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_SpecialChars.XonChar);
}
m_SendXonChar = FALSE;
m_HoldingEmpty = FALSE;
// If we send an xon, by definition we
// can't be holding by Xoff.
m_TXHolding &= ~SERIAL_TX_XOFF;
// If we are sending an xon char then
// by definition we can't be "holding"
// up reception by Xoff.
m_RXHolding &= ~SERIAL_RX_XOFF;
}
else if (m_SendXoffChar && !m_TXHolding)
{
if ((m_HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
{
// We have to raise if we're sending
// this character.
SetRTS();
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_SpecialChars.XoffChar);
m_KdDpc_StartTimerLowerRTSDpc.InsertQueue()
? m_CountOfTryingToLowerRTS++ : 0;
}
else
{
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_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 (!(m_HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE))
{
m_TXHolding |= SERIAL_TX_XOFF;
if ((m_HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
{
m_KdDpc_StartTimerLowerRTSDpc.InsertQueue()
? m_CountOfTryingToLowerRTS++ : 0;
}
}
m_SendXoffChar = FALSE;
m_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 (m_TransmitImmediate &&
(!m_TXHolding || (m_TXHolding == SERIAL_TX_XOFF)))
{
m_TransmitImmediate = FALSE;
if ((m_HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
{
// We have to raise if we're sending this character.
SetRTS();
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_ImmediateChar);
m_KdDpc_StartTimerLowerRTSDpc.InsertQueue() ? m_CountOfTryingToLowerRTS++ : 0;
}
else
{
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_ImmediateChar);
}
m_HoldingEmpty = FALSE;
m_KdDpc_CompleteImmediate.InsertQueue();
}
else if (!m_TXHolding)
{
ULONG amountToWrite;
if (m_FifoPresent)
{
amountToWrite = (m_TxFifoAmount < m_WriteLength) ?
m_TxFifoAmount : m_WriteLength;
}
else
amountToWrite = 1;
if ((m_HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
{
// We have to raise if we're sending
// this character.
SetRTS();
if (amountToWrite == 1)
{
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, *(m_WriteCurrentChar));
}
else
{
m_PerfStats.TransmittedCount += amountToWrite;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER,
m_WriteCurrentChar,
amountToWrite);
}
m_KdDpc_StartTimerLowerRTSDpc.InsertQueue()
? m_CountOfTryingToLowerRTS++ : 0;
}
else
{
if (amountToWrite == 1)
{
m_PerfStats.TransmittedCount++;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, *(m_WriteCurrentChar));
}
else
{
m_PerfStats.TransmittedCount +=
amountToWrite;
m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER,
m_WriteCurrentChar,
amountToWrite);
}
}
m_HoldingEmpty = FALSE;
m_WriteCurrentChar += amountToWrite;
m_WriteLength -= amountToWrite;
if (!m_WriteLength)
{
// 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.
m_CurrentWriteIrp.Information() =
m_CurrentWriteIrp.MajorFunction()==IRP_MJ_WRITE ?
m_CurrentWriteIrp.WriteLength() : 1 ;
m_KdDpc_CompleteWrite.InsertQueue();
}
}
}
break;
case SERIAL_IIR_MS:
HandleModemUpdate(FALSE);
break;
}
} while (!((InterruptIdReg = m_pController->ReadByte(INTERRUPT_IDENT_REGISTER))
& 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 (ProcessLSR() & SERIAL_LSR_THRE)
{
if (!m_TXHolding && (m_WriteLength || m_TransmitImmediate))
goto doTrasmitStuff;
}
}
return ServicedAnInterrupt;
}
VOID KdSerialDevice::PutChar( IN UCHAR CharToPut )
/*++
Routine Description:
This routine, which only runs at device level, takes care of
placing a character into the typeahead (receive) buffer.
--*/
{
// If we have dsr sensitivity enabled then
// we need to check the modem status register
// to see if it has changed.
if (m_HandFlow.ControlHandShake &
SERIAL_DSR_SENSITIVITY)
{
HandleModemUpdate(FALSE);
if (m_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 (m_CountSinceXoff)
{
m_CountSinceXoff--;
if (!m_CountSinceXoff)
{
m_CurrentXoffIrp.Status() = STATUS_SUCCESS;
m_CurrentXoffIrp.Information() = 0;
m_KdDpc_XoffCountComplete.InsertQueue();
}
}
// 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -