#ifndef _SCC_H
#define _SCC_H

/* Definitions for Z8530 SCC driver by PE1CHL
 * Adapted for NOS 1/23/90
 * Ken Mitchum KY3B
 * km@speedy.cs.pitt.edu
 * km@cadre.dsl.pitt.edu
 */
#ifndef _MBUF_H
#include "mbuf.h"
#endif

#ifndef _IFACE_H
#include "iface.h"
#endif

#define INLINE 1

typedef int16 ioaddr;	/* type definition for an 'io port address' */
#ifndef MAXSCC
#define MAXSCC	4	/* maximal number of SCC chips supported
			 *
			 * NOTE: 15 chips is an absolute maximum with
			 * the current interrupt handler
			 */
#endif
#if MAXSCC > 15
#error MAXSCC must not exceed 15
#endif

#define TPS	(1000/MSPTICK)	/* scctim() ticks per second */

#if defined(INLINE)
/* special delay construction only necessary when inline IN/OUT is used */
#define D(v)		scc_delay(v)		/* delay for 5 PCLK cycles (or more) */
#define RDREG(a)	(D(inportb(a)))		/* read any input port */
#define WRREG(a,v)	{outportb(a,v); D(1);}	/* write any output port */
#define RDSCC(c,r)	(outportb(c,r), D(1), D(inportb(c)))		/* read SCC reg */
#define WRSCC(c,r,v)	{outportb(c,r); D(1); outportb(c,v); D(1);}	/* 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 HWEAGLE		0x01	/* hardware type for EAGLE card */
#define HWPC100		0x02	/* hardware type for PC100 card */
#define HWPRIMUS	0x04	/* hardware type for PRIMUS-PC (DG9BL) card */
#define HWDRSI		0x08	/* hardware type for DRSI PC*Packet card */
#define HWBAYCOM	0x10	/* hardware type for the Baycom modem */

#ifndef VOID
#define VOID(x)	(x)	/* not necessary for most compilers */
#endif

struct sccboard {
	char *name;		/* Label for the board */
	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 */
	long clk;		/* PCLK/RTxC frequency in Hz */
	int pclk;		/* flag to use PCLK (instead of RTxC) */
	int hwtype;		/* special hardware type indicator */
	int hwparam;		/* special hardware parameter */
	struct sccboard *next;	/* pointer to next board */
};

/* SCC channel control structure for AX.25 mode */
struct scca {
	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 txdelay;	/* Transmit Delay 10 ms/cnt */
	unsigned char persist;	/* Persistence (0-255) as a % */
	unsigned char slottime;	/* Delay to wait on persistence hit */
	unsigned char tailtime;	/* Delay after XMTR OFF */
	unsigned char fulldup;	/* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
	unsigned char waittime;	/* Waittime before any transmit attempt */
	unsigned char maxkeyup;	/* Maximum time to transmit (seconds) */
	unsigned char mintime;	/* Minimal offtime after MAXKEYUP timeout */
	unsigned char idletime;	/* Maximum idle time in ALWAYS KEYED mode (seconds) */
	unsigned char flags;	/* Config Options */
#define SCC_FLAG_SWDCD 1

};

/* 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)
	 * i.e. "ctrl" must be the next item after the interrupt handlers
	 */
	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 fifo fifo;
	struct scca a;		/* control structure for AX.25 use */

	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 */

	struct iface *iface;	/* associated interface structure */

	int bufsiz;

	unsigned int timercount;	/* ticker timer counts 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 when another channel asserting PTT */
#define TX2GROUP	0x400	/* if set, don't transmit when another channel prepared to */

	long speed;		/* Line speed, bps */
	char extclock;		/* External clock source on RTxC/TRxC */
	char fulldup;		/* External divider for fulldup available */
	char tx_inhibit;	/* Transmit is not allowed when set */
	char nrz;		/* Use NRZ rather than NRZI */

	/* 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 */
	unsigned int tunders;	/* Transmitter Underruns */

	struct sccboard *card;	/* Board this channel is on */
	char escc;		/* Chip is ESCC rather than SCC */
	char reg_11;		/* User provided R11 contents to write */
};
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)))

#endif	/* _SCC_H */
