📄 modmflow.c
字号:
//
// However if we are already holding we don't want
// to turn it back on unless we exceed the Xon
// limit.
//
if (Extension->RXHolding & SERIAL_RX_RTS) {
//
// We can assume that its RTS line is already low.
//
if (Extension->CharsInInterruptBuffer >
(ULONG)New.XonLimit) {
SerialDump(
SERFLOW,
("SERIAL: Removing rts block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_RTS;
SerialSetRTS(Extension);
}
} else {
SerialSetRTS(Extension);
}
} else {
SerialDump(
SERFLOW,
("SERIAL: Setting rts block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding |= SERIAL_RX_RTS;
SerialClrRTS(Extension);
}
} else if ((New.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_RTS_CONTROL) {
//
// Note that if we aren't currently doing rts flow control then
// we MIGHT have been. So even if we aren't currently doing
// RTS flow control, we should still check if RX is holding
// because of RTS. If it is, then we should clear the holding
// of this bit.
//
if (Extension->RXHolding & SERIAL_RX_RTS) {
SerialDump(
SERFLOW,
("SERIAL: Clearing rts block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_RTS;
}
SerialSetRTS(Extension);
} else if ((New.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We first need to check whether reception is being held
// up because of previous RTS flow control. If it is then
// we should clear that reason in the RXHolding mask.
//
if (Extension->RXHolding & SERIAL_RX_RTS) {
SerialDump(
SERFLOW,
("SERIAL: TOGGLE Clearing rts block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_RTS;
}
//
// We have to place the rts value into the Extension
// now so that the code that tests whether the
// rts line should be lowered will find that we
// are "still" doing transmit toggling. The code
// for lowering can be invoked later by a timer so
// it has to test whether it still needs to do its
// work.
//
Extension->HandFlow.FlowReplace &= ~SERIAL_RTS_MASK;
Extension->HandFlow.FlowReplace |= SERIAL_TRANSMIT_TOGGLE;
//
// The order of the tests is very important below.
//
// If there is a break then we should turn on the RTS.
//
// If there isn't a break but there are characters in
// the hardware, then turn on the RTS.
//
// If there are writes pending that aren't being held
// up, then turn on the RTS.
//
/*henry
if ((Extension->TXHolding & SERIAL_TX_BREAK) ||
((SerialProcessLSR(Extension) & (SERIAL_LSR_THRE |
SERIAL_LSR_TEMT)) !=
(SERIAL_LSR_THRE |
SERIAL_LSR_TEMT)) ||
(Extension->CurrentWriteIrp || Extension->TransmitImmediate ||
(!IsListEmpty(&Extension->WriteQueue)) &&
(!Extension->TXHolding))) {
SerialSetRTS(Extension);
} else {
//
// This routine will check to see if it is time
// to lower the RTS because of transmit toggle
// being on. If it is ok to lower it, it will,
// if it isn't ok, it will schedule things so
// that it will get lowered later.
//
Extension->CountOfTryingToLowerRTS++;
SerialPerhapsLowerRTS(Extension);
}
*/
} else {
//
// The end result here will be that RTS is cleared.
//
// We first need to check whether reception is being held
// up because of previous RTS flow control. If it is then
// we should clear that reason in the RXHolding mask.
//
if (Extension->RXHolding & SERIAL_RX_RTS) {
SerialDump(
SERFLOW,
("SERIAL: Clearing rts block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_RTS;
}
SerialClrRTS(Extension);
}
}
//
// We now take care of automatic receive flow control.
// We only do work if things have changed.
//
if ((!Extension->DeviceIsOpened) ||
((Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) !=
(New.FlowReplace & SERIAL_AUTO_RECEIVE))) {
if (New.FlowReplace & SERIAL_AUTO_RECEIVE) {
//
// We wouldn't be here if it had been on before.
//
// We should check to see whether we exceed the turn
// off limits.
//
// Note that since we are following the OS/2 flow
// control rules we will never send an xon if
// when enabling xon/xoff flow control we discover that
// we could receive characters but we are held up do
// to a previous Xoff.
//
if ((Extension->BufferSize - New.XoffLimit) <=
Extension->CharsInInterruptBuffer) {
//
// Cause the Xoff to be sent.
//
Extension->RXHolding |= SERIAL_RX_XOFF;
SerialProdXonXoff(
Extension,
FALSE
);
}
} else {
//
// The app has disabled automatic receive flow control.
//
// If transmission was being held up because of
// an automatic receive Xoff, then we should
// cause an Xon to be sent.
//
if (Extension->RXHolding & SERIAL_RX_XOFF) {
Extension->RXHolding &= ~SERIAL_RX_XOFF;
//
// Cause the Xon to be sent.
//
SerialProdXonXoff(
Extension,
TRUE
);
}
}
}
//
// We now take care of automatic transmit flow control.
// We only do work if things have changed.
//
if ((!Extension->DeviceIsOpened) ||
((Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) !=
(New.FlowReplace & SERIAL_AUTO_TRANSMIT))) {
if (New.FlowReplace & SERIAL_AUTO_TRANSMIT) {
//
// We wouldn't be here if it had been on before.
//
// BUG BUG ??? There is some belief that if autotransmit
// was just enabled, I should go look in what we
// already received, and if we find the xoff character
// then we should stop transmitting. I think this
// is an application bug. For now we just care about
// what we see in the future.
//
;
} else {
//
// The app has disabled automatic transmit flow control.
//
// If transmission was being held up because of
// an automatic transmit Xoff, then we should
// cause an Xon to be sent.
//
if (Extension->TXHolding & SERIAL_TX_XOFF) {
Extension->TXHolding &= ~SERIAL_TX_XOFF;
//
// Cause the Xon to be sent.
//
SerialProdXonXoff(
Extension,
TRUE
);
}
}
}
//
// At this point we can simply make sure that entire
// handflow structure in the extension is updated.
//
Extension->HandFlow = New;
return FALSE;
}
BOOLEAN
SerialSetHandFlow(
IN PVOID Context
)
/*++
Routine Description:
This routine is used to set the handshake and control
flow in the device extension.
Arguments:
Context - Pointer to a structure that contains a pointer to
the device extension and a pointer to a handflow
structure..
Return Value:
This routine always returns FALSE.
--*/
{
PSERIAL_IOCTL_SYNC S = Context;
PDEVICE_EXTENSION Extension = S->Extension;
PSERIAL_HANDFLOW HandFlow = S->Data;
SerialSetupNewHandFlow(
Extension,
HandFlow
);
SerialHandleModemUpdate(
Extension,
FALSE
);
return FALSE;
}
BOOLEAN
SerialTurnOnBreak(
IN PVOID Context
)
/*++
Routine Description:
This routine will turn on break in the hardware and
record the fact the break is on, in the extension variable
that holds reasons that transmission is stopped.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
UCHAR OldLineControl;
if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialSetRTS(Extension);
}
/*henry
OldLineControl = READ_LINE_CONTROL(Extension->Controller);
OldLineControl |= SERIAL_LCR_BREAK;
WRITE_LINE_CONTROL(
Extension->Controller,
OldLineControl
);
*/
Extension->TXHolding |= SERIAL_TX_BREAK;
return FALSE;
}
BOOLEAN
SerialTurnOffBreak(
IN PVOID Context
)
/*++
Routine Description:
This routine will turn off break in the hardware and
record the fact the break is off, in the extension variable
that holds reasons that transmission is stopped.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
UCHAR OldLineControl;
if (Extension->TXHolding & SERIAL_TX_BREAK) {
//
// 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.
/*henry
OldLineControl = READ_LINE_CONTROL(Extension->Controller);
OldLineControl &= ~SERIAL_LCR_BREAK;
WRITE_LINE_CONTROL(
Extension->Controller,
OldLineControl
);
*/
Extension->TXHolding &= ~SERIAL_TX_BREAK;
if (!Extension->TXHolding &&
(Extension->TransmitImmediate ||
Extension->WriteLength) &&
Extension->HoldingEmpty) {
/*henry
DISABLE_ALL_INTERRUPTS(Extension->Controller);
ENABLE_ALL_INTERRUPTS(Extension->Controller);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -