|
|
/*--------------------------------------------------------------------------
* * Copyright (C) Cyclades Corporation, 1997-2000. * All rights reserved. * * Cyclades-Z Port Driver * * This file: cyzport.h * * Description: Type definitions and data for the Cyclades-Z Port * Driver * * Notes: This code supports Windows 2000 and x86 processor. * * Complies with Cyclades SW Coding Standard rev 1.3. * *-------------------------------------------------------------------------- */
/*-------------------------------------------------------------------------
* * Change History * *-------------------------------------------------------------------------- * * *-------------------------------------------------------------------------- */
#define POOL_TAGGING 1
#ifdef POOL_TAGGING
#undef ExAllocatePool
#undef ExAllocatePoolWithQuota
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'PzyC')
#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'PzyC')
#endif
//
// The following definition is used to include/exclude changes made for power
// support in the driver. If non-zero the support is included. If zero the
// support is excluded.
//
#define POWER_SUPPORT 1
#define CYZDIAG1 (DPFLTR_INFO_LEVEL + 1)
#define CYZDIAG2 (DPFLTR_INFO_LEVEL + 2)
#define CYZDIAG3 (DPFLTR_INFO_LEVEL + 3)
#define CYZDIAG4 (DPFLTR_INFO_LEVEL + 4)
#define CYZDIAG5 (DPFLTR_INFO_LEVEL + 5)
#define CYZIRPPATH (DPFLTR_INFO_LEVEL + 6)
#define CYZINITCODE (DPFLTR_INFO_LEVEL + 7)
#define CYZTRACECALLS (DPFLTR_INFO_LEVEL + 8)
#define CYZPNPPOWER (DPFLTR_INFO_LEVEL + 9)
#define CYZFLOW (DPFLTR_INFO_LEVEL + 10)
#define CYZERRORS (DPFLTR_INFO_LEVEL + 11)
#define CYZDBGALL ((ULONG)0xFFFFFFFF)
#define CYZ_DBG_DEFAULT CYZDBGALL
//
// Some default driver values. We will check the registry for
// them first.
//
#define CYZ_UNINITIALIZED_DEFAULT 1234567
#define CYZ_PERMIT_SHARE_DEFAULT 0
//
// This define gives the default Object directory
// that we should use to insert the symbolic links
// between the NT device name and namespace used by
// that object directory.
#define DEFAULT_DIRECTORY L"DosDevices"
//
// For the above directory, the serial port will
// use the following name as the suffix of the serial
// ports for that directory. It will also append
// a number onto the end of the name. That number
// will start at 1.
#define DEFAULT_SERIAL_NAME L"COM"
//
//
// This define gives the default NT name for
// for serial ports detected by the firmware.
// This name will be appended to Device prefix
// with a number following it. The number is
// incremented each time encounter a serial
// port detected by the firmware. Note that
// on a system with multiple busses, this means
// that the first port on a bus is not necessarily
// \Device\Serial0.
//
#define DEFAULT_NT_SUFFIX L"Cyzport"
//#define CYZ_VENDOR_ID 0x120e
//#define CYZ_LO_DEV_ID 0x100
//#define CYZ_HI_DEV_ID 0x101
// Defines for OutputRS232
#define CYZ_LC_RTS 0x01
#define CYZ_LC_DTR 0x02
typedef struct _CONFIG_DATA { PHYSICAL_ADDRESS PhysicalRuntime; PHYSICAL_ADDRESS TranslatedRuntime; PHYSICAL_ADDRESS PhysicalBoardMemory; PHYSICAL_ADDRESS TranslatedBoardMemory; ULONG RuntimeLength; ULONG BoardMemoryLength; ULONG PortIndex; ULONG PPPaware; ULONG WriteComplete; ULONG BusNumber; ULONG RuntimeAddressSpace; ULONG BoardMemoryAddressSpace; ULONG RxFIFO; ULONG TxFIFO; INTERFACE_TYPE InterfaceType; #ifndef POLL
KINTERRUPT_MODE InterruptMode; ULONG OriginalVector; ULONG OriginalIrql; ULONG TrVector; ULONG TrIrql; KAFFINITY Affinity; #endif
} CONFIG_DATA,*PCONFIG_DATA;
//
// This structure contains configuration data, much of which
// is read from the registry.
//
typedef struct _CYZ_REGISTRY_DATA { PDRIVER_OBJECT DriverObject; ULONG ControllersFound; ULONG DebugLevel; ULONG ShouldBreakOnEntry; // ULONG RxFIFODefault;
// ULONG TxFIFODefault;
ULONG PermitShareDefault; ULONG PermitSystemWideShare; UNICODE_STRING Directory; UNICODE_STRING NtNameSuffix; UNICODE_STRING DirectorySymbolicName; LIST_ENTRY ConfigList; } CYZ_REGISTRY_DATA,*PCYZ_REGISTRY_DATA;
// Default xon/xoff characters.
#define CYZ_DEF_XON 0x11
#define CYZ_DEF_XOFF 0x13
// Reasons why reception may be held up.
#define CYZ_RX_DTR ((ULONG)0x01)
#define CYZ_RX_XOFF ((ULONG)0x02)
#define CYZ_RX_RTS ((ULONG)0x04)
#define CYZ_RX_DSR ((ULONG)0x08)
// Reasons why transmission may be held up.
#define CYZ_TX_CTS ((ULONG)0x01)
#define CYZ_TX_DSR ((ULONG)0x02)
#define CYZ_TX_DCD ((ULONG)0x04)
#define CYZ_TX_XOFF ((ULONG)0x08)
#define CYZ_TX_BREAK ((ULONG)0x10)
//Line status in RDSR Register
#define CYZ_LSR_OE 0x01 //Overrun Error
#define CYZ_LSR_FE 0x02 //Framing Error
#define CYZ_LSR_PE 0x04 //Parity Error
#define CYZ_LSR_BI 0x08 //Break Interrupt
#define CYZ_LSR_ERROR 0x0f //Overrun+Framing+Parity+Break
// These values are used by the routines that can be used
// to complete a read (other than interval timeout) to indicate
//
#define CYZ_COMPLETE_READ_CANCEL ((LONG)-1)
#define CYZ_COMPLETE_READ_TOTAL ((LONG)-2)
#define CYZ_COMPLETE_READ_COMPLETE ((LONG)-3)
typedef struct _CYZ_DEVICE_STATE { //
// TRUE if we need to set the state to open
// on a powerup
//
BOOLEAN Reopen;
ULONG op_mode; ULONG intr_enable; ULONG sw_flow; ULONG comm_baud; ULONG comm_parity; ULONG comm_data_l; ULONG hw_flow; ULONG rs_control;
#if 0
//
// 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
#endif
} CYZ_DEVICE_STATE, *PCYZ_DEVICE_STATE;
#if DBG
#define CyzLockPagableSectionByHandle(_secHandle) \
{ \ MmLockPagableSectionByHandle((_secHandle)); \ InterlockedIncrement(&CyzGlobals.PAGESER_Count); \ }
#define CyzUnlockPagableImageSection(_secHandle) \
{ \ InterlockedDecrement(&CyzGlobals.PAGESER_Count); \ MmUnlockPagableImageSection(_secHandle); \ }
#define CYZ_LOCKED_PAGED_CODE() \
if ((KeGetCurrentIrql() > APC_LEVEL) \ && (CyzGlobals.PAGESER_Count == 0)) { \ KdPrint(("CYZPORT: Pageable code called at IRQL %d without lock \n", \ KeGetCurrentIrql())); \ ASSERT(FALSE); \ }
#else
#define CyzLockPagableSectionByHandle(_secHandle) \
{ \ MmLockPagableSectionByHandle((_secHandle)); \ }
#define CyzUnlockPagableImageSection(_secHandle) \
{ \ MmUnlockPagableImageSection(_secHandle); \ }
#define CYZ_LOCKED_PAGED_CODE()
#endif // DBG
#define CyzRemoveQueueDpc(_dpc, _pExt) \
{ \ if (KeRemoveQueueDpc((_dpc))) { \ InterlockedDecrement(&(_pExt)->DpcCount); \ } \ }
typedef struct _CYZ_DEVICE_EXTENSION { // PKSERVICE_ROUTINE ptIsr;
// PVOID ptContext;
// struct _CYZ_DEVICE_EXTENSION *ptExtension[CYZ_MAX_PORTS];
// ULONG nchannel;
BOOLEAN LieRIDSR;
//
// 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 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 OriginalRuntimeMemory;
// For reporting resource usage, we keep around the physical
// address we got from the registry.
//
PHYSICAL_ADDRESS OriginalBoardMemory;
//
// 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.
#ifndef POLL
PKSERVICE_ROUTINE OurIsr; #endif
//
// 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;
struct RUNTIME_9060 *Runtime; // Virtual Address Pointer to the PLX Runtime memory
// PUCHAR BoardMemory; // Virtual Address Pointer to the Dual Port memory
struct BOARD_CTRL *BoardCtrl; struct CH_CTRL *ChCtrl; struct BUF_CTRL *BufCtrl; struct INT_QUEUE *PtZfIntQueue; PUCHAR TxBufaddr; PUCHAR RxBufaddr; ULONG TxBufsize; ULONG RxBufsize;
//POLL // The base address for interrupt status register.
//POLL // This is only defined in the root extension.
//POLL //
//POLL PUCHAR InterruptStatus;
#ifndef POLL
//
// Points to the interrupt object for used by this device.
//
PKINTERRUPT Interrupt; #endif
//
// 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
// of characters received after an xoff (as currently defined
// by the IOCTL_CYZ_XOFF_COUNTER ioctl) is sent.
//
PIRP CurrentXoffIrp;
//
// Holds the number of bytes remaining in the current write
// irp.
//
// This location is only accessed while at interrupt level.
//
ULONG WriteLength;
//
// Holds a pointer to the current character to be sent in
// the current write.
//
// This location is only accessed while at interrupt level.
//
PUCHAR WriteCurrentChar;
//
// This is a buffer for the read processing.
//
// The buffer works as a ring. When the character is read from
// the device it will be place at the end of the ring.
//
// Characters are only placed in this buffer at interrupt level
// although character may be read at any level. The pointers
// that manage this buffer may not be updated except at interrupt
// level.
//
PUCHAR InterruptReadBuffer;
//
// This is a pointer to the first character of the buffer into
// which the interrupt service routine is copying characters.
//
PUCHAR ReadBufferBase;
//
// This is a count of the number of characters in the interrupt
// buffer. This value is set and read at interrupt level. Note
// that this value is only *incremented* at interrupt level so
// it is safe to read it at any level. When characters are
// copied out of the read buffer, this count is decremented by
// a routine that synchronizes with the ISR.
//
ULONG CharsInInterruptBuffer;
//
// Points to the first available position for a newly received
// character. This variable is only accessed at interrupt level and
// buffer initialization code.
//
PUCHAR CurrentCharSlot;
//
// This variable is used to contain the last available position
// in the read buffer. It is updated at open and at interrupt
// level when switching between the users buffer and the interrupt
// buffer.
//
PUCHAR LastCharSlot;
//
// This marks the first character that is available to satisfy
// a read request. Note that while this always points to valid
// memory, it may not point to a character that can be sent to
// the user. This can occur when the buffer is empty.
//
PUCHAR FirstReadableChar;
//
// Pointer to the lock variable returned for this extension when
// locking down the driver
//
PVOID LockPtr; BOOLEAN LockPtrFlag;
//
// This variable holds the size of whatever buffer we are currently
// using.
//
ULONG BufferSize;
//
// This variable holds .8 of BufferSize. We don't want to recalculate
// this real often - It's needed when so that an application can be
// "notified" that the buffer is getting full.
//
ULONG BufferSizePt8;
//
// This value holds the number of characters desired for a
// particular read. It is initially set by read length in the
// IRP. It is decremented each time more characters are placed
// into the "users" buffer buy the code that reads characters
// out of the typeahead buffer into the users buffer. If the
// typeahead buffer is exhausted by the read, and the reads buffer
// is given to the isr to fill, this value is becomes meaningless.
//
ULONG NumberNeededForRead;
//
// This mask will hold the bitmask sent down via the set mask
// ioctl. It is used by the interrupt service routine to determine
// if the occurence of "events" (in the serial drivers understanding
// of the concept of an event) should be noted.
//
ULONG IsrWaitMask;
//
// This mask will always be a subset of the IsrWaitMask. While
// at device level, if an event occurs that is "marked" as interesting
// in the IsrWaitMask, the driver will turn on that bit in this
// history mask. The driver will then look to see if there is a
// request waiting for an event to occur. If there is one, it
// will copy the value of the history mask into the wait irp, zero
// the history mask, and complete the wait irp. If there is no
// waiting request, the driver will be satisfied with just recording
// that the event occured. If a wait request should be queued,
// the driver will look to see if the history mask is non-zero. If
// it is non-zero, the driver will copy the history mask into the
// irp, zero the history mask, and then complete the irp.
//
ULONG HistoryMask;
//
// This is a pointer to the where the history mask should be
// placed when completing a wait. It is only accessed at
// device level.
//
// We have a pointer here to assist us to synchronize completing a wait.
// If this is non-zero, then we have wait outstanding, and the isr still
// knows about it. We make this pointer null so that the isr won't
// attempt to complete the wait.
//
// We still keep a pointer around to the wait irp, since the actual
// pointer to the wait irp will be used for the "common" irp completion
// path.
//
ULONG *IrpMaskLocation;
//
// This mask holds all of the reason that transmission
// is not proceeding. Normal transmission can not occur
// if this is non-zero.
//
// This is only written from interrupt level.
// This could be (but is not) read at any level.
//
ULONG TXHolding;
//
// This mask holds all of the reason that reception
// is not proceeding. Normal reception can not occur
// if this is non-zero.
//
// This is only written from interrupt level.
// This could be (but is not) read at any level.
//
ULONG RXHolding;
//
// This holds the reasons that the driver thinks it is in
// an error state.
//
// This is only written from interrupt level.
// This could be (but is not) read at any level.
//
ULONG ErrorWord;
//
// This keeps a total of the number of characters that
// are in all of the "write" irps that the driver knows
// about. It is only accessed with the cancel spinlock
// held.
//
ULONG TotalCharsQueued;
//
// This holds a count of the number of characters read
// the last time the interval timer dpc fired. It
// is a long (rather than a ulong) since the other read
// completion routines use negative values to indicate
// to the interval timer that it should complete the read
// if the interval timer DPC was lurking in some DPC queue when
// some other way to complete occurs.
//
LONG CountOnLastRead;
//
// This is a count of the number of characters read by the
// isr routine. It is *ONLY* written at isr level. We can
// read it at dispatch level.
//
ULONG ReadByIsr;
//
// This holds the current baud rate for the device.
//
ULONG CurrentBaud;
//
// This is the number of characters read since the XoffCounter
// was started. This variable is only accessed at device level.
// If it is greater than zero, it implies that there is an
// XoffCounter ioctl in the queue.
//
LONG CountSinceXoff;
//
// This ulong is incremented each time something trys to start
// the execution path that tries to lower the RTS line when
// doing transmit toggling. If it "bumps" into another path
// (indicated by a false return value from queueing a dpc
// and a TRUE return value tring to start a timer) it will
// decrement the count. These increments and decrements
// are all done at device level. Note that in the case
// of a bump while trying to start the timer, we have to
// go up to device level to do the decrement.
//
ULONG CountOfTryingToLowerRTS;
//
// This ULONG is used to keep track of the "named" (in ntddser.h)
// baud rates that this particular device supports.
//
ULONG SupportedBauds;
//
// This value holds the span (in units of bytes) of the register
// set controlling this port. This is constant over the life
// of the port.
//
ULONG RuntimeLength;
//
// This value holds the span (in units of bytes) of the interrupt
// status register associated with this port. This is constant
// over the life of the port.
//
ULONG BoardMemoryLength;
//
// The number of characters to push out if a fifo is present.
//
ULONG TxFifoAmount;
//
// Set to indicate that it is ok to share interrupts within the device.
//
ULONG PermitShare;
//
// Holds the timeout controls for the device. This value
// is set by the Ioctl processing.
//
// It should only be accessed under protection of the control
// lock since more than one request can be in the control dispatch
// routine at one time.
//
SERIAL_TIMEOUTS Timeouts;
//
// This holds the various characters that are used
// for replacement on errors and also for flow control.
//
// They are only set at interrupt level.
//
SERIAL_CHARS SpecialChars;
//
// This structure holds the handshake and control flow
// settings for the serial driver.
//
// It is only set at interrupt level. It can be
// be read at any level with the control lock held.
//
SERIAL_HANDFLOW HandFlow;
//
// Holds performance statistics that applications can query.
// Reset on each open. Only set at device level.
//
SERIALPERF_STATS PerfStats;
//
// This holds what we beleive to be the current value of
// the line control register.
//
// It should only be accessed under protection of the control
// lock since more than one request can be in the control dispatch
// routine at one time.
//
ULONG CommParity; ULONG CommDataLen;
//
// We keep track of whether the somebody has the device currently
// opened with a simple boolean. We need to know this so that
// spurious interrupts from the device (especially during initialization)
// will be ignored. This value is only accessed in the ISR and
// is only set via synchronization routines. We may be able
// to get rid of this boolean when the code is more fleshed out.
//
BOOLEAN DeviceIsOpened;
//
// This is only accessed at interrupt level. It keeps track
// of whether the holding register is empty.
//
BOOLEAN HoldingEmpty;
//
// This variable is only accessed at interrupt level. It
// indicates that we want to transmit a character immediately.
// That is - in front of any characters that could be transmitting
// from a normal write.
//
BOOLEAN TransmitImmediate;
//
// This variable is only accessed at interrupt level. Whenever
// a wait is initiated this variable is set to false.
// Whenever any kind of character is written it is set to true.
// Whenever the write queue is found to be empty the code that
// is processing that completing irp will synchonize with the interrupt.
// If this synchronization code finds that the variable is true and that
// there is a wait on the transmit queue being empty then it is
// certain that the queue was emptied and that it has happened since
// the wait was initiated.
//
BOOLEAN EmptiedTransmit;
//
// This simply indicates that the port associated with this
// extension is part of a multiport card.
//
// BOOLEAN PortOnAMultiportCard;
#ifndef POLL
//
// We keep the following values around so that we can connect
// to the interrupt and report resources after the configuration
// record is gone.
//
ULONG Vector; KIRQL Irql; ULONG OriginalVector; ULONG OriginalIrql; KINTERRUPT_MODE InterruptMode; KAFFINITY ProcessorAffinity; #endif
ULONG RuntimeAddressSpace; ULONG BoardMemoryAddressSpace; ULONG BusNumber; INTERFACE_TYPE InterfaceType;
//
// Port index for multiport devices
//
ULONG PortIndex;
//
// We hold the character that should be transmitted immediately.
//
// Note that we can't use this to determine whether there is
// a character to send because the character to send could be
// zero.
//
UCHAR ImmediateChar;
//
// This holds the mask that will be used to mask off unwanted
// data bits of the received data (valid data bits can be 5,6,7,8)
// The mask will normally be 0xff. This is set while the control
// lock is held since it wouldn't have adverse effects on the
// isr if it is changed in the middle of reading characters.
// (What it would do to the app is another question - but then
// the app asked the driver to do it.)
//
UCHAR ValidDataMask;
//
// The application can turn on a mode,via the
// IOCTL_CYZ_LSRMST_INSERT ioctl, that will cause the
// serial driver to insert the line status or the modem
// status into the RX stream. The parameter with the ioctl
// is a pointer to a UCHAR. If the value of the UCHAR is
// zero, then no insertion will ever take place. If the
// value of the UCHAR is non-zero (and not equal to the
// xon/xoff characters), then the serial driver will insert.
//
UCHAR EscapeChar;
// REMOVED FANNY
// //
// // This boolean will be true if a 16550 is present *and* enabled.
// //
// BOOLEAN FifoPresent;
//
// //
// // This denotes that this particular port is an on the motherboard
// // port for the Jensen hardware. On these ports the OUT2 bit
// // which is used to enable/disable interrupts is always hight.
// //
// BOOLEAN Jensen;
//
// This is the water mark that the rxfifo should be
// set to when the fifo is turned on. This is not the actual
// value, but the encoded value that goes into the register.
//
ULONG RxFifoTrigger;
#ifndef POLL
//
// Says whether this device can share interrupts with devices
// other than serial devices.
//
BOOLEAN InterruptShareable; #endif
//
// Records whether we actually created the symbolic link name
// at driver load time. If we didn't create it, we won't try
// to distry it when we unload.
//
BOOLEAN CreatedSymbolicLink;
//
// Records whether we actually created an entry in SERIALCOMM
// at driver load time. If we didn't create it, we won't try
// to destroy it when the device is removed.
//
BOOLEAN CreatedSerialCommEntry;
//
// We place all of the kernel and Io subsystem "opaque" structures
// at the end of the extension. We don't care about their contents.
//
//
// This lock will be used to protect various fields in
// the extension that are set (& read) in the extension
// by the io controls.
//
KSPIN_LOCK ControlLock;
//
// This lock will be used to protect the accept / reject state
// transitions and flags of the driver It must be acquired
// before a cancel lock
//
KSPIN_LOCK FlagsLock;
#ifdef POLL
//
// This lock will be used to protect various fields in
// the extension and in the hardware that are set (& read)
// by the Timer Dpc. In the NT driver, we used ControlLock
// for this.
//
KSPIN_LOCK PollLock; // Added to fix Modem Share test 53 freeze (dead lock)
#endif
//
// This points to a DPC used to complete read requests.
//
KDPC CompleteWriteDpc;
//
// This points to a DPC used to complete read requests.
//
KDPC CompleteReadDpc;
//
// This dpc is fired off if the timer for the total timeout
// for the read expires. It will execute a dpc routine that
// will cause the current read to complete.
//
//
KDPC TotalReadTimeoutDpc;
//
// This dpc is fired off if the timer for the interval timeout
// expires. If no more characters have been read then the
// dpc routine will cause the read to complete. However, if
// more characters have been read then the dpc routine will
// resubmit the timer.
//
KDPC IntervalReadTimeoutDpc;
//
// This dpc is fired off if the timer for the total timeout
// for the write expires. It will execute a dpc routine that
// will cause the current write to complete.
//
//
KDPC TotalWriteTimeoutDpc;
//
// This dpc is fired off if a comm error occurs. It will
// execute a dpc routine that will cancel all pending reads
// and writes.
//
KDPC CommErrorDpc;
//
// This dpc is fired off if an event occurs and there was
// a irp waiting on that event. A dpc routine will execute
// that completes the irp.
//
KDPC CommWaitDpc;
//
// This dpc is fired off when the transmit immediate char
// character is given to the hardware. It will simply complete
// the irp.
//
KDPC CompleteImmediateDpc;
//
// This dpc is fired off if the transmit immediate char
// character times out. The dpc routine will "grab" the
// irp from the isr and time it out.
//
KDPC TotalImmediateTimeoutDpc;
//
// This dpc is fired off if the timer used to "timeout" counting
// the number of characters received after the Xoff ioctl is started
// expired.
//
KDPC XoffCountTimeoutDpc;
//
// This dpc is fired off if the xoff counter actually runs down
// to zero.
//
KDPC XoffCountCompleteDpc;
//
// This dpc is fired off only from device level to start off
// a timer that will queue a dpc to check if the RTS line
// should be lowered when we are doing transmit toggling.
//
KDPC StartTimerLowerRTSDpc;
//
// This dpc is fired off when a timer expires (after one
// character time), so that code can be invoked that will
// check to see if we should lower the RTS line when
// doing transmit toggling.
//
KDPC PerhapsLowerRTSDpc;
//
// This DPC is fired to set an event stating that all other
// DPC's have been finish for this device extension so that
// paged code may be unlocked.
//
KDPC IsrUnlockPagesDpc;
//
// This is the kernal timer structure used to handle
// total read request timing.
//
KTIMER ReadRequestTotalTimer;
//
// This is the kernal timer structure used to handle
// interval read request timing.
//
KTIMER ReadRequestIntervalTimer;
//
// This is the kernal timer structure used to handle
// total time request timing.
//
KTIMER WriteRequestTotalTimer;
//
// This is the kernal timer structure used to handle
// total time request timing.
//
KTIMER ImmediateTotalTimer;
//
// This timer is used to timeout the xoff counter
// io.
//
KTIMER XoffCountTimer;
//
// This timer is used to invoke a dpc one character time
// after the timer is set. That dpc will be used to check
// whether we should lower the RTS line if we are doing
// transmit toggling.
//
KTIMER LowerRTSTimer; //
// This is a pointer to the next lower device in the IRP stack.
//
PDEVICE_OBJECT LowerDeviceObject;
//
// This is where keep track of the power state the device is in.
//
DEVICE_POWER_STATE PowerState;
//
// Pointer to the driver object
//
PDRIVER_OBJECT DriverObject;
//
// Event used to do some synchronization with the devices underneath me
// (namely ACPI)
//
KEVENT SerialSyncEvent;
//
// String where we keep the symbolic link that is returned to us when we
// register our device under the COMM class with the Plug and Play manager.
//
UNICODE_STRING DeviceClassSymbolicName;
//
// Count of pending IRP's
//
ULONG PendingIRPCnt;
//
// Accepting requests?
//
ULONG DevicePNPAccept;
//
// No IRP's pending event
//
KEVENT PendingIRPEvent;
//
// PNP State
//
ULONG PNPState;
//
// Misc Flags
//
ULONG Flags;
//
// Open count
//
LONG OpenCount;
//
// Start sync event
//
KEVENT CyzStartEvent;
//
// Current state during powerdown
//
CYZ_DEVICE_STATE DeviceState;
//
// Device stack capabilites
//
DEVICE_POWER_STATE DeviceStateMap[PowerSystemMaximum];
//
// Event to signal transition to D0 completion
//
KEVENT PowerD0Event;
//
// List of stalled IRP's
//
LIST_ENTRY StalledIrpQueue;
//
// Mutex on open status
//
FAST_MUTEX OpenMutex;
//
// Mutex on close
//
FAST_MUTEX CloseMutex;
//
// TRUE if we own power policy
//
BOOLEAN OwnsPowerPolicy;
//
// SystemWake from devcaps
//
SYSTEM_POWER_STATE SystemWake;
//
// DeviceWake from devcaps
//
DEVICE_POWER_STATE DeviceWake;
//
// Our PDO
//
PDEVICE_OBJECT Pdo;
//
// Should we enable wakeup
//
BOOLEAN SendWaitWake;
//
// Pending wait wake IRP
//
PIRP PendingWakeIrp;
//
// WMI Information
//
WMILIB_CONTEXT WmiLibInfo;
//
// Name to use as WMI identifier
//
UNICODE_STRING WmiIdentifier;
//
// WMI Comm Data
//
SERIAL_WMI_COMM_DATA WmiCommData;
//
// WMI HW Data
//
SERIAL_WMI_HW_DATA WmiHwData;
//
// WMI Performance Data
//
SERIAL_WMI_PERF_DATA WmiPerfData;
//
// Pending DPC count
//
ULONG DpcCount;
//
// Pending DPC event
//
KEVENT PendingDpcEvent;
//
// Should we expose external interfaces?
//
ULONG SkipNaming; //
// Com port number.
//
//ULONG Com;
//
// Flag to indicate if Command Failure error was already logged.
// Only one log per driver load. Otherwise, the system may crash if
// too many logs start happening.
//
BOOLEAN CmdFailureLog; //
// DCD Status when the firmware detected the DCD signal change
//
ULONG DCDstatus;
//
// Flag to indicate that the fw has processed the C_CM_IOCTLW command.
//
BOOLEAN IoctlwProcessed;
//
// Flag read from the Registry. It indicates when Write status is returned.
//
BOOLEAN ReturnStatusAfterFwEmpty; //
// Flag read from the Registry. It indicates that the reception should
// give the packets as soon as the second 7E is received.
//
BOOLEAN PPPaware;
//
// Flag to indicate that the driver can return the status of CyzWrite.
//
BOOLEAN ReturnWriteStatus;
// These two booleans are used to indicate to the isr transmit
// code that it should send the xon or xoff character. They are
// only accessed at open and at interrupt level.
//
BOOLEAN SendXonChar; BOOLEAN SendXoffChar;
//
// PCI slot where the board is inserted.
//
ULONG PciSlot;
} CYZ_DEVICE_EXTENSION,*PCYZ_DEVICE_EXTENSION;
#define CYZ_PNPACCEPT_OK 0x0L
#define CYZ_PNPACCEPT_REMOVING 0x1L
#define CYZ_PNPACCEPT_STOPPING 0x2L
#define CYZ_PNPACCEPT_STOPPED 0x4L
#define CYZ_PNPACCEPT_SURPRISE_REMOVING 0x8L
#define CYZ_PNP_ADDED 0x0L
#define CYZ_PNP_STARTED 0x1L
#define CYZ_PNP_QSTOP 0x2L
#define CYZ_PNP_STOPPING 0x3L
#define CYZ_PNP_QREMOVE 0x4L
#define CYZ_PNP_REMOVING 0x5L
#define CYZ_PNP_RESTARTING 0x6L
#define CYZ_FLAGS_CLEAR 0x0L
#define CYZ_FLAGS_STARTED 0x1L
#define CYZ_FLAGS_STOPPED 0x2L
#define CYZ_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.
//
#ifdef POLL
typedef struct _CYZ_DISPATCH { ULONG NChannels; PCYZ_DEVICE_EXTENSION Extensions[CYZ_MAX_PORTS]; KTIMER PollingTimer; LARGE_INTEGER PollingTime; ULONG PollingPeriod; KDPC PollingDpc; BOOLEAN PollingStarted; BOOLEAN PollingDrained; ULONG PollingCount; KSPIN_LOCK PollingLock; KSPIN_LOCK PciDoorbellLock; KEVENT PendingDpcEvent; } CYZ_DISPATCH,*PCYZ_DISPATCH; #else
typedef struct _CYZ_DISPATCH { ULONG NChannels; PCYZ_DEVICE_EXTENSION Extensions[CYZ_MAX_PORTS]; BOOLEAN PoweredOn[CYZ_MAX_PORTS]; } CYZ_DISPATCH,*PCYZ_DISPATCH; #endif
//
// 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 _CYZ_MEM_COMPARES { AddressesAreEqual, AddressesOverlap, AddressesAreDisjoint } CYZ_MEM_COMPARES,*PCYZ_MEM_COMPARES;
typedef struct _CYZ_GLOBALS { LIST_ENTRY AllDevObjs; PVOID PAGESER_Handle; UNICODE_STRING RegistryPath; KSPIN_LOCK GlobalsSpinLock; #if DBG
ULONG PAGESER_Count; #endif // DBG
} CYZ_GLOBALS, *PCYZ_GLOBALS;
extern CYZ_GLOBALS CyzGlobals;
typedef struct _SERIAL_PTR_CTX { ULONG isPointer; PHYSICAL_ADDRESS Port; ULONG Vector; } SERIAL_PTR_CTX, *PSERIAL_PTR_CTX;
#define DEVICE_OBJECT_NAME_LENGTH 128
#define SYMBOLIC_NAME_LENGTH 128
#define SERIAL_DEVICE_MAP L"SERIALCOMM"
//
// Return values for mouse detection callback
//
#define SERIAL_FOUNDPOINTER_PORT 1
#define SERIAL_FOUNDPOINTER_VECTOR 2
#define CyzCompleteRequest(PDevExt, PIrp, PriBoost) \
{ \ CyzDbgPrintEx(CYZIRPPATH, "Complete Irp: %X\n", (PIrp)); \ IoCompleteRequest((PIrp), (PriBoost)); \ CyzIRPEpilogue((PDevExt)); \ }
#define SERIAL_WMI_GUID_LIST_SIZE 5
extern WMIGUIDREGINFO SerialWmiGuidList[SERIAL_WMI_GUID_LIST_SIZE];
// For Cyclades-Z
#define CYZ_BASIC_RXTRIGGER 0x08 // Used in IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS
#define Z_COMPATIBLE_FIRMWARE 0x323 // C_CM_TXFEMPTY support added.
|