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

📄 serial.h

📁 串口Windows驱动
💻 H
📖 第 1 页 / 共 5 页
字号:
#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;
    KAFFINITY           Affinity;
    ULONG               Indexed;
    ULONG               TL16C550CAFC;
    } 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;
} 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_POWER_COMPLETION_CONTEXT {
    PDEVICE_OBJECT  PDevObj;
    PIRP            PSIrp;
} SERIAL_POWER_COMPLETION_CONTEXT, *PSERIAL_POWER_COMPLETION_CONTEXT;


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;

    //
    // Points to the irp that is being used to send an immediate
    // character.
    //
    PIRP CurrentImmediateIrp;

    //
    // Points to the irp that is being used to count the number

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -