📄 modmflow.c
字号:
*/
} else {
//
// The following routine will lower the rts if we
// are doing transmit toggleing and there is no
// reason to keep it up.
//
Extension->CountOfTryingToLowerRTS++;
SerialPerhapsLowerRTS(Extension);
}
}
return FALSE;
}
BOOLEAN
SerialPretendXoff(
IN PVOID Context
)
/*++
Routine Description:
This routine is used to process the Ioctl that request the
driver to act as if an Xoff was received. Even if the
driver does not have automatic Xoff/Xon flowcontrol - This
still will stop the transmission. This is the OS/2 behavior
and is not well specified for Windows. Therefore we adopt
the OS/2 behavior.
Note: If the driver does not have automatic Xoff/Xon enabled
then the only way to restart transmission is for the
application to request we "act" as if we saw the xon.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
Extension->TXHolding |= SERIAL_TX_XOFF;
if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
}
return FALSE;
}
BOOLEAN
SerialPretendXon(
IN PVOID Context
)
/*++
Routine Description:
This routine is used to process the Ioctl that request the
driver to act as if an Xon was received.
Note: If the driver does not have automatic Xoff/Xon enabled
then the only way to restart transmission is for the
application to request we "act" as if we saw the xon.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
if (Extension->TXHolding) {
//
// We actually have a good reason for testing if transmission
// is holding instead of blindly clearing the bit.
//
// If transmission actually was holding and the result of
// clearing the bit is that we should restart transmission
// then we will poke the interrupt enable bit, which will
// cause an actual interrupt and transmission will then
// restart on its own.
//
// If transmission wasn't holding and we poked the bit
// then we would interrupt before a character actually made
// it out and we could end up over writing a character in
// the transmission hardware.
Extension->TXHolding &= ~SERIAL_TX_XOFF;
if (!Extension->TXHolding &&
(Extension->TransmitImmediate ||
Extension->WriteLength) &&
Extension->HoldingEmpty) {
/*
DISABLE_ALL_INTERRUPTS(Extension->Controller);
ENABLE_ALL_INTERRUPTS(Extension->Controller);
*/
}
}
return FALSE;
}
VOID
SerialHandleReducedIntBuffer(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine is called to handle a reduction in the number
of characters in the interrupt (typeahead) buffer. It
will check the current output flow control and re-enable transmission
as needed.
NOTE: This routine assumes that it is working at interrupt level.
Arguments:
Extension - A pointer to the device extension.
Return Value:
None.
--*/
{
//
// If we are doing receive side flow control and we are
// currently "holding" then because we've emptied out
// some characters from the interrupt buffer we need to
// see if we can "re-enable" reception.
//
if (Extension->RXHolding) {
if (Extension->CharsInInterruptBuffer <=
(ULONG)Extension->HandFlow.XonLimit) {
if (Extension->RXHolding & SERIAL_RX_DTR) {
Extension->RXHolding &= ~SERIAL_RX_DTR;
SerialSetDTR(Extension);
}
if (Extension->RXHolding & SERIAL_RX_RTS) {
Extension->RXHolding &= ~SERIAL_RX_RTS;
SerialSetRTS(Extension);
}
if (Extension->RXHolding & SERIAL_RX_XOFF) {
//
// Prod the transmit code to send xon.
//
SerialProdXonXoff(
Extension,
TRUE
);
}
}
}
}
VOID
SerialProdXonXoff(
IN PDEVICE_EXTENSION Extension,
IN BOOLEAN SendXon
)
/*++
Routine Description:
This routine will set up the SendXxxxChar variables if
necessary and determine if we are going to be interrupting
because of current transmission state. It will cause an
interrupt to occur if neccessary, to send the xon/xoff char.
NOTE: This routine assumes that it is called at interrupt
level.
Arguments:
Extension - A pointer to the serial device extension.
SendXon - If a character is to be send, this indicates whether
it should be an Xon or an Xoff.
Return Value:
None.
--*/
{
//
// We assume that if the prodding is called more than
// once that the last prod has set things up appropriately.
//
// We could get called before the character is sent out
// because the send of the character was blocked because
// of hardware flow control (or break).
//
if (!Extension->SendXonChar && !Extension->SendXoffChar
&& Extension->HoldingEmpty) {
/*
DISABLE_ALL_INTERRUPTS(Extension->Controller);
ENABLE_ALL_INTERRUPTS(Extension->Controller);
*/
}
if (SendXon) {
Extension->SendXonChar = TRUE;
Extension->SendXoffChar = FALSE;
} else {
Extension->SendXonChar = FALSE;
Extension->SendXoffChar = TRUE;
}
}
ULONG
SerialHandleModemUpdate(
IN PDEVICE_EXTENSION Extension,
IN BOOLEAN DoingTX
)
/*++
Routine Description:
This routine will be to check on the modem status, and
handle any appropriate event notification as well as
any flow control appropriate to modem status lines.
NOTE: This routine assumes that it is called at interrupt
level.
Arguments:
Extension - A pointer to the serial device extension.
DoingTX - This boolean is used to indicate that this call
came from the transmit processing code. If this
is true then there is no need to cause a new interrupt
since the code will be trying to send the next
character as soon as this call finishes.
Return Value:
This returns the old value of the modem status register
(extended into a ULONG).
--*/
{
//
// We keep this local so that after we are done
// examining the modem status and we've updated
// the transmission holding value, we know whether
// we've changed from needing to hold up transmission
// to transmission being able to proceed.
//
ULONG OldTXHolding = Extension->TXHolding;
//
// Holds the value in the mode status register.
//
UCHAR ModemStatus;
/*
ModemStatus =
READ_MODEM_STATUS(Extension->Controller);
*/
ModemStatus = Extension->intdata[3];
//
// If we are placeing the modem status into the data stream
// on every change, we should do it now.
//
if (Extension->EscapeChar) {
if (ModemStatus & (SERIAL_MSR_DCTS |
SERIAL_MSR_DDSR |
SERIAL_MSR_TERI |
SERIAL_MSR_DDCD)) {
SerialPutChar(
Extension,
Extension->EscapeChar
);
SerialPutChar(
Extension,
SERIAL_LSRMST_MST
);
SerialPutChar(
Extension,
ModemStatus
);
}
}
//
// Take care of input flow control based on sensitivity
// to the DSR. This is done so that the application won't
// see spurious data generated by odd devices.
//
// Basically, if we are doing dsr sensitivity then the
// driver should only accept data when the dsr bit is
// set.
//
/*henry
if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
if (ModemStatus & SERIAL_MSR_DSR) {
//
// The line is high. Simply make sure that
// RXHolding does't have the DSR bit.
//
Extension->RXHolding &= ~SERIAL_RX_DSR;
} else {
Extension->RXHolding |= SERIAL_RX_DSR;
}
} else {
//
// We don't have sensitivity due to DSR. Make sure we
// arn't holding. (We might have been, but the app just
// asked that we don't hold for this reason any more.)
//
Extension->RXHolding &= ~SERIAL_RX_DSR;
}
*/
//
// Check to see if we have a wait
// pending on the modem status events. If we
// do then we schedule a dpc to satisfy
// that wait.
//
if (Extension->IsrWaitMask) {
if ((Extension->IsrWaitMask & SERIAL_EV_CTS) &&
(ModemStatus & SERIAL_MSR_DCTS)) {
Extension->HistoryMask |= SERIAL_EV_CTS;
}
if ((Extension->IsrWaitMask & SERIAL_EV_DSR) &&
(ModemStatus & SERIAL_MSR_DDSR)) {
Extension->HistoryMask |= SERIAL_EV_DSR;
}
if ((Extension->IsrWaitMask & SERIAL_EV_RING) &&
(ModemStatus & SERIAL_MSR_TERI)) {
Extension->HistoryMask |= SERIAL_EV_RING;
}
if ((Extension->IsrWaitMask & SERIAL_EV_RLSD) &&
(ModemStatus & SERIAL_MSR_DDCD)) {
Extension->HistoryMask |= SERIAL_EV_RLSD;
}
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
);
}
}
#if 0
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -