/* Definitions for Z8530 SCC driver */
/* Initially for Atari ST - Goal is to replace all Z8530 drivers */

#ifdef ATARI_ST
typedef unsigned char *ioaddr;	/* type definition for an 'io port address' */
#define MAXSCC		7	/* maximal number of SCC chips supported */
#define TPS		100	/* scctim() ticks per second (10ms) */
#define RDREG(a)	(*(a))		  /* read any input port */
#define WRREG(a,v)	*(a) = v	  /* write any output port */
#define RDSCC(c,r)	(*c = r, *c)	  /* read SCC register */
#define WRSCC(c,r,v)	{*c = r; *c = v;} /* write SCC register */

#ifdef __TURBOC__
static unsigned char dummy;
#define VOID(x)		dummy = (x)	/* discard a value */
#endif
#endif

#ifdef MSDOS
typedef int16 ioaddr;		/* type definition for an 'io port address' */
#define MAXSCC		6	/* maximal number of SCC chips supported */
#define TPS		sccinfo.tps	/* scctim() ticks, # is variable */
# if ((defined(MSC) && defined(INLINE)) || (defined(__TURBOC__) && defined(inportb)))
/* special delay construction only necessary when inline IN/OUT is used */
#define RDREG(a)	(scc_delay(inportb(a))) /* read any input port */
#define WRREG(a,v)	{outportb(a,v); scc_delay();} /* write any output port */
#define RDSCC(c,r)	(outportb(c,r), scc_delay(), scc_delay(inportb(c))) /* read SCC reg */
#define WRSCC(c,r,v)	{outportb(c,r); scc_delay(); outportb(c,v); scc_delay();} /* write SCC reg*/
# else
#define RDREG(a)	(inportb(a))		/* read any input port */
#define WRREG(a,v)	{outportb(a,v);}	/* write any output port */
#define RDSCC(c,r)	(outportb(c,r), inportb(c)) /* read SCC reg */
#define WRSCC(c,r,v)	{outportb(c,r); outportb(c,v);} /* write SCC reg */
# endif

#define EAGLE		0x01	/* hardware type for EAGLE card */
#define PC100		0x02	/* hardware type for PC100 card */
#define PRIMUS		0x04	/* hardware type for PRIMUS-PC (DG9BL) card */
#define DRSI		0x08	/* hardware type for DRSI PC*Packet card */
#endif

#ifndef VOID
#define VOID(x)		(x)	/* not necessary for most compilers */
#endif

struct sccinfo {
	int init;		/* SCC driver initialized? */
	int nchips;		/* Number of SCC chips in system */
	int maxchan;		/* Highest valid channel number */
	ioaddr iobase;		/* Base address of first SCC */
	int space;		/* Spacing between subsequent SCCs */
	int off[2];		/* Offset to A and B channel control regs */
	int doff;		/* Offset from control to data register */
	int ivec;		/* System interrupt vector number */
	long clk;		/* PCLK/RTxC frequency in Hz */
	int pclk;		/* flag to use PCLK (instead of RTxC) */
	unsigned int hwtype;	/* special hardware type indicator */
	int hwparam;		/* special hardware parameter */
#ifdef MSDOS
	unsigned int tps;	/* Timer interrupt frequency in Hz, when variable */
	unsigned long ticks;	/* Timer ticks since startup */
#endif
};
extern struct sccinfo sccinfo;

/* SCC channel control structure for AX.25 mode */
struct scca {
	struct mbuf *rbp;	/* Head of mbuf chain being filled */
	struct mbuf *rbp1;	/* Pointer to mbuf currently being written */

	struct mbuf *sndq;	/* Encapsulated packets awaiting transmission */
	struct mbuf *tbp;	/* Transmit mbuf being sent */

	unsigned int maxdefer;	/* Timer for CSMA defer time limit */

	unsigned int tstate;	/* Transmitter state */
#define IDLE		0	/* Transmitter off, no data pending */
#define DEFER		1	/* Receive Active - DEFER Transmit */
#define KEYUP		2	/* Permission to keyup the transmitter */
#define KEYWT		3	/* Transmitter switched on, waiting for CTS */
#define ACTIVE		4	/* Transmitter on, sending data */
#define FLUSH		5	/* CRC sent - attempt to start next frame */
#define TAIL		6	/* End of transmission, send tail */

	unsigned char params[11]; /* Channel control parameters */
#define TXDELAY		1	/* Transmit Delay 10 ms/cnt */
#define PERSIST		2	/* Persistence (0-255) as a % */
#define SLOTTIME	3	/* Delay to wait on persistence hit */
#define TAILTIME	4	/* Delay after XMTR OFF */
#define FULLDUP		5	/* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
#define TNCSPECIF	6	/* reserved for KISS-TNC-specific parameters */
#define WAITTIME	7	/* Waittime before any transmit attempt */
#define MAXKEYUP	8	/* Maximum time to transmit (seconds) */
#define MINTIME		9	/* Minimal offtime after MAXKEYUP timeout */
#define IDLETIME	10	/* Maximum idle time in ALWAYS KEYED mode (seconds) */
};

/* SCC channel structure. one is allocated for each attached SCC channel, */
/* so 2 of these are allocated for each fully utilized SCC chip */
struct sccchan {
	/* interrupt handlers for 4 different IP's */
	/* MUST BE first 4 elements of this structure, and MUST remain */
	/* in the sequence Transmit-Status-Receive-Special */
	void (*int_transmit)(); /* Transmit Buffer Empty interrupt handler */
	void (*int_extstat)();	/* External/Status Change interrupt handler */
	void (*int_receive)();	/* Receive Character Avail. interrupt handler */
	void (*int_special)();	/* Special Receive Condition interrupt handler */

	/* don't insert anything before "ctrl" (see assembly interrupt handler) */
	ioaddr ctrl;		/* I/O address of CONTROL register */
	ioaddr data;		/* I/O address of DATA register for this channel */

	unsigned char wreg[16]; /* Copy of last written value in WRx */
	unsigned char status;	/* Copy of R0 at last external interrupt */
	unsigned char txchar;	/* Char to transmit on next TX interrupt */

	struct interface *iface;/* associated interface structure */
	struct mbuf *rqueue;	/* queue of received frames ready to process */
	void (*recv)();		/* function to call to process these */
	unsigned int timercount;/* 10ms timer for AX.25 use */
	int group;		/* group ID for AX.25 TX interlocking */
#define NOGROUP		0	/* not member of any group */
#define RXGROUP		0x100	/* if set, only tx when all channels clear */
#define TXGROUP		0x200	/* if set, don't transmit simultaneously */

	union {
		struct slip s;	/* control structure for SLIP use */
		struct scca a;	/* control structure for AX.25 use */
	} c;

	long speed;		/* Line speed, bps */
	int flags;		/* Clockmode/special flags, see below */
#define DIVIDER		0x01	/* External /32 divider for fulldup available */
#define EXTCLOCK	0x02	/* External clock source on RTxC/TRxC */
#define TX_INHIBIT	0x80	/* Transmit is not allowed when set */

	/* statistic information on this channel */
	long rxints;		/* Receiver interrupts */
	long txints;		/* Transmitter interrupts */
	long exints;		/* External/status interrupts */
	long spints;		/* Special receiver interrupts */

	long enqueued;		/* Packets actually forwarded */
	long rxframes;		/* Number of Frames Actally Received */
	long rxerrs;		/* CRC Errors or KISS errors */
	unsigned int nospace;	/* "Out of buffers" */
	unsigned int rovers;	/* Receiver Overruns */
};
extern struct sccchan *sccchan[];
#define NULLCHAN	(struct sccchan *)0

/* Z8530 SCC Register access macros */

#define rd(scc,reg)	RDSCC((scc)->ctrl,(reg))
#define wr(scc,reg,val) WRSCC((scc)->ctrl,(reg),((scc)->wreg[reg] = val))
#define or(scc,reg,val) WRSCC((scc)->ctrl,(reg),((scc)->wreg[reg] |= val))
#define cl(scc,reg,val) WRSCC((scc)->ctrl,(reg),((scc)->wreg[reg] &= ~(val)))

