📄 serial.h
字号:
// Pending DPC count
//
ULONG DpcCount;
//
// Pending DPC event
//
KEVENT PendingDpcEvent;
//
// Should we expose external interfaces?
//
ULONG SkipNaming;
} SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION;
#define SERIAL_PNPACCEPT_OK 0x0L
#define SERIAL_PNPACCEPT_REMOVING 0x1L
#define SERIAL_PNPACCEPT_STOPPING 0x2L
#define SERIAL_PNPACCEPT_STOPPED 0x4L
#define SERIAL_PNPACCEPT_SURPRISE_REMOVING 0x8L
#define SERIAL_PNP_ADDED 0x0L
#define SERIAL_PNP_STARTED 0x1L
#define SERIAL_PNP_QSTOP 0x2L
#define SERIAL_PNP_STOPPING 0x3L
#define SERIAL_PNP_QREMOVE 0x4L
#define SERIAL_PNP_REMOVING 0x5L
#define SERIAL_PNP_RESTARTING 0x6L
#define SERIAL_FLAGS_CLEAR 0x0L
#define SERIAL_FLAGS_STARTED 0x1L
#define SERIAL_FLAGS_STOPPED 0x2L
#define SERIAL_FLAGS_BROKENHW 0x4L
//
// 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
// extension 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 extensions whose
// devices are being serviced by this interrupt.
//
typedef struct _SERIAL_MULTIPORT_DISPATCH {
PUCHAR InterruptStatus;
PSERIAL_DEVICE_EXTENSION Extensions[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:
//
// BaseAddress - 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(BaseAddress,DesiredDivisor) \
do \
{ \
PUCHAR Address = BaseAddress; \
SHORT Divisor = DesiredDivisor; \
UCHAR LineControl; \
LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
WRITE_PORT_UCHAR( \
Address+LINE_CONTROL_REGISTER, \
(UCHAR)(LineControl | SERIAL_LCR_DLAB) \
); \
WRITE_PORT_UCHAR( \
Address+DIVISOR_LATCH_LSB, \
(UCHAR)(Divisor & 0xff) \
); \
WRITE_PORT_UCHAR( \
Address+DIVISOR_LATCH_MSB, \
(UCHAR)((Divisor & 0xff00) >> 8) \
); \
WRITE_PORT_UCHAR( \
Address+LINE_CONTROL_REGISTER, \
LineControl \
); \
} while (0)
//
// 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:
//
// BaseAddress - 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(BaseAddress,PDesiredDivisor) \
do \
{ \
PUCHAR Address = BaseAddress; \
PSHORT PDivisor = PDesiredDivisor; \
UCHAR LineControl; \
UCHAR Lsb; \
UCHAR Msb; \
LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
WRITE_PORT_UCHAR( \
Address+LINE_CONTROL_REGISTER, \
(UCHAR)(LineControl | SERIAL_LCR_DLAB) \
); \
Lsb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_LSB); \
Msb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_MSB); \
*PDivisor = Lsb; \
*PDivisor = *PDivisor | (((USHORT)Msb) << 8); \
WRITE_PORT_UCHAR( \
Address+LINE_CONTROL_REGISTER, \
LineControl \
); \
} while (0)
//
// This macro reads the interrupt enable register.
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
#define READ_INTERRUPT_ENABLE(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+INTERRUPT_ENABLE_REGISTER))
//
// This macro writes the interrupt enable register.
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// Values - The values to write to the interrupt enable register.
//
#define WRITE_INTERRUPT_ENABLE(BaseAddress,Values) \
do \
{ \
WRITE_PORT_UCHAR( \
BaseAddress+INTERRUPT_ENABLE_REGISTER, \
Values \
); \
} while (0)
//
// This macro disables all interrupts on the hardware.
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define DISABLE_ALL_INTERRUPTS(BaseAddress) \
do \
{ \
WRITE_INTERRUPT_ENABLE(BaseAddress,0); \
} while (0)
//
// This macro enables all interrupts on the hardware.
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define ENABLE_ALL_INTERRUPTS(BaseAddress) \
do \
{ \
\
WRITE_INTERRUPT_ENABLE( \
(BaseAddress), \
(UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \
SERIAL_IER_RLS | SERIAL_IER_MS) \
); \
\
} while (0)
//
// This macro reads the interrupt identification register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// Note that this routine potententially quites a transmitter
// empty interrupt. This is because one way that the transmitter
// empty interrupt is cleared is to simply read the interrupt id
// register.
//
//
#define READ_INTERRUPT_ID_REG(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+INTERRUPT_IDENT_REGISTER))
//
// This macro reads the modem control register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define READ_MODEM_CONTROL(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+MODEM_CONTROL_REGISTER))
//
// This macro reads the modem status register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define READ_MODEM_STATUS(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+MODEM_STATUS_REGISTER))
//
// This macro reads a value out of the receive buffer
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define READ_RECEIVE_BUFFER(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+RECEIVE_BUFFER_REGISTER))
//
// This macro reads the line status register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define READ_LINE_STATUS(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+LINE_STATUS_REGISTER))
//
// This macro writes the line control register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define WRITE_LINE_CONTROL(BaseAddress,NewLineControl) \
do \
{ \
WRITE_PORT_UCHAR( \
(BaseAddress)+LINE_CONTROL_REGISTER, \
(NewLineControl) \
); \
} while (0)
//
// This macro reads the line control register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
//
#define READ_LINE_CONTROL(BaseAddress) \
(READ_PORT_UCHAR((BaseAddress)+LINE_CONTROL_REGISTER))
//
// This macro writes to the transmit register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// TransmitChar - The character to send down the wire.
//
//
#define WRITE_TRANSMIT_HOLDING(BaseAddress,TransmitChar) \
do \
{ \
WRITE_PORT_UCHAR( \
(BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
(TransmitChar) \
); \
} while (0)
//
// This macro writes to the transmit FIFO register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// TransmitChars - Pointer to the characters to send down the wire.
//
// TxN - number of charactes to send.
//
//
#define WRITE_TRANSMIT_FIFO_HOLDING(BaseAddress,TransmitChars,TxN) \
do \
{ \
WRITE_PORT_BUFFER_UCHAR( \
(BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
(TransmitChars), \
(TxN) \
); \
} while (0)
//
// This macro writes to the control register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// ControlValue - The value to set the fifo control register too.
//
//
#define WRITE_FIFO_CONTROL(BaseAddress,ControlValue) \
do \
{ \
WRITE_PORT_UCHAR( \
(BaseAddress)+FIFO_CONTROL_REGISTER, \
(ControlValue) \
); \
} while (0)
//
// This macro writes to the modem control register
//
// Arguments:
//
// BaseAddress - A pointer to the address from which the hardware
// device registers are located.
//
// ModemControl - The control bits to send to the modem control.
//
//
#define WRITE_MODEM_CONTROL(BaseAddress,ModemControl) \
do \
{ \
WRITE_PORT_UCHAR( \
(BaseAddress)+MODEM_CONTROL_REGISTER, \
(ModemControl) \
); \
} while (0)
//
// We use this to query into the registry as to whether we
// should break at driver entry.
//
extern SERIAL_FIRMWARE_DATA driverDefaults;
//
// This is exported from the kernel. It is used to point
// to the address that the kernel debugger is using.
//
extern PUCHAR *KdComPortInUse;
typedef enum _SERIAL_MEM_COMPARES {
AddressesAreEqual,
AddressesOverlap,
AddressesAreDisjoint
} SERIAL_MEM_COMPARES,*PSERIAL_MEM_COMPARES;
typedef struct _SERIAL_LIST_DATA {
PLIST_ENTRY destList;
PLIST_ENTRY newElement;
} SERIAL_LIST_DATA, *PSERIAL_LIST_DATA;
typedef struct _SERIAL_GLOBALS {
LIST_ENTRY AllDevObjs;
PVOID PAGESER_Handle;
UNICODE_STRING RegistryPath;
#if DBG
ULONG PAGESER_Count;
#endif // DBG
} SERIAL_GLOBALS, *PSERIAL_GLOBALS;
extern SERIAL_GLOBALS SerialGlobals;
typedef struct _SERIAL_USER_DATA {
PHYSICAL_ADDRESS UserPort;
PHYSICAL_ADDRESS UserInterruptStat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -