/******
 *
 *	F O S _ I S D N . H          by Jan Ceuleers, The Experimenter Board, 1992
 *
 ******/

#include <apidef.inc>

//#define ENABLE_LED
//#define HAYES_ESCAPE_CODE

#define VERNUM "0.05"

//#define ALPHA
//#define BETA
#define GAMMA
//#define RELEASE

#define P(f) (pport->f)
#define P0(f) (ports->f)

#define XON  17
#define XOFF 19

typedef char far *charFarPtr_t;

typedef struct flowControl_t
{
	unsigned mask;					// mask as defined by function 0Fh of FSC-0015
	int      restart;				// flag indicating whether receiver has to be restarted
	unsigned char rxXonXoffState;	// flow control state for receive Xon/Xoff
	unsigned char txXonXoffState;	// flow control state for transmit Xon/Xoff
} flowControl_t;

#define NUMBER_OF_REGISTERS 20

typedef struct modem_t
{
	unsigned char B, E, L, M, Q, V, X, Y;
	unsigned char S[NUMBER_OF_REGISTERS];
	unsigned hayesState;		// see comment in hayes.c for values
	char hayesCommandBuffer[41];
	char *hayesBufTail;
	unsigned responseCode;
	unsigned extraResponseInfo;
	int chars;					// number of garbage chars entered in command
	               				// mode; used to count number of backspaces required
} modem_t;

typedef struct call_t
{
	int referenceNumber;
	int state;					// 0: idle, 1: incoming call, 2: call proceeding, 3: outgoing call pending
	int refuseAllCalls;
	unsigned timer;
	int checkAutoAnswer;		// 1 each time RING is output
	int hangupRequested;		// Set to 1 by interrupt routine if the call needs to be terminated
	char address[A_ADDRESS_ARRAY_LENGTH];
	char subaddress[A_SUBADDRESS_ARRAY_LENGTH];
	int protocol;
//	int speed;					// Speed as encoded in ISDN API
//	int datab_stopb_par;		// parms "     "    "    "   "

	struct
	{
		CALL_INFO_TP			call_info;
		RECEIVE_STRING_TP		incoming_data;
	} no_wait;

	union
	{
		ACCEPT_CALL_TP			accept;
		CALL_SETUP_TP			setup;
		DEFINE_INC_CALL_TP		def_inc_call;
		REJECT_CALL_TP			rej_call;
		RELEASE_CALL_TP 		release;
		REMOVE_INCOMING_CALL_TP rem_inc_call;
		RN_INFO_TP				rn_info;
		SEND_STRING_TP			outgoing_data;
	} message;
} call_t;

#ifdef ENABLE_LED
	typedef struct led_t
	{
		unsigned portNumber;
		unsigned trigger[8];
	} led_t;
#endif

typedef struct port_t
{
	unsigned number;			// 0xFF: unavailable
	unsigned initialized;		// whether or not initialized
	unsigned rxBufSize;
	unsigned txBufSize;
	unsigned rxBufChars;		// Number of characters currently in buffer
	unsigned txBufChars;
	charFarPtr_t rxBuf;
	charFarPtr_t txBuf;
	charFarPtr_t rxBufHead;
	charFarPtr_t rxBufTail;
	charFarPtr_t txBufHead;
	charFarPtr_t txBufTail;
	unsigned ticksSinceLastTx;
	unsigned ticksSinceLastPoll;
	unsigned numberOfPollsThisTick;
	unsigned idleCount;
	unsigned status;
	int overrun;
	int charToSendNow;
	flowControl_t flowControl;
	modem_t modem;
	call_t call;
	#ifdef ENABLE_LED
		led_t led;
	#endif
} port_t;

// V.110 and V.120, both synchronous and asynchronous
// + V.110 asynchronous protocol_override on HLC=126
// + V.120 synchronous  protocol_override on HLC=125
// + V.120 asynchronous protocol_override on HLC=124
#define NUMBER_OF_FILTERS 7

typedef struct
{
	int               protocol;
	int               protocol_override;
	int               hlc_coding;
	int               hlc_id;
	int               filter_nmbr;
	CHECK_INC_CALL_TP message;
} incomingCallFilter_t;

#define RSP_OK              0
#define RSP_CONNECT         1
#define RSP_RING            2
#define RSP_NO_CARRIER      3
#define RSP_ERROR           4
// There's one missing
#define RSP_NO_DIAL_TONE    6
#define RSP_BUSY            7
#define RSP_NO_ANSWER       8
#define RSP_CONNECT_50      9
#define RSP_CONNECT_75     10
#define RSP_CONNECT_110    11
#define RSP_CONNECT_150    12
#define RSP_CONNECT_200    13
#define RSP_CONNECT_300    14
#define RSP_CONNECT_600    15
#define RSP_CONNECT_1200   16
#define RSP_CONNECT_2400   17
#define RSP_CONNECT_3600   18
#define RSP_CONNECT_4800   19
#define RSP_CONNECT_7200   20
#define RSP_CONNECT_9600   21
#define RSP_CONNECT_12000  22
#define RSP_CONNECT_14400  23
#define RSP_CONNECT_19200  24
#define RSP_CONNECT_38400  25
#define RSP_CONNECT_48000  26
#define RSP_CONNECT_56000  27
#define RSP_CONNECT_64000  28
#define RSP_NONE           29

#define ERSP_NONE              0
#define ERSP_V110ASYN          1
#define ERSP_V110SYN           2
#define ERSP_V110SYNX25DTE     3
#define ERSP_V110SYNX25DCE     4
#define ERSP_V110SYNX25PADDTE  5
#define ERSP_V110SYNX25PADDCE  6
#define ERSP_V120ASYN          7
#define ERSP_V120SYN           8
#define ERSP_X25DTECSW         9
#define ERSP_X25DCECSW        10
#define ERSP_X25PADDTECSW     11
#define ERSP_X25PADDCECSW     12
#define ERSP_X25DTEPSW        13
#define ERSP_X25PADDTEPSW     14

#ifndef FOS_ISDN
	extern port_t *ports;
	extern incomingCallFilter_t incomingCallFilter[NUMBER_OF_FILTERS];
#endif

extern unsigned isdnIntNo;
extern unsigned number_of_ports;
extern void (interrupt cdecl far *old_clock_tick_ISR)();

unsigned apiSoftwareInterrupt(void);
void hangup(port_t *pport);
void hayesCONNECT(port_t *pport);
void emitResponseCode(port_t *pport);
void hayesAnswerCall(port_t *pport);
unsigned bytesFreeInBuffer(const charFarPtr_t head, const charFarPtr_t tail, unsigned size);
unsigned bytesUsedInBuffer(const charFarPtr_t head, const charFarPtr_t tail, unsigned size);
void purgeInputBuffer(port_t *pport);
int blockIntoRxBuf(port_t *pport, charFarPtr_t buffer, int size);
int blockFromTxBufNonDestructive(port_t *pport, charFarPtr_t buffer, int size);
void removeFromTxBuf(port_t *pport, unsigned byteCount);
void restartRxWhenReadyTo(port_t *pport);
void checkIncomingCall(void);
void checkAutoAnswer(port_t *pport);
void initializeIncomingData(port_t *pport);
void checkIncomingData(port_t *pport);
void checkOutgoingData(port_t *pport);
void checkCallState(port_t *pport);
void skipQueue(char charToSend, port_t *pport);
void defineIncomingCall(int onOrOff);
void executeHayes(port_t *pport);
void processHayesChar(port_t *pport, unsigned char txchar);
void interrupt far cdecl timer_isr(void);
int charIntoRxBuf(port_t *pport, unsigned ch);
void answerCall(port_t *pport);
void setupCall(port_t *pport);
int initialize(unsigned no_ports, unsigned minPortNo, unsigned rxBufKBytes, unsigned txBufKBytes);
void uninitialize(void);
void beginCriticalSection(void);
void endCriticalSection(void);
void releaseTimeSlice(void);
void pollIsdnDriver(port_t *pport);
void initializeLed(port_t *pport);
void resetModemEmul(port_t *pport);
void newlineRx(port_t *pport);

#ifdef ENABLE_LED
	void ledOn(port_t *pport, unsigned trigger);
	void ledOnNp(unsigned trigger);
	void ledOff(port_t *pport, unsigned trigger);
	void ledOffNp(unsigned trigger);
	void ledInvert(port_t *pport, unsigned trigger);
	void ledInvertNp(unsigned trigger);
#endif


#ifdef NDEBUG
	#define CLICK _asm{_asm in al,61h _asm xor al,2 _asm out 61h,al}
#endif

#ifdef ENABLE_LED
	#define LED_ON(t) ledOn(pport, t)
	#define LED_ON_NP(t) ledOn(ports, t)
	#define LED_OFF(t) ledOff(pport, t)
	#define LED_OFF_NP(t) ledOff(ports, t)
	#define LED_INVERT(t) ledInvert(pport, t)
	#define LED_INVERT_NP(t) ledInvert(ports, t)
#else
	#define LED_ON(t)
	#define LED_ON_NP(t)
	#define LED_OFF(t)
	#define LED_OFF_NP(t)
	#define LED_INVERT(t)
	#define LED_INVERT_NP(t)
#endif


// LED Trigger Numbers
#define LT_INITINCOMINGDATA  0xffff	// Function initializeIncomingData active
#define LT_ANSWERCALL        0xfffe	// Function answerCall active
#define LT_HANGUP            0xfffd	// Function hangup active
#define LT_INITCALLINFO      0xfffc	// Function initializeCallInfo active
#define LT_CHECKCALLSTATE    0xfffb	// Function checkCallState active
#define LT_CI_PENDING        0xfffa	// CALL_INFO: command pending
#define LT_CI_USERINFORECVD  0xfff9	// CALL_INFO: user info received
#define LT_CI_CHARGINGINFO   0xfff8	// CALL_INFO: charging info received
#define LT_CI_REMINDER       0xfff7	// CALL_INFO: reminder received
#define LT_CI_CALLCONNECTED  0xfff6	// CALL_INFO: call connected
#define LT_CI_CALLRELEASED   0xfff5	// CALL_INFO: call released
#define LT_CI_BCHANNELOOS    0xfff4	// CALL_INFO: B channel out of service
#define LT_CI_SUSPACK        0xfff3	// CALL_INFO: suspension acknowledged
#define LT_CI_SUSPREJ        0xfff2	// CALL_INFO: suspension rejected
#define LT_CI_RESACK         0xfff1	// CALL_INFO: resumption acknowledged
#define LT_CI_RESREJ         0xfff0	// CALL_INFO: resumption rejected
#define LT_CHECKAUTOANSWER   0xffef	// Function checkAutoAnswer active
#define LT_CHECKINCOMINGDATA 0xffee	// Function checkIncomingData active
#define LT_ID_BREAKRECVD     0xffed	// INCOMING_DATA: break received
#define LT_ID_STRINGRECVD    0xffec	// INCOMING_DATA: string received
#define LT_ID_PENDING        0xffeb	// INCOMING_DATA: command pending
#define LT_CHECKOUTGOINGDATA 0xffea	// Function checkOutgoingData active
#define LT_URGENTCHARSENT    0xffe9	// Urgent character has been sent
#define LT_TRANSMITLOOP      0xffe8	// Top of block transmission loop
#define LT_POSTPONINGTX      0xffe7	// Postponing transmission
#define LT_STRINGSENT        0xffe6	// Data string successfully sent
#define LT_TXFLOWCONTROL     0xffe5	// Transmission flow control
#define LT_SETUPCALL         0xffe4	// Function setupCall active
#define LT_ABORTINGSETUP     0xffe3	// Aborting setup due to incoming call
#define LT_HANGUPSETUP       0xffe2	// Hanging up before call setup
#define LT_SETUPOK           0xffe1	// Setup accepted
#define LT_POLLISDNDRIVER    0xffe0	// Function pollIsdnDriver active
#define LT_CHARINTOTXBUF     0xfeff	// Function charIntoTxBuf active
#define LT_CHARINTORXBUF     0xfefe	// Function charIntoRxBuf active
#define LT_CHARFROMRXBUF     0xfefd	// Function charFromRxBuf active
#define LT_BLOCKINTORXBUF    0xfefc	// Function blockIntoRxBuf active
#define LT_REMOVEFROMTXBUF   0xfefb	// Function removeFromTxBuf active
#define LT_BLOCKFROMTXBUFND  0xfefa	// Function blockFromTxBufNonDestructive active
#define LT_BLOCKFROMRXBUF    0xfef9	// Function blockFromRxBuf active
#define LT_BLOCKINTOTXBUF    0xfef8	// Function blockIntoTxBuf active
#define LT_RESTARTRXWHENRDY  0xfef7	// Function restartRxWhenReadyTo active
#define LT_SETBAUDRATE       0xfef6	// Function setBaudRate called
#define LT_TRANSMITCHAR      0xfef5	// Function transmitChar active
#define LT_RECVCHARWITHWAIT  0xfef4	// Function receiveCharWithWait
#define LT_REQUESTSTATUS     0xfef3	// Function requestStatus called
#define LT_STAT_RDA          0xfef2	// Input data is available in buffer
#define LT_STAT_OVRN         0xfef1	// The input buffer has been overrun
#define LT_STAT_THRE         0xfef0	// Room is available in the output buffer
#define LT_STAT_TSRE         0xfeef	// Output buffer is empty
#define LT_STAT_DCD          0xfeee	// Carrier detect
#define LT_INITIALIZEDRIVER  0xfeed	// Function initializeDriver called
#define LT_INITIALIZED       0xfeec	// Port is initialized
#define LT_DEINITIALIZEDRVR  0xfeeb	// Function deinitializeDriver called
#define LT_RAISEORLOWERDTR   0xfeea	// Function raiseOrLowerDTR called
#define LT_DTR               0xfee9	// Data Terminal Ready
#define LT_FLUSHOUTPUTBUF    0xfee8	// Function flushOutputBuffer active
#define LT_PURGEOUTPUTBUF    0xfee7	// Function purgeOutputBuffer called
#define LT_PURGEINPUTBUF     0xfee6	// Function purgeInputBuffer called
#define LT_NDREADAHEAD       0xfee5	// Function nonDestructiveReadAhead called
#define LT_READBLOCK         0xfee4	// Function readBlock active
#define LT_WRITEBLOCK        0xfee3	// Function writeBlock active
#define LT_INFOABOUTDRIVER   0xfee2	// Function informationAboutDriver called
#define LT_CHAININGTOBNU     0xfee1	// Chaining interrupt 14h to BNU
#define LT_FOSSILACTIVE      0xfee0	// Int 14h handler active
#define LT_INITIALIZE        0xfedf	// Function initialize active
#define LT_UNINITIALIZE      0xfede	// Function uninitialize active
#define LT_ISDNDRIVER        0xfdff	// Function isdnDriver active


#define LT_FOSSIL_ERROR      0x0100	// Malfunction of Int 14h handler
#define LT_SU_ERROR          0x0006	// SETUP: error
#define LT_OD_ERROR          0x0005	// OUTGOING_DATA: error returned
#define LT_ID_ERROR          0x0004	// INCOMING_DATA: unknown return code
#define LT_CC_ERROR          0x0003	// CHK_CALL: error returned
#define LT_CI_ERROR          0x0002	// CALL_INFO: unknown return code
#define LT_ISDNERROR         0x0001	// Error condition with/in ISDN driver


#ifdef ALPHA
	#define VERSION VERNUM "à"
#elif defined(BETA)
	#define VERSION VERNUM "á"
#elif defined(GAMMA)
	#define VERSION VERNUM "â"
#elif defined(RELEASE)
	#define VERSION VERNUM
#else
	#error Release status undefined
#endif
