📄 serial.h
字号:
// line is held to logic 0 for more than the amount of time it takes
// to send one serial data unit. This bit is cleared whenever the
// this register is read.
#define SERIAL_LSR_BI 0x10
// This is the transmit holding register empty indicator. It is set
// to indicate that the hardware is ready to accept another character
// for transmission. This bit is cleared whenever a character is
// written to the transmit holding register.
#define SERIAL_LSR_THRE 0x20
// This bit is the transmitter empty indicator. It is set whenever the
// transmit holding buffer is empty and the transmit shift register
// (a non-software accessable register that is used to actually put
// the data out on the wire) is empty. Basically this means that all
// data has been sent. It is cleared whenever the transmit holding or
// the shift registers contain data.
#define SERIAL_LSR_TEMT 0x40
// This bit indicates that there is at least one error in the fifo.
// The bit will not be turned off until there are no more errors
// in the fifo.
#define SERIAL_LSR_FIFOERR 0x80
// These masks are used to access the modem status register.
// Whenever one of the first four bits in the modem status
// register changes state a modem status interrupt is generated.
// This bit is the delta clear to send. It is used to indicate
// that the clear to send bit (in this register) has *changed*
// since this register was last read by the CPU.
#define SERIAL_MSR_DCTS 0x01
// This bit is the delta data set ready. It is used to indicate
// that the data set ready bit (in this register) has *changed*
// since this register was last read by the CPU.
#define SERIAL_MSR_DDSR 0x02
// This is the trailing edge ring indicator. It is used to indicate
// that the ring indicator input has changed from a low to high state.
#define SERIAL_MSR_TERI 0x04
// This bit is the delta data carrier detect. It is used to indicate
// that the data carrier bit (in this register) has *changed*
// since this register was last read by the CPU.
#define SERIAL_MSR_DDCD 0x08
// This bit contains the (complemented) state of the clear to send
// (CTS) line.
#define SERIAL_MSR_CTS 0x10
// This bit contains the (complemented) state of the data set ready
// (DSR) line.
#define SERIAL_MSR_DSR 0x20
// This bit contains the (complemented) state of the ring indicator
// (RI) line.
#define SERIAL_MSR_RI 0x40
// This bit contains the (complemented) state of the data carrier detect
// (DCD) line.
#define SERIAL_MSR_DCD 0x80
// This should be more than enough space to hold then
// numeric suffix of the device name.
#define DEVICE_NAME_DELTA 20
// Up to 16 Ports Per card. However for sixteen
// port cards the interrupt status register must me
// the indexing kind rather then the bitmask kind.
#define SERIAL_MAX_PORTS_INDEXED (16)
#define SERIAL_MAX_PORTS_NONINDEXED (8)
// Default xon/xoff characters.
#define SERIAL_DEF_XON 0x11
#define SERIAL_DEF_XOFF 0x13
// Reasons that reception may be held up.
#define SERIAL_RX_DTR ((ULONG)0x01)
#define SERIAL_RX_XOFF ((ULONG)0x02)
#define SERIAL_RX_RTS ((ULONG)0x04)
#define SERIAL_RX_DSR ((ULONG)0x08)
// Reasons that transmission may be held up.
#define SERIAL_TX_CTS ((ULONG)0x01)
#define SERIAL_TX_DSR ((ULONG)0x02)
#define SERIAL_TX_DCD ((ULONG)0x04)
#define SERIAL_TX_XOFF ((ULONG)0x08)
#define SERIAL_TX_BREAK ((ULONG)0x10)
// These values are used by the routines that can be used
// to complete a read (other than interval timeout) to indicate
// to the interval timeout that it should complete.
#define SERIAL_COMPLETE_READ_CANCEL ((LONG)-1)
#define SERIAL_COMPLETE_READ_TOTAL ((LONG)-2)
#define SERIAL_COMPLETE_READ_COMPLETE ((LONG)-3)
// When dealing with a multi-port device (that is possibly
// daisy chained with other multi-port device), the interrupt
// service routine will actually be a routine that determines
// which port on which board is actually causing the interrupt.
//
// The following structure is used so that only one device
// will actually need to connect to the interrupt.
// The following structure which is passed to the interrupt
// service routine contains the addresses of all of the
// interrupt status registers (there will be multiple
// status registers when multi-port cards are chained). It
// will contain the addresses of all the devices whose
// devices are being serviced by this interrupt.
typedef struct _SERIAL_MULTIPORT_DISPATCH {
PUCHAR InterruptStatus;
PKdSerialDevice pdvDevices[SERIAL_MAX_PORTS_INDEXED];
ULONG MaskInverted;
UCHAR UsablePortMask;
} SERIAL_MULTIPORT_DISPATCH,*PSERIAL_MULTIPORT_DISPATCH;
// Sets the divisor latch register. The divisor latch register
// is used to control the baud rate of the 8250.
//
// As with all of these routines it is assumed that it is called
// at a safe point to access the hardware registers. In addition
// it also assumes that the data is correct.
//
// Arguments:
//
// pKdBaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// DesiredDivisor - The value to which the divisor latch register should
// be set.
#define WRITE_DIVISOR_LATCH(pKdBaseAddress,DesiredDivisor) \
{ \
UCHAR LineControl; \
LineControl = pKdBaseAddress->ReadByte(LINE_CONTROL_REGISTER); \
pKdBaseAddress->WriteByte(LINE_CONTROL_REGISTER, (UCHAR)(LineControl | SERIAL_LCR_DLAB)); \
pKdBaseAddress->WriteByte(DIVISOR_LATCH_LSB, (UCHAR)(DesiredDivisor & 0xff)); \
pKdBaseAddress->WriteByte(DIVISOR_LATCH_MSB, (UCHAR)((DesiredDivisor & 0xff00) >> 8)); \
pKdBaseAddress->WriteByte(LINE_CONTROL_REGISTER, LineControl); \
}
// Reads the divisor latch register. The divisor latch register
// is used to control the baud rate of the 8250.
//
// As with all of these routines it is assumed that it is called
// at a safe point to access the hardware registers. In addition
// it also assumes that the data is correct.
//
// Arguments:
//
// pKdBaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// DesiredDivisor - A pointer to the 2 byte word which will contain
// the value of the divisor.
#define READ_DIVISOR_LATCH(pKdBaseAddress,PDesiredDivisor) \
{ \
PSHORT PDivisor = (PSHORT)PDesiredDivisor; \
UCHAR LineControl; \
UCHAR Lsb; \
UCHAR Msb; \
LineControl = pKdBaseAddress->ReadByte(LINE_CONTROL_REGISTER); \
pKdBaseAddress->WriteByte(LINE_CONTROL_REGISTER, (UCHAR)(LineControl | SERIAL_LCR_DLAB));\
Lsb = pKdBaseAddress->ReadByte(DIVISOR_LATCH_LSB); \
Msb = pKdBaseAddress->ReadByte(DIVISOR_LATCH_MSB); \
*PDivisor = Lsb; \
*PDivisor = *PDivisor | (((USHORT)Msb) << 8); \
pKdBaseAddress->WriteByte(LINE_CONTROL_REGISTER, LineControl); \
}
// This macro disables all interrupts on the hardware.
//
// Arguments:
//
// pKdBaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
#define DISABLE_ALL_INTERRUPTS(pKdBaseAddress) \
(pKdBaseAddress)->WriteByte(INTERRUPT_ENABLE_REGISTER, 0);
// This macro enables all interrupts on the hardware.
//
// Arguments:
//
// pKdBaseAddress - A pointer to the address from which the hardware
// device registers are located.
#define ENABLE_ALL_INTERRUPTS(pKdBaseAddress) \
(pKdBaseAddress)->WriteByte(INTERRUPT_ENABLE_REGISTER, \
(UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \
SERIAL_IER_RLS | SERIAL_IER_MS));
class KdSerialDriver : public KdDriver
{
public:
KdSerialDriver(NTSTATUS &Status, PDRIVER_OBJECT pDriverObject, PUNICODE_STRING puniRegistryPath);
virtual ~KdSerialDriver() ;
VOID GetConfigInfo(
ULONG ForceFifoEnableDefault,
ULONG RxFIFODefault,
ULONG TxFIFODefault,
ULONG PermitShareDefault,
ULONG LogFifoDefault,
OUT KdConfigList *pConfigList
);
BOOLEAN PutInConfigList(
IN OUT KdConfigList *pConfigList,
IN PCONFIG_DATA New,
IN BOOLEAN FirmwareAddition
);
VOID InitializeRootInterrupt(IN PCONFIG_DATA ConfigData);
NTSTATUS InitializeRootMultiPort(IN PCONFIG_DATA ConfigData);
};
#endif //__SERIAL__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -