⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.h

📁 这个是串口驱动程序开发包
💻 H
📖 第 1 页 / 共 2 页
字号:
// 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 + -