//--- 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();