|
|
//--- init.h(common for vs and rk)
// use 2.04.03 format 3 part optional for non-released versions)
// use 2.05 format 2 part for released changes
#ifdef S_RK
#ifdef NT50
#define VER_PRODUCTVERSION_STR "4.50"
#define VER_PRODUCTVERSION 4,50
#else
#define VER_PRODUCTVERSION_STR "4.50"
#define VER_PRODUCTVERSION 4,50
#endif
#else
#ifdef NT50
#define VER_PRODUCTVERSION_STR "2.50"
#define VER_PRODUCTVERSION 2,50
#else
#define VER_PRODUCTVERSION_STR "2.50"
#define VER_PRODUCTVERSION 2,50
#endif
#endif
// these are now turned on or off in the sources file in rk or vs dir
//#define ROCKET
//#define VS1000
//#define NT50
// make the ExAllocatePool call "WDM-compatible" - use pool tags version
// with our tag "Rckt" (little endian format)
#ifdef NT50
#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'tkcR')
#endif
#endif
//
// define paths to Rockwell modem firmware...
//
#define MODEM_CSREC_PATH "\\SystemRoot\\system32\\ROCKET\\ctmmdmfw.rm"
#define MODEM_CSM_SREC_PATH "\\SystemRoot\\system32\\ROCKET\\ctmmdmld.rm"
//#define TRY_DYNAMIC_BINDING
// define to allow modem download for new pci rocketmodem 56k product(no flash)
#define MDM_DOWNLOAD
// these should be on, they are left in just in case(will strip out in future)
#define RING_FAKE
#define USE_SYNC_LOCKS
#define NEW_WAIT
#define NEW_WRITE_SYNC_LOCK
#define NEW_WAIT_SYNC_LOCK
#ifdef S_RK
// we can only use this on rocketport
#define NEW_FAST_TX
#endif
#define TRACE_PORT
#define USE_HAL_ASSIGNSLOT
// pnp bus-driver stuff
#define DO_BUS_EXTENDER
// attempted io-aliasing solution for nt5.0 to properly get resources
// for isa-bus cards using alias io space
#define DO_ISA_BUS_ALIAS_IO
#define GLOBAL_ASSERT
#define GLOBAL_TRACE
#define TRACE_PORT
#ifdef S_VS
#define MAX_NUM_BOXES 64
#else
#define MAX_NUM_BOXES 8
#endif
#define MAX_PORTS_PER_DEVICE 64
//---- following used to trace driver activity
//#define D_L0 0x00001L
//#define D_L2 0x00004L
//#define D_L4 0x00010L
//#define D_L6 0x00040L
//#define D_L7 0x00080L
//#define D_L8 0x00100L
//#define D_L9 0x00200L
//#define D_L10 0x00400L
//#define D_L11 0x00800L
#define D_Error 0x08000L
#define D_All 0xffffffffL
#define D_Nic 0x00002L
#define D_Hdlc 0x00008L
#define D_Port 0x00020L
#define D_Options 0x01000L
//---- following used to trace driver activity
#define D_Init 0x00010000L
#define D_Pnp 0x00020000L
#define D_Ioctl 0x00040000L
#define D_Write 0x00080000L
#define D_Read 0x00100000L
#define D_Ssci 0x00200000L
#define D_Thread 0x00400000L
#define D_Test 0x00800000L
#define D_PnpAdd 0x01000000L
#define D_PnpPower 0x02000000L
//Constant definitions for the I/O error code log values.
// Values are 32 bit values layed out as follows:
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
// where
// Sev - is the severity code
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
// C - is the Customer code flag
// R - is a reserved bit
// Facility - is the facility code
// Code - is the facility's status code
// Define the facility codes
#define FACILITY_SERIAL_ERROR_CODE 0x6
#define FACILITY_RPC_STUBS 0x3
#define FACILITY_RPC_RUNTIME 0x2
#define FACILITY_IO_ERROR_CODE 0x4
// Define the severity codes
#define STATUS_SEVERITY_WARNING 0x2
#define STATUS_SEVERITY_SUCCESS 0x0
#define STATUS_SEVERITY_INFORMATIONAL 0x1
#define STATUS_SEVERITY_ERROR 0x3
#ifdef S_RK
#define SERIAL_RP_INIT_FAIL ((NTSTATUS)0x80060001L)
#else
#define SERIAL_RP_INIT_FAIL ((NTSTATUS)0xC0060001L)
#endif
#define SERIAL_RP_INIT_PASS ((NTSTATUS)0x40060002L)
#define SERIAL_NO_SYMLINK_CREATED ((NTSTATUS)0x80060003L)
#define SERIAL_NO_DEVICE_MAP_CREATED ((NTSTATUS)0x80060004L)
#define SERIAL_NO_DEVICE_MAP_DELETED ((NTSTATUS)0x80060005L)
#define SERIAL_UNREPORTED_IRQL_CONFLICT ((NTSTATUS)0xC0060006L)
#define SERIAL_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC0060007L)
#define SERIAL_NO_PARAMETERS_INFO ((NTSTATUS)0xC0060008L)
#define SERIAL_UNABLE_TO_ACCESS_CONFIG ((NTSTATUS)0xC0060009L)
#define SERIAL_UNKNOWN_BUS ((NTSTATUS)0xC006000AL)
#define SERIAL_BUS_NOT_PRESENT ((NTSTATUS)0xC006000BL)
#define SERIAL_INVALID_USER_CONFIG ((NTSTATUS)0xC006000CL)
#define SERIAL_RP_RESOURCE_CONFLICT ((NTSTATUS)0xC006000DL)
#define SERIAL_RP_HARDWARE_FAIL ((NTSTATUS)0xC006000EL)
#define SERIAL_DEVICEOBJECT_FAILED ((NTSTATUS)0xC006000FL)
#define SERIAL_CUSTOM_ERROR_MESSAGE ((NTSTATUS)0xC0060010L)
#define SERIAL_CUSTOM_INFO_MESSAGE ((NTSTATUS)0x40060011L)
#define SERIAL_NT50_INIT_PASS ((NTSTATUS)0x40060012L)
// max number of nic cards we will allow
#define VS1000_MAX_NICS 6
#ifdef GLOBAL_ASSERT
#define GAssert(id, exp ) { if (!(exp)) our_assert(id, __LINE__); }
#else
#define GAssert(id, exp )
#endif
#ifdef GLOBAL_TRACE
#define GTrace3(_Mask,_LeadStr, _Msg,_P1,_P2, _P3) \
{ if (Driver.GTraceFlags & _Mask) TTprintf(_LeadStr, _Msg, _P1, _P2, _P3); }
#define GTrace2(_Mask,_LeadStr, _Msg,_P1,_P2) \
{ if (Driver.GTraceFlags & _Mask) TTprintf(_LeadStr, _Msg, _P1, _P2); }
#define GTrace1(_Mask,_LeadStr, _Msg,_P1) \
{ if (Driver.GTraceFlags & _Mask) TTprintf(_LeadStr, _Msg, _P1); }
#define GTrace(_Mask_, _LeadStr, _Msg_) \
{ if (Driver.GTraceFlags & _Mask_) OurTrace(_LeadStr, _Msg_); } //#define GMark(c, x)
#else
#define GTrace2(_Mask,_LeadStr, _Msg,_P1, _P2) {}
#define GTrace1(_Mask,_LeadStr, _Msg,_P1) {}
#define GTrace(_Mask_, _LeadStr, _Msg_) {}
//#define GMark(c, x) {}
#endif
// following are for debug, when checked build is made DBG is defined
// and the messages go to our debug queue and the nt debug string output.
#if DBG
#define DTrace3(_Mask_,_LeadStr,_Msg_,_P1_,_P2_,_P3_) \
{ if (RocketDebugLevel & _Mask_) TTprintf(_LeadStr,_Msg_,_P1_,_P2_,_P3_); }
#define DTrace2(_Mask_,_LeadStr,_Msg_,_P1_,_P2_) \
{ if (RocketDebugLevel & _Mask_) TTprintf(_LeadStr,_Msg_,_P1_,_P2_); }
#define DTrace1(_Mask_,_LeadStr,_Msg_,_P1_) \
{ if (RocketDebugLevel & _Mask_) TTprintf(_LeadStr,_Msg_,_P1_); }
#define DTrace(_Mask_,_LeadStr,_Msg_) \
{ if (RocketDebugLevel & _Mask_) OurTrace(_LeadStr, _Msg_); }
#define DPrintf(_Mask_,_Msg_) \
{ if (RocketDebugLevel & _Mask_) Tprintf _Msg_; } #else
#define DTrace3(_Mask,_LeadStr, _Msg,_P1, _P2, _P3) {}
#define DTrace2(_Mask,_LeadStr, _Msg,_P1, _P2) {}
#define DTrace1(_Mask,_LeadStr, _Msg,_P1) {}
#define DTrace(_Mask_, _LeadStr, _Msg_) {}
#define DPrintf(_Mask_,_Msg_) {}
#endif
#ifdef TRACE_PORT
#define ExtTrace4(_Ext_,_Mask_,_Msg_,_P1_,_P2_,_P3_, _P4_) \
{ if (_Ext_->TraceOptions & 1) Tprintf(_Msg_,_P1_,_P2_,_P3_,_P4_); }
#define ExtTrace3(_Ext_,_Mask_,_Msg_,_P1_,_P2_,_P3_) \
{ if (_Ext_->TraceOptions & 1) Tprintf(_Msg_,_P1_,_P2_,_P3_); }
#define ExtTrace2(_Ext_,_Mask_,_Msg_,_P1_,_P2_) \
{ if (_Ext_->TraceOptions & 1) Tprintf(_Msg_,_P1_,_P2_); }
#define ExtTrace1(_Ext_,_Mask_,_Msg_,_P1_) \
{ if (_Ext_->TraceOptions & 1) Tprintf(_Msg_,_P1_); }
#define ExtTrace(_Ext_,_Mask_,_Msg_) \
{ if (_Ext_->TraceOptions & 1) Tprintf(_Msg_); } #else
#define ExtTrace3(_Mask_,_Msg_,_P1_,_P2_,_P3_) {}
#define ExtTrace2(_Mask_,_Msg_,_P1_,_P2_) {}
#define ExtTrace1(_Mask_,_Msg_,_P1_) {}
#define ExtTrace(_Mask_,_Msg_) {}
#endif
#if DBG
#define MyAssert( exp ) { if (!(exp)) MyAssertMessage(__FILE__, __LINE__); }
# ifdef S_VS
#define MyKdPrint(_Mask_,_Msg_) \
{ \ if (_Mask_ & RocketDebugLevel) { \ DbgPrint ("VS:"); \ DbgPrint _Msg_; \ } \ } # else
#define MyKdPrint(_Mask_,_Msg_) \
{ \ if (_Mask_ & RocketDebugLevel) { \ DbgPrint ("RK:"); \ DbgPrint _Msg_; \ } \ } # endif
#define MyKdPrintUnicode(_Mask_,_PUnicode_)\
if(_Mask_ & RocketDebugLevel) \ { \ ANSI_STRING tempstr; \ RtlUnicodeStringToAnsiString(&tempstr,_PUnicode_,TRUE); \ DbgPrint("%s",tempstr.Buffer);\ RtlFreeAnsiString(&tempstr); \ } #else
#define MyAssert( exp ) {}
#define MyKdPrint(_Mask_,_Msg_) {}
#define MyKdPrintUnicode(_Mask_,_PUnicode_) {}
#endif //DBG
#define SERIAL_NONE_PARITY ((UCHAR)0x00)
#define SERIAL_ODD_PARITY ((UCHAR)0x08)
#define SERIAL_EVEN_PARITY ((UCHAR)0x18)
#define SERIAL_MARK_PARITY ((UCHAR)0x28)
#define SERIAL_SPACE_PARITY ((UCHAR)0x38)
#define SERIAL_PARITY_MASK ((UCHAR)0x38)
// This should be enough space to hold the numeric suffix of the device name.
// #define DEVICE_NAME_DELTA 20
// 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)
#define ST_XOFF_FAKE ((ULONG)0x20) // added for SETXOFF(kpb)
// 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)
//--- flags for MdmCountry (ROW country code)
#define ROW_NOT_USED 0
#define ROW_AUSTRIA 1
#define ROW_BELGIUM 2
#define ROW_DENMARK 3
#define ROW_FINLAND 4
#define ROW_FRANCE 5
#define ROW_GERMANY 6
#define ROW_IRELAND 7
#define ROW_ITALY 8
#define ROW_LUXEMBOURG 9
#define ROW_NETHERLANDS 10
#define ROW_NORWAY 11
#define ROW_PORTUGAL 12
#define ROW_SPAIN 13
#define ROW_SWEDEN 14
#define ROW_SWITZERLAND 15
#define ROW_UK 16
#define ROW_GREECE 17
#define ROW_ISRAEL 18
#define ROW_CZECH_REP 19
#define ROW_CANADA 20
#define ROW_MEXICO 21
#define ROW_USA 22
#define ROW_NA ROW_USA
#define ROW_HUNGARY 23
#define ROW_POLAND 24
#define ROW_RUSSIA 25
#define ROW_SLOVAC_REP 26
#define ROW_BULGARIA 27
// 28
// 29
#define ROW_INDIA 30
// 31
// 32
// 33
// 34
// 35
// 36
// 37
// 38
// 39
#define ROW_AUSTRALIA 40
#define ROW_CHINA 41
#define ROW_HONG_KONG 42
#define ROW_JAPAN 43
#define ROW_PHILIPPINES ROW_JAPAN
#define ROW_KOREA 44
// 45
#define ROW_TAIWAN 46
#define ROW_SINGAPORE 47
#define ROW_NEW_ZEALAND 48
#define ROW_DEFAULT ROW_USA
// Ext->DeviceType: // DEV_PORT, DEV_DRIVER, DEV_BOARD
#define DEV_PORT 0
#define DEV_BOARD 1
/* Configuration information structure for one port */ typedef struct { char Name[12]; ULONG LockBaud; ULONG TxCloseTime; int WaitOnTx : 1; int RS485Override : 1; int RS485Low : 1; int Map2StopsTo1 : 1; int MapCdToDsr : 1; int RingEmulate : 1; } PORT_CONFIG;
/* Configuration information structure for one board or vs1000("device") */ typedef struct { #ifdef S_RK
unsigned int MudbacIO; /* I/O address of MUDBAC */ PUCHAR pMudbacIO; /* NT ptrs to I/O address of MUDBAC */ unsigned int BaseIoAddr; // normal io-address
unsigned int TrBaseIoAddr; // translated io-address
PUCHAR pBaseIoAddr; // final indirect mapped handle for io-address
unsigned int BaseIoSize; /* 44H for 1st isa, 40 for isa addition, etc */ unsigned int ISABrdIndex; /* 0 for first, 1 for second, etc(isa only) */ unsigned int AiopIO[AIOP_CTL_SIZE]; /* I/O addresses of AIOPs */ PUCHAR pAiopIO[AIOP_CTL_SIZE]; /* NT ptrs to I/O address of AIOPs */ //int NumChan; /* number of channels on this controller */
// use NumPorts instead
int NumAiop; /* number of Aiops on board */ unsigned int RocketPortFound; /* indicates ctl was found and init'd */ INTERFACE_TYPE BusType; /* PCIBus or Isa */ int PCI_DevID; int PCI_RevID; int PCI_SVID; int PCI_SID;
int Irq; int InterruptMode; int IrqLevel; int IrqVector; int Affinity;
int TrInterruptMode; int TrIrqLevel; int TrIrqVector; int TrAffinity;
int PCI_Slot; int BusNumber;
int IsRocketPortPlus; // true if rocketport plus hardware
#else
int IsHubDevice; // true if device(RHub) uses slower baud clock
#endif
BOOLEAN HardwareStarted;
BYTE MacAddr[6]; // vs1000
int BackupServer; // vs1000
int BackupTimer; // vs1000
//int StartComIndex; // starting com-port index
ULONG Hardware_ID; // software derived hardware id(used for nt50 now)
ULONG IoAddress; // user interface io-address selection
int ModemDevice; // true for RocketModems & Vs2000
int NumPorts; // configured number of ports on this device
ULONG ClkRate; // def:36864000=rcktport, 44236800=rplus, 18432000=rhub
ULONG ClkPrescaler; // def:14H=rcktport, 12H=rplus, 14H=rhub
#ifdef NT50
// this holds the pnp-name we use as a registry key to hold
// our device parameters in the registry for RocketPort & NT50
char szNt50DevObjName[50]; // typical: "Device_002456
#else
int DevIndex; // nt40 keeps simple linear list of devices 0,1,2...
#endif
PORT_CONFIG port[MAX_PORTS_PER_DEVICE]; // our read in port configuration
} DEVICE_CONFIG;
#define TYPE_RM_VS2000 1
#define TYPE_RMII 2
#define TYPE_RM_i 3
// forward declaration
typedef struct _SERIAL_DEVICE_EXTENSION *PSERIAL_DEVICE_EXTENSION;
typedef struct _SERIAL_DEVICE_EXTENSION { USHORT DeviceType; // DEV_PORT, DEV_BOARD
USHORT BoardNum; // 0,1,2,3 for DEV_BOARD type
BOOLEAN IsPDO; // a nt50 pnp thing, tells if we are a pdo or fdo
char NtNameForPort[32]; // like "RocketPort0"
char SymbolicLinkName[16]; // like "COM5"
#ifdef S_VS
//int box_num; // index into box & hdlc array
SerPort *Port; // if a DEV_PORT type extension
PortMan *pm; // if a DEV_BOARD type extension
Hdlc *hd; // if a DEV_BOARD type extension
//int DeviceNum; // index into total port array
#else
CHANPTR_T ChP; // ptr to channel structure
CHANNEL_T ch; // our board channel structure
#endif
unsigned int UniqueId; // 0,1,2,3... CreateBoardDevice() bumps...
// if we are DEV_BOARD, the this points to next board extension
// if we are DEV_PORT, then it points to our parent board
PSERIAL_DEVICE_EXTENSION board_ext;
// if we are DEV_BOARD, the this points to start of port extensions
// if we are DEV_PORT, then it points to next port extension
PSERIAL_DEVICE_EXTENSION port_ext; // next port extension
// if we are DEV_BOARD, the this points to start of pdo port extensions
PSERIAL_DEVICE_EXTENSION port_pdo_ext; // next pdo port extension
ULONG BaudRate; // NT defined baud rate
SERIAL_LINE_CONTROL LineCtl; // NT defined line control
ULONG ModemStatus; // NT defined modem status
ULONG DTRRTSStatus; // NT defined modem status
USHORT DevStatus; // device status
//unsigned int FlowControl;
//unsigned int DetectEn;
#ifdef S_RK
USHORT io_reported; // flag to tell if we have io,irq to unreport.
ULONG EventModemStatus; // used to detect change for events
unsigned int ModemCtl; unsigned int IntEnables; // RP specific ints to enable
#endif
int PortIndex; // if port: index into ports on board(0,1,2..)
#ifdef TXBUFFER
//PUCHAR TxBuf;
//LONG TxIn;
//LONG TxOut;
//LONG TxBufSize;
#endif
Queue RxQ;
// Used to keep ISR from completing a read while it is being started.
BOOLEAN ReadPending;
// 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;
// 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;
// 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;
// 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
// 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 count the number
// of characters received after an xoff (as currently defined
// by the IOCTL_SERIAL_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;
// The syncronization between the various threads in this
// driver is hosed up in places, besides being really confusing.
// This is an attempt to have a protected flag which is set
// to 1 if the ISR owns the currentwriteirp, 2 if the ISR
// is in the progress of ending the IRP(going to serialcompletewrite),
// and 0 when it is complete. The starter routine sets it
// from 0 to 1 to give a new irp to the isr/timer routine for
// processing. The ISR sets it from 1 to 2 when it queues
// the DPC to finalize the irp. The DPC sets it from 2 to
// 0 when it completes the irp. The cancel or timer routines
// must run a synchronized routine which guarentees sole access
// to this flag. Looks if it is 1, if it is 1 then it takes
// by setting it to zero, and returning a flag to indicate to
// the caller to finalize the irp. If it is a 2, it assumes
// the isr has arranged to finalize the irp. Geez-O-Pete
// what a lot of silly gears!
ULONG WriteBelongsToIsr;
// 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 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; ULONG WaitIsISRs; // 1=owned by isr.c(expicit help)
ULONG DummyIrpMaskLoc; // Point the IrpMaskLocation here when not in use
// 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 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;
// 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;
// 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 DeviceIsOpen;
// 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;
// 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 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 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 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 timer is used to timeout the xoff counter
// io.
KTIMER XoffCountTimer;
USHORT sent_packets; // number of write() packets
USHORT rec_packets; // number of read() packets
SERIALPERF_STATS OurStats; // our non-resetable stats
SERIALPERF_STATS OldStats; // performance monitor statistics(resetable)
USHORT TraceOptions; // Debug Trace Options. 1=trace, 2=in data, 4=out dat
// 8 = isr level events
USHORT ISR_Flags; // bit flags used to control ISR, detects EV_TXEMPTY
// used by NT virt-driver to embed modem status changes in input stream
unsigned char escapechar; unsigned char Option; // used for per port options
void *TraceExt; // Debug Trace Extension
PORT_CONFIG *port_config; // if a port extension, points to port config data
DEVICE_CONFIG *config; // if a board extension, points to config data
//KEVENT SerialSyncEvent;
#ifdef S_RK
CONTROLLER_T *CtlP; // if a board extension, points to controller struct
#endif
// This is to tell the driver that we have received a QUERY_POWER asking
// to power down. The driver will then queue any open requests until after
// the power down.
BOOLEAN ReceivedQueryD3; #ifdef NT50
PDEVICE_OBJECT Pdo; // new PnP object used to open registry.
PDEVICE_OBJECT LowerDeviceObject; // new PnP stack arrangement.
// This is where keep track of the power state the device is in.
DEVICE_POWER_STATE PowerState;
// 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; #endif
// Count of pending IRP's
ULONG PendingIRPCnt; // Accepting requests?
ULONG DevicePNPAccept;
// No IRP's pending event
KEVENT PendingIRPEvent;
// PNP State
ULONG PNPState;
// Used by PnP.c module
//BOOLEAN DeviceIsOpened;
BOOLEAN FdoStarted;
#ifdef RING_FAKE
BYTE ring_char; // used to implement RING emulation via software
BYTE ring_timer; // used to implement RING emulation via software
#endif
#ifdef NT50
// 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; #endif
} SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION;
//--- bits for Option field in extension
#define OPTION_RS485_OVERRIDE 0x0001 // always use 485 mode
#define OPTION_RS485_SOFTWARE_TOGGLE 0x0002 // port in toggle mode
#define OPTION_RS485_HIGH_ACTIVE 0x0004 // use hardware to toggle rts low
//--- bit flags for ISR_Flags
#define TX_NOT_EMPTY 0x0001
#define SERIAL_PNPACCEPT_OK 0x0L
#define SERIAL_PNPACCEPT_REMOVING 0x1L
#define SERIAL_PNPACCEPT_STOPPING 0x2L
#define SERIAL_PNPACCEPT_STOPPED 0x4L
#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_FLAGS_CLEAR 0x0L
#define SERIAL_FLAGS_STARTED 0x1L
typedef struct _DRIVER_CONTROL {
PDRIVER_OBJECT GlobalDriverObject;
// copy of RegistryPath into DriverEntry, with room for adding options
UNICODE_STRING RegPath;
// working global RegistryPath string, , with room for adding options
UNICODE_STRING OptionRegPath;
// head link of all board extensions
PSERIAL_DEVICE_EXTENSION board_ext;
USHORT VerboseLog; // boolean flag tells to log verbose to eventlog.
USHORT ScanRate; // scan rate in milliseconds
USHORT PreScaler; // optional prescaler value for rocketport boards
USHORT MdmCountryCode; // country code for ROW RocketModems
USHORT MdmSettleTime; // time to allow modems to settle (unit=0.10 sec)
ULONG load_testing; // load testing(creates artificial load in isr.c)
#ifdef S_VS
// This is the names of the NIC cards which we get from the Registry.
// Used to specify the nic card when we do an OpenAdapter call.
char *BindNames; // list of strings, null, null terminated [VS1000_MAX_BINDINGS];
#ifdef OLD_BINDING_GATHER
PWCHAR BindString; // binding in registry, tells us what nic cards we have
// This is the names of the NIC cards which we get from the Registry.
// Used to specify the nic card when wee do an OpenAdapter call.
UNICODE_STRING NicName[VS1000_MAX_BINDINGS];
int num_nics; // number of nic cards in system which we use
int num_bindings; // number of nic card bindings in our NicName list
// there may be lots of old useless bindings with NT, PCI adapters
// leave an old binding resident for each slot they are booted in
// under nt50, pcmcia adapters also have inactive bindings.
#endif
#ifdef TRY_DYNAMIC_BINDING
// bind passes in a handle as a reference, when we get an un-bind
// we get passed in another handle. At unbind time, we look up in
// this table to figure which nic card it references.
NDIS_HANDLE BindContext[VS1000_MAX_NICS]; #endif
Nic *nics; // our open nic adapters, array of Nic structs.
//Hdlc *hd; // array of Hdlc structs(NumBoxes # of elements)
//PortMan *pm; // array of PortMan structs(NumBoxes # of elements)
//SerPort *sp; // total array of serial-port structs(1 per port)
// tells if thread needs to save off a detected mac-address back
// to config reg area.
PSERIAL_DEVICE_EXTENSION AutoMacDevExt; #endif
#ifdef S_RK
ULONG SetupIrq; // Irq used, 0 if none, 1 if PCI automatic
#endif
PKINTERRUPT InterruptObject;
// Timer fields
KTIMER PollTimer; LARGE_INTEGER PollIntervalTime; KDPC TimerDpc; //USHORT TotalNTPorts; // count of ports registered with NT
ULONG PollCnt; // count of interrupts/timer ticks
ULONG WriteDpcCnt; USHORT TimerCreated; USHORT InRocketWrite;
ULONG TraceOptions; // bit flags, tells what driver parts to trace
ULONG TraceFlags; Queue DebugQ; // data output buffer for driver debug log
PSERIAL_DEVICE_EXTENSION DebugExt; KSPIN_LOCK DebugLock; ULONG DebugTimeOut; // used to timeout inactive debug sessions.
#ifdef S_RK
USHORT RS485_Flags; // 1H bit set if Reverse hardware type
// clear if driver toggles RTS high
#endif
ULONG GTraceFlags; // trace flags, global.
ULONG mem_alloced; // track how much memory we are using
#ifdef S_VS
UCHAR *MicroCodeImage; // mem buf for micro code to download to unit
ULONG MicroCodeSize; // size of it in bytes
// This is the handle for the protocol returned by ndisregisterprotocol
NDIS_HANDLE NdisProtocolHandle; ULONG ndis_version; // 3=NT3.51, 4=NT4.0(includes dynamic binding)
// for auto-find boxes, make a list of boxes which respond with
// there mac address. Keep 2 extra bytes, byte [6] is for
// flags in response tells us if main-driver-app loaded,
// while last byte[7] we stuff with the nic-index which responded.
int NumBoxMacs; BYTE BoxMacs[MAX_NUM_BOXES*8]; // following is a counter per mac-address added to list where
// the list entry will be removed after it ticks down to zero.
// when the mac-address is added to the list or found again,
// the counter is initialized to some non-zero value(say 5)
// and then each time a broadcast query is sent out, all the
// counters are decremented by 1. When they hit zero, they
// are removed from the list.
BYTE BoxMacsCounter[MAX_NUM_BOXES]; #else
UCHAR *ModemLoaderCodeImage; // --> mem buf for modem loader code to download to unit
ULONG ModemLoaderCodeSize; // size in bytes
UCHAR *ModemCodeImage; // --> mem buf for modem code to download to unit
ULONG ModemCodeSize; // size in bytes
#endif
int NoPnpPorts; // flag to tell if we should eject port pdo's
#ifdef S_RK
PSERIAL_DEVICE_EXTENSION irq_ext; // board ext doing global irq, null if not used
#endif
//int NT50_PnP;
int NumDevices; // configuration count of NumDevices for NT4.0
int Stop_Poll; // flag to stop poll access
KSPIN_LOCK TimerLock; // Timer DPC(ISR) lock to sync up code
#ifdef S_VS
HANDLE threadHandle; int threadCount; //int TotalNTPorts; // this should go away(vs uses it)
#endif
LARGE_INTEGER IsrSysTime; // ISR service routine gets this every time
// so we know what are time base is.
LARGE_INTEGER LastIsrSysTime; // used to recalculate the tick rate periodically
ULONG TickBaseCnt; // used to recalculate the tick rate periodically
// this is the isr-tick rate in 100us units. Timers called by the
// isr-service routine can assume they are called periodically based
// on this rate. Needed for accurate time bases(VS protocol timers).
ULONG Tick100usBase;
// one of these made, and is used to support the global driver
// object which the applications can open and talk to driver.
PSERIAL_DEVICE_EXTENSION driver_ext;
} DRIVER_CONTROL;
typedef struct { char *imagepath; char *imagetype; UCHAR *image; ULONG imagesize; int rc; } MODEM_IMAGE;
/* Configuration information structure for one port */ typedef struct { ULONG BusNumber; ULONG PCI_Slot; ULONG PCI_DevID; ULONG PCI_RevID; ULONG BaseIoAddr; ULONG Irq; ULONG NumPorts; ULONG PCI_SVID; ULONG PCI_SID; ULONG Claimed; // 1 if we assigned or used it.
} PCI_CONFIG;
typedef NTSTATUS (*PSERIAL_START_ROUTINE) ( IN PSERIAL_DEVICE_EXTENSION );
typedef VOID (*PSERIAL_GET_NEXT_ROUTINE) ( IN PIRP *CurrentOpIrp, IN PLIST_ENTRY QueueToProcess, OUT PIRP *NewIrp, IN BOOLEAN CompleteCurrent, PSERIAL_DEVICE_EXTENSION Extension );
typedef struct _SERIAL_UPDATE_CHAR { PSERIAL_DEVICE_EXTENSION Extension; ULONG CharsCopied; BOOLEAN Completed; } SERIAL_UPDATE_CHAR,*PSERIAL_UPDATE_CHAR;
//
// The following simple structure is used to send a pointer
// the device extension and an ioctl specific pointer
// to data.
//
typedef struct _SERIAL_IOCTL_SYNC { PSERIAL_DEVICE_EXTENSION Extension; PVOID Data; } SERIAL_IOCTL_SYNC,*PSERIAL_IOCTL_SYNC;
//
// Return values for mouse detection callback
//
//#define SERIAL_FOUNDPOINTER_PORT 1
//#define SERIAL_FOUNDPOINTER_VECTOR 2
//
// The following three macros are used to initialize, increment
// and decrement reference counts in IRPs that are used by
// this driver. The reference count is stored in the fourth
// argument of the irp, which is never used by any operation
// accepted by this driver.
//
#define SERIAL_REF_ISR (0x00000001)
#define SERIAL_REF_CANCEL (0x00000002)
#define SERIAL_REF_TOTAL_TIMER (0x00000004)
#define SERIAL_REF_INT_TIMER (0x00000008)
#define SERIAL_REF_XOFF_REF (0x00000010)
#define SERIAL_INIT_REFERENCE(Irp) { \
ASSERT(sizeof(LONG) <= sizeof(PVOID)); \ IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4 = NULL; \ }
#define SERIAL_SET_REFERENCE(Irp,RefType) \
do { \ LONG _refType = (RefType); \ PLONG _arg4 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4; \ GAssert(515,!(*_arg4 & _refType)); \ *_arg4 |= _refType; \ } while (0)
#define SERIAL_CLEAR_REFERENCE(Irp,RefType) \
do { \ LONG _refType = (RefType); \ PLONG _arg4 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4; \ *_arg4 &= ~_refType; \ } while (0) //GAssert(516,*_arg4 & _refType); \ (pull out, not valid, kpb, 1-18-98)
//#define SERIAL_INC_REFERENCE(Irp) \ // ((*((LONG *)(&(IoGetCurrentIrpStackLocation((Irp)))->Parameters.Others.Argument4)))++)
//#define SERIAL_DEC_REFERENCE(Irp) \ // ((*((LONG *)(&(IoGetCurrentIrpStackLocation((Irp)))->Parameters.Others.Argument4)))--)
#define SERIAL_REFERENCE_COUNT(Irp) \
((LONG)((IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4)))
extern ULONG RocketDebugLevel; extern DRIVER_CONTROL Driver; // driver related options and references
#ifdef S_RK
extern PCI_CONFIG PciConfig[MAX_NUM_BOXES+1]; // array of all our pci-boards in sys
#endif
extern int LoadModemCode(char *firm_pathname,char *flm_pathname); extern void FreeModemFiles();
|