📄 modmflow.c
字号:
/*++
Copyright (c) 1991, 1992, 1993 Microsoft Corporation
Copyright (c) 2000 Maverick Research Inc
Module Name:
modmflow.c
Abstract:
This module contains *MOST* of the code used to manipulate
the modem control and status registers. The vast majority
of the remainder of flow control is concentrated in the
Interrupt service routine. A very small amount resides
in the read code that pull characters out of the interrupt
buffer.
Author:
Anthony V. Ercolano 26-Sep-1991
Henry Tan 11-Aug-2000
Environment:
Kernel mode
Revision History :
--*/
//#include "precomp.h"
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usbcom.h"
BOOLEAN
SerialDecrementRTSCounter(
IN PVOID Context
);
/*
#ifdef ALLOC_PRAGMA
#if 0
#pragma alloc_text(PAGESER,SerialHandleReducedIntBuffer)
#pragma alloc_text(PAGESER,SerialProdXonXoff)
#pragma alloc_text(PAGESER,SerialHandleModemUpdate)
#pragma alloc_text(PAGESER,SerialPerhapsLowerRTS)
#pragma alloc_text(PAGESER,SerialStartTimerLowerRTS)
#pragma alloc_text(PAGESER,SerialInvokePerhapsLowerRTS)
#pragma alloc_text(PAGESER,SerialSetDTR)
//#pragma alloc_text(PAGESER,SerialClrDTR)
#pragma alloc_text(PAGESER,SerialSetRTS)
//#pragma alloc_text(PAGESER,SerialClrRTS)
//#pragma alloc_text(PAGESER,SerialSetupNewHandFlow)
#pragma alloc_text(PAGESER,SerialSetHandFlow)
#pragma alloc_text(PAGESER,SerialTurnOnBreak)
#pragma alloc_text(PAGESER,SerialTurnOffBreak)
#pragma alloc_text(PAGESER,SerialPretendXoff)
#pragma alloc_text(PAGESER,SerialPretendXon)
#pragma alloc_text(PAGESER,SerialDecrementRTSCounter)
#endif
#endif
*/
BOOLEAN
SerialSetDTR(
IN PVOID Context
)
/*++
Routine Description:
This routine which is only called at interrupt level is used
to set the DTR in the modem control register.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
/* UCHAR ModemControl;
ModemControl = READ_MODEM_CONTROL(Extension->Controller);
ModemControl |= SERIAL_MCR_DTR;
SerialDump(
SERFLOW,
("SERIAL: Setting DTR for %x\n",
Extension->Controller)
);
WRITE_MODEM_CONTROL(
Extension->Controller,
ModemControl
);
*/
UsbCom_SendVendor(Extension->DeviceObject, VendorSetDTR, 0x01);
return FALSE;
}
BOOLEAN
SerialClrDTR(
IN PVOID Context
)
/*++
Routine Description:
This routine which is only called at interrupt level is used
to clear the DTR in the modem control register.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
/* UCHAR ModemControl;
ModemControl = READ_MODEM_CONTROL(Extension->Controller);
ModemControl &= ~SERIAL_MCR_DTR;
SerialDump(
SERFLOW,
("SERIAL: Clearing DTR for %x\n",
Extension->Controller)
);
WRITE_MODEM_CONTROL(
Extension->Controller,
ModemControl
);
*/
UsbCom_SendVendor(Extension->DeviceObject, VendorSetDTR, 0x00);
return FALSE;
}
BOOLEAN
SerialSetRTS(
IN PVOID Context
)
/*++
Routine Description:
This routine which is only called at interrupt level is used
to set the RTS in the modem control register.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
/* UCHAR ModemControl;
ModemControl = READ_MODEM_CONTROL(Extension->Controller);
ModemControl |= SERIAL_MCR_RTS;
SerialDump(
SERFLOW,
("SERIAL: Setting Rts for %x\n",
Extension->Controller)
);
WRITE_MODEM_CONTROL(
Extension->Controller,
ModemControl
);
*/
UsbCom_SendVendor(Extension->DeviceObject, VendorSetRTS, 0x01);
return FALSE;
}
BOOLEAN
SerialClrRTS(
IN PVOID Context
)
/*++
Routine Description:
This routine which is only called at interrupt level is used
to clear the RTS in the modem control register.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
/* UCHAR ModemControl;
ModemControl = READ_MODEM_CONTROL(Extension->Controller);
ModemControl &= ~SERIAL_MCR_RTS;
SerialDump(
SERFLOW,
("SERIAL: Clearing Rts for %x\n",
Extension->Controller)
);
WRITE_MODEM_CONTROL(
Extension->Controller,
ModemControl
);
*/
UsbCom_SendVendor(Extension->DeviceObject, VendorSetRTS, 0x00);
return FALSE;
}
BOOLEAN
SerialSetupNewHandFlow(
IN PDEVICE_EXTENSION Extension,
IN PSERIAL_HANDFLOW NewHandFlow
)
/*++
Routine Description:
This routine adjusts the flow control based on new
control flow.
Arguments:
Extension - A pointer to the serial device extension.
NewHandFlow - A pointer to a serial handflow structure
that is to become the new setup for flow
control.
Return Value:
This routine always returns FALSE.
--*/
{
SERIAL_HANDFLOW New = *NewHandFlow;
//
// If the Extension->DeviceIsOpened is FALSE that means
// we are entering this routine in response to an open request.
// If that is so, then we always proceed with the work regardless
// of whether things have changed.
//
//
// First we take care of the DTR flow control. We only
// do work if something has changed.
//
if ((!Extension->DeviceIsOpened) ||
((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) !=
(New.ControlHandShake & SERIAL_DTR_MASK))) {
SerialDump(
SERFLOW,
("SERIAL: Processing DTR flow for %x\n",
Extension->Controller)
);
if (New.ControlHandShake & SERIAL_DTR_MASK) {
//
// Well we might want to set DTR.
//
// Before we do, we need to check whether we are doing
// dtr flow control. If we are then we need to check
// if then number of characters in the interrupt buffer
// exceeds the XoffLimit. If it does then we don't
// enable DTR AND we set the RXHolding to record that
// we are holding because of the dtr.
//
if ((New.ControlHandShake & SERIAL_DTR_MASK)
== SERIAL_DTR_HANDSHAKE) {
if ((Extension->BufferSize - New.XoffLimit) >
Extension->CharsInInterruptBuffer) {
//
// 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_DTR) {
//
// We can assume that its DTR line is already low.
//
if (Extension->CharsInInterruptBuffer >
(ULONG)New.XonLimit) {
SerialDump(
SERFLOW,
("SERIAL: Removing DTR block on reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_DTR;
SerialSetDTR(Extension);
}
} else {
SerialSetDTR(Extension);
}
} else {
SerialDump(
SERFLOW,
("SERIAL: Setting DTR block on reception for %x\n",
Extension->Controller)
);
Extension->RXHolding |= SERIAL_RX_DTR;
SerialClrDTR(Extension);
}
} else {
//
// Note that if we aren't currently doing dtr flow control then
// we MIGHT have been. So even if we aren't currently doing
// DTR flow control, we should still check if RX is holding
// because of DTR. If it is, then we should clear the holding
// of this bit.
//
if (Extension->RXHolding & SERIAL_RX_DTR) {
SerialDump(
SERFLOW,
("SERIAL: Removing dtr block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_DTR;
}
SerialSetDTR(Extension);
}
} else {
//
// The end result here will be that DTR is cleared.
//
// We first need to check whether reception is being held
// up because of previous DTR flow control. If it is then
// we should clear that reason in the RXHolding mask.
//
if (Extension->RXHolding & SERIAL_RX_DTR) {
SerialDump(
SERFLOW,
("SERIAL: removing dtr block of reception for %x\n",
Extension->Controller)
);
Extension->RXHolding &= ~SERIAL_RX_DTR;
}
SerialClrDTR(Extension);
}
}
//
// Time to take care of the RTS Flow control.
//
// First we only do work if something has changed.
//
if ((!Extension->DeviceIsOpened) ||
((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) !=
(New.FlowReplace & SERIAL_RTS_MASK))) {
SerialDump(
SERFLOW,
("SERIAL: Processing RTS flow\n",
Extension->Controller)
);
if ((New.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_RTS_HANDSHAKE) {
//
// Well we might want to set RTS.
//
// Before we do, we need to check whether we are doing
// rts flow control. If we are then we need to check
// if then number of characters in the interrupt buffer
// exceeds the XoffLimit. If it does then we don't
// enable RTS AND we set the RXHolding to record that
// we are holding because of the rts.
//
if ((Extension->BufferSize - New.XoffLimit) >
Extension->CharsInInterruptBuffer) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -