📄 serial.h
字号:
//
#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)
typedef struct _CONFIG_DATA {
PHYSICAL_ADDRESS Controller;
PHYSICAL_ADDRESS TrController;
PHYSICAL_ADDRESS InterruptStatus;
PHYSICAL_ADDRESS TrInterruptStatus;
ULONG SpanOfController;
ULONG SpanOfInterruptStatus;
ULONG PortIndex;
ULONG ClockRate;
ULONG BusNumber;
ULONG AddressSpace;
ULONG DisablePort;
ULONG ForceFifoEnable;
ULONG RxFIFO;
ULONG TxFIFO;
ULONG PermitShare;
ULONG PermitSystemWideShare;
ULONG LogFifo;
ULONG MaskInverted;
KINTERRUPT_MODE InterruptMode;
INTERFACE_TYPE InterfaceType;
ULONG OriginalVector;
ULONG OriginalIrql;
ULONG TrVector;
ULONG TrIrql;
ULONG Affinity;
ULONG Indexed;
BOOLEAN Jensen;
} CONFIG_DATA,*PCONFIG_DATA;
//
// Serial ISR switch structure
//
typedef struct _SERIAL_CISR_SW {
BOOLEAN (*IsrFunc)(PKINTERRUPT, PVOID);
PVOID Context;
LIST_ENTRY SharerList;
} SERIAL_CISR_SW, *PSERIAL_CISR_SW;
//
// This structure contains configuration data, much of which
// is read from the registry.
//
typedef struct _SERIAL_FIRMWARE_DATA {
PDRIVER_OBJECT DriverObject;
ULONG ControllersFound;
ULONG ForceFifoEnableDefault;
ULONG DebugLevel;
ULONG ShouldBreakOnEntry;
ULONG RxFIFODefault;
ULONG TxFIFODefault;
ULONG PermitShareDefault;
ULONG PermitSystemWideShare;
ULONG LogFifoDefault;
UNICODE_STRING Directory;
UNICODE_STRING NtNameSuffix;
UNICODE_STRING DirectorySymbolicName;
LIST_ENTRY ConfigList;
BOOLEAN JensenDetected;
} SERIAL_FIRMWARE_DATA,*PSERIAL_FIRMWARE_DATA;
//
// Default xon/xoff characters.
//
#define SERIAL_DEF_XON 0x11
#define SERIAL_DEF_XOFF 0x13
//
// Reasons that recption 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)
//
// These are default values that shouldn't appear in the registry
//
#define SERIAL_BAD_VALUE ((ULONG)-1)
typedef struct _SERIAL_DEVICE_STATE {
//
// TRUE if we need to set the state to open
// on a powerup
//
BOOLEAN Reopen;
//
// Hardware registers
//
UCHAR IER;
// FCR is known by other values
UCHAR LCR;
UCHAR MCR;
// LSR is never written
// MSR is never written
// SCR is either scratch or interrupt status
} SERIAL_DEVICE_STATE, *PSERIAL_DEVICE_STATE;
#if DBG
#define SerialLockPagableSectionByHandle(_secHandle) \
{ \
MmLockPagableSectionByHandle((_secHandle)); \
InterlockedIncrement(&SerialGlobals.PAGESER_Count); \
}
#define SerialUnlockPagableImageSection(_secHandle) \
{ \
InterlockedDecrement(&SerialGlobals.PAGESER_Count); \
MmUnlockPagableImageSection(_secHandle); \
}
#define SERIAL_LOCKED_PAGED_CODE() \
if ((KeGetCurrentIrql() > APC_LEVEL) \
&& (SerialGlobals.PAGESER_Count == 0)) { \
KdPrint(("SERIAL: Pageable code called at IRQL %d without lock \n", \
KeGetCurrentIrql())); \
ASSERT(FALSE); \
}
#else
#define SerialLockPagableSectionByHandle(_secHandle) \
{ \
MmLockPagableSectionByHandle((_secHandle)); \
}
#define SerialUnlockPagableImageSection(_secHandle) \
{ \
MmUnlockPagableImageSection(_secHandle); \
}
#define SERIAL_LOCKED_PAGED_CODE()
#endif // DBG
#define SerialRemoveQueueDpc(_dpc, _pExt) \
{ \
if (KeRemoveQueueDpc((_dpc))) { \
InterlockedDecrement(&(_pExt)->DpcCount); \
} \
}
typedef struct _SERIAL_DEVICE_EXTENSION {
//
// This holds the isr that should be called from our own
// dispatching isr for "cards" that are trying to share the
// same interrupt.
//
PKSERVICE_ROUTINE TopLevelOurIsr;
//
// This holds the context that should be used when we
// call the above service routine.
//
PVOID TopLevelOurIsrContext;
//
// This links together all of the different "cards" that are
// trying to share the same interrupt of a non-mca machine.
//
LIST_ENTRY TopLevelSharers;
//
// This circular doubly linked list links together all
// devices that are using the same interrupt object.
// NOTE: This does not mean that they are using the
// same interrupt "dispatching" routine.
//
LIST_ENTRY CommonInterruptObject;
//
// This is to link together ports on the same multiport card
//
LIST_ENTRY MultiportSiblings;
//
// This links together all devobjs that this driver owns.
// It is needed to search when starting a new device.
//
LIST_ENTRY AllDevObjs;
//
// For reporting resource usage, we keep around the physical
// address we got from the registry.
//
PHYSICAL_ADDRESS OriginalController;
//
// For reporting resource usage, we keep around the physical
// address we got from the registry.
//
PHYSICAL_ADDRESS OriginalInterruptStatus;
//
// This value is set by the read code to hold the time value
// used for read interval timing. We keep it in the extension
// so that the interval timer dpc routine determine if the
// interval time has passed for the IO.
//
LARGE_INTEGER IntervalTime;
//
// These two values hold the "constant" time that we should use
// to delay for the read interval time.
//
LARGE_INTEGER ShortIntervalAmount;
LARGE_INTEGER LongIntervalAmount;
//
// This holds the value that we use to determine if we should use
// the long interval delay or the short interval delay.
//
LARGE_INTEGER CutOverAmount;
//
// This holds the system time when we last time we had
// checked that we had actually read characters. Used
// for interval timing.
//
LARGE_INTEGER LastReadTime;
//
// We keep a pointer around to our device name for dumps
// and for creating "external" symbolic links to this
// device.
//
UNICODE_STRING DeviceName;
//
// This points to the object directory that we will place
// a symbolic link to our device name.
//
UNICODE_STRING ObjectDirectory;
//
// This points to the device name for this device
// sans device prefix.
//
UNICODE_STRING NtNameForPort;
//
// This points to the symbolic link name that will be
// linked to the actual nt device name.
//
UNICODE_STRING SymbolicLinkName;
//
// This points to the pure "COMx" name
//
UNICODE_STRING DosName;
//
// This points the the delta time that we should use to
// delay for interval timing.
//
PLARGE_INTEGER IntervalTimeToUse;
//
// Points to the device object that contains
// this device extension.
//
PDEVICE_OBJECT DeviceObject;
//
// After initialization of the driver is complete, this
// will either be NULL or point to the routine that the
// kernel will call when an interrupt occurs.
//
// If the pointer is null then this is part of a list
// of ports that are sharing an interrupt and this isn't
// the first port that we configured for this interrupt.
//
// If the pointer is non-null then this routine has some
// kind of structure that will "eventually" get us into
// the real serial isr with a pointer to this device extension.
//
// NOTE: On an MCA bus (except for multiport cards) this
// is always a pointer to the "real" serial isr.
PKSERVICE_ROUTINE OurIsr;
//
// This will generally point right to this device extension.
//
// However, when the port that this device extension is
// "managing" was the first port initialized on a chain
// of ports that were trying to share an interrupt, this
// will point to a structure that will enable dispatching
// to any port on the chain of sharers of this interrupt.
//
PVOID OurIsrContext;
//
// The base address for the set of device registers
// of the serial port.
//
PUCHAR Controller;
//
// The base address for interrupt status register.
// This is only defined in the root extension.
//
PUCHAR InterruptStatus;
//
// Points to the interrupt object for used by this device.
//
PKINTERRUPT Interrupt;
//
// This list head is used to contain the time ordered list
// of read requests. Access to this list is protected by
// the global cancel spinlock.
//
LIST_ENTRY ReadQueue;
//
// This list head is used to contain the time ordered list
// of write requests. Access to this list is protected by
// the global cancel spinlock.
//
LIST_ENTRY WriteQueue;
//
// This list head is used to contain the time ordered list
// of set and wait mask requests. Access to this list is protected by
// the global cancel spinlock.
//
LIST_ENTRY MaskQueue;
//
// Holds the serialized list of purge requests.
//
LIST_ENTRY PurgeQueue;
//
// This points to the irp that is currently being processed
// for the read queue. This field is initialized by the open to
// NULL.
//
// This value is only set at dispatch level. It may be
// read at interrupt level.
//
PIRP CurrentReadIrp;
//
// This points to the irp that is currently being processed
// for the write queue.
//
// This value is only set at dispatch level. It may be
// read at interrupt level.
//
PIRP CurrentWriteIrp;
//
// Points to the irp that is currently being processed to
// affect the wait mask operations.
//
PIRP CurrentMaskIrp;
//
// Points to the irp that is currently being processed to
// purge the read/write queues and buffers.
//
PIRP CurrentPurgeIrp;
//
// Points to the current irp that is waiting on a comm event.
//
PIRP CurrentWaitIrp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -