/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 *
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

#ident "$Header: xs.h 1.31 90/09/14 $"

#ifndef	_SYS_XS_H_

/*
 * xs.h
 *	Xylogics 781 16-port driver structure definitions.
 */

/* $Log:	xs.h,v $
 */

#ifdef INKERNEL
extern ushort xsrxtime;
extern int xsinputmin;
extern int xslowwater;
#endif

/* Mapping of 781 registers during reset and initialization. */

typedef struct xs_hardware {
	unchar f0;
	unchar low_rd_active;	/* Read active for ports 0-7 */
	unchar f1;
	unchar hi_rd_active;	/* Read active for ports 8-15 */
	unchar f2;
	unchar low_wr_active;	/* Write active for ports 0-7 */
	unchar f3;
	unchar hi_wr_active;	/* Write active for ports 8-15*/
	unchar f4;
	unchar cmd_report;	/* Command/report register */
	unchar f5;
 	unchar cntl_status;	/* 781 cntl/status register */
	unchar f6;
 	unchar port;		/* Port register */
} hardware_781;

/*
 * The 781 hardware registers have different functions at init time
 * and at runtime.  The following defines map the init registers into
 * the runtime register structure.
 */
#define idb_addr0	low_rd_active
#define idb_addr1	hi_rd_active
#define idb_addr2	low_wr_active
#define idb_addr3	hi_wr_active
#define idb_addr_mod	cmd_report
#define fatal_error	port

/*
 * 781 control register commands.  (Write only)
 */
#define XSCR_CRS	0x02		/* Clear Register Status */
#define XSCR_ARC	0x04		/* Add Register Control  */
#define XSCR_EMM 	0x20		/* Enter Maintenance Mode */
#define XSCR_MRST	0x40 		/* Module Reset */

/*
 * 781 status register values. (Read only)
 */
#define XSSR_FERR	0x01		/* Fatal Error */
#define XSSR_RSP	0x02		/* Register Status Pending */
#define XSSR_ARCP	0x04		/* Add Register Control Pending */
#define XSSR_MMA	0x20		/* Maint. Mode Active */
#define XSSR_RSTA	0x40		/* Reset Active */

/*
 * Command/Report register bits
 */
#define XSCR_RAC	0x01		/* Read Active/Complete */
#define XSCR_WAC	0x02		/* Write Active/Complete */
#define	XSCR_SYNC	0x04		/* Synchronous Active/Complete */

/*
 * Command/Report register report codes (non read/write) (781 to host)
 */
#define XSCR_PARITY	0x10		/* Parity Error */
#define XSCR_FRAME	0x20		/* Framing Error/Break */
#define XSCR_MODEM	0x30		/* Modem Change */
#define XSCR_INOVRR	0x40		/* Input Overrun */
#define XSCR_CMDERR	0x50		/* Command Error */
#define XSCR_ACCERR	0x60		/* Data Access Error */
#define XSCR_ACCTIME    0x70		/* Data Access Timeout Error */
#define XSCR_UARTOVF	0x80		/* Uart Overflow */
#define XSCR_INTQOVF	0x90		/* Internal Queue Overflow */
#define XSCR_RMASK	0xF0		/* Report code mask */
/*
 * Command/Report register commands (non read/write) (host to 781)
 */
#define XSCR_UINIT	0x10		/* Uart Init */
#define XSCR_FLUSH	0x20 		/* Flush Buffers */
#define XSCR_RESET	0x30		/* Reset Port */
#define XSCR_MSET	0x40		/* Modem Set Parameters */
#define XSCR_MGET	0x50		/* Modem Get Parameters */
#define XSCR_BREAK	0x60		/* Send Break */
#define XSCR_ELGET	0x70		/* Error Log Get */
#define XSCR_XON	0x90		/* Unsuspend output */
#define XSCR_XOFF	0xA0		/* Suspend output */
#define XSCR_BREAKON	0xB0		/* Start Break */
#define XSCR_BREAKOFF	0xC0		/* Stop Break */

/*
 * 781 uart parameter blocks (1 per port)    Pointed to by idb.
 */
typedef struct uparms {
	ushort serial_modes;		/* Port stop bits, parity, bits, flow */
	ushort baud_rates;		/* Output/Input baud rates */
	ushort line_state;		/* Modem line state info */
	ushort line_mask;		/* Ignore status lines, dis/enable RX */
	ushort input_timeout;		/* Input timeout value */
	ushort input_min;		/* Minimum # of chars expected by host*/
	char xoff_char;			/* XOFF character */
	char xon_char;			/* XON character */
	ushort low_water;		/* Output buffer low water mark */
	ushort break_time;		/* Duration of break (in 5ms ticks) */
	ushort reserved3;		/* Reserved space */
	ushort reserved4;		/* Reserved space */
	ushort parerr_cnt;		/* Parity error count */
	ushort framerr_cnt;		/* Framing error count */
	ushort ovflow_cnt;		/* Overflow error count */
	ushort reserved5;		/* Reserved space */
	ushort reserved6;		/* Reserved space */
} uparms_781;

/*
 * Values used to set uart parameters
 */

/* Line mode values for uparms.serial_modes */
#define XS_STOP1		0x4000    /* 1 stop bit */
#define XS_STOP1P5		0x8000	  /* 1.5 stop bits */
#define XS_STOP2		0xC000	  /* 2 stop bits */
#define XS_NO_PARITY		0x0000    /* No parity */
#define XS_ODD_PARITY		0x1000	  /* Odd parity */
#define XS_EVEN_PARITY		0x3000	  /* Even parity */
#define XS_BITS5                0x0000    /* 5 bits per character */
#define XS_BITS6		0x0400	  /* 6 bits per character */
#define XS_BITS7		0x0800    /* 7 bits per character */
#define XS_BITS8		0x0C00    /* 8 bits per character */
#define XS_NO_FLOW		0x0000	  /* No flow control */
#define XS_HW_FLOW		0x0100	  /* Hardware flow control */
#define XS_SW_FLOW		0x0200	/* XON/XOFF flow control */

/* Baud rate values for uparms.baud_rates */
#define XSB_50			0x00	/* 50 baud */
#define XSB_75			0x01	/* 75 baud */
#define XSB_110			0x02	/* 110 baud */
#define XSB_134P5		0x03	/* 134.5 baud */
#define XSB_150			0x04	/* 150 baud */
#define XSB_300			0x05	/* 300 baud */
#define XSB_600			0x06	/* 600 baud */
#define XSB_1200		0x07	/* 1200 baud */
#define XSB_1800 		0x08	/* 1800 baud */
#define XSB_2000		0x09	/* 2000 baud */
#define XSB_2400		0x0A	/* 2400 baud */
#define XSB_3600		0x0B    /* 3600 baud */
#define XSB_4800		0x0C	/* 4800 baud */
#define XSB_7200		0x0D	/* 7200 baud */
#define XSB_9600		0x0E	/* 9600 baud */
#define XSB_19200		0x0F	/* 19.2K baud */


/* Values for setting line state with uparms.line_state and uparms.line_mask */
#define XSLINE_RTS		0x0100	/* RTS */
#define XSLINE_DTR		0x0200  /* DTR */
#define XSLINE_DCD		0x2000  /* DCD */
#define XSLINE_CTS		0x4000  /* CTS */
#define XSLINE_DSR		0x8000  /* DSR */

#define XS_IENABLE		0x0100    /* Input Enable bit */
#define XS_UNI			0x1000	  /* UNIdirectional handshake*/
#define XS_MCU			0x0200	  /* modem change update ON */


/*
 * 781 Initialization Descriptor Block structure
 */
typedef struct xs_idb {
	ushort icba_hi;		/* Input char buffer array addr msb */
	ushort icba_lo;		/* Input char buffer array addr lsb */
	ushort inbuf_len;		/* Length of input data buffers */
	ushort ocrba_hi;		/* Output char ring buf array addr msb*/
	ushort ocrba_lo;		/* Output char ring buf array addr lsb*/
	ushort outbuf_len;		/* Length of output data buffers */
	ushort addr_mod;		/* Addr modifier for both buffers */
	ushort inp_intvec;		/* Input interrupt vector */
	ushort inp_intlev;		/* Input interrupt level */
	ushort out_intvec;		/* Output interrupt vector */
	ushort out_intlev;		/* Output interrupt level */
	ushort stat_intvec;		/* Status interrupt vector */
	ushort stat_intlev;		/* Status interrupt level */
	uparms_781 uart_parms[16];/* Uart parameters for ports 0-15 */
} idb_781;

#define XS_DMA_AMOD	0x0d		/* 781 VME data transfer addr mod */
#define XS_CSR_AMOD	0x2d		/* 781 VME CSR addr modifier */
#define XS_VME_INTVEC	1		/* 781 VME interrupt vector base */
#define OBUFSIZE 	2048		/* 2k output buffer size */
#define XSMAPSREQ	  17		/* Number of VME maps needed */
#define OBUFSIZEDEC	(OBUFSIZE - 1)	/* Mask for wrapping PUT index */
#define IBUFSIZE	1024		/* 1k input buffer size */
#define XSLOWWATER	(OBUFSIZE / 2)  /* Output low water mark */
#define	MAXPORTS	  16		/* 16 ports per 781 board */
/*
 * 781 Output Character Ring Buffer Element (1 per port)
 */
typedef struct outbuf {
	short get;			/* GET index pointer */
	short put;			/* PUT index pointer */
	char buffer[OBUFSIZE];		/* DATA area */
} outbuf_781;
/*
 * Output Character Ring Buffer Element array (1 per 781 board)
 */
typedef struct outbuf_array {
	outbuf_781 obufs[MAXPORTS];
} outbuf_array_781;


/*
 * 781 Input Character Buffer Element (1 per port)
 */
typedef struct inbuf {
	short	count;
	char	data[IBUFSIZE];
} inbuf_781;

/*
 * Input Character Buffer Element array (1 per 781 board)
 */
typedef struct inbuf_array {
	inbuf_781 ibufs[MAXPORTS];
} inbuf_array_781;

/*
 * Per-port info structure.
 *
 * Note: the t_ttylock guarantees protected access to the uart parameters
 *       and other per-port info structures.  The only requirement is that
 *       the 781 MUST BE IDLE before writing locations such as the uart
 *       params.  A previous process may have written to the uart params
 *	 area but the 781 may still be reading the data.
 */

struct xsstrtty	{
	queue_t	*qptr;			/* Local streams queue(wr)*/
	int 	t_cmask;		/* Carrier detect mask */
	uint	t_flags;		/* flags from st config file */
	dev_t	t_dev;			/* Device number */
	lock_t	t_ttylock;		/* Line structure lock */
	sema_t	t_rawqwait;		/* Carrier wait sema */
	uint	t_state;		/* Current state of device */
	ushort	t_cflags;		/* Flags from termio c_cflags */
	unchar	t_flow;			/* delayed stop/start character */
	mblk_t	*msg;			/* Current output message */
	uint	t_bufcallid;		/* Bufcall ID */
	int	t_delayid;		/* Output delay timeout id */
	int	t_breakid;		/* Break duration timeout id */
};

/*
 * State bits for t_state.
 */
#define XS_TXDELAY 	0x001
#define XS_ISOPEN	0x002
#define XS_WOPEN	0x004
#define XS_WCLOSE  	0x008
#define XS_CARR_ON	0x010
#define XS_TX_FULL	0x020
#define XS_DRAINTIME 	0x040
#define XS_SUSPOUT 	0x080
#define XS_WIOCTL  	0x100
#define XS_TXBREAK	0x200
#define XS_TX_BUSY	0x400
#define XS_DATASUSP	0x800

/*
 * Flag bits for t_flags.
 */
#define XS_DISCARDIN    0x001
#define XS_SYNCREQ	0x002
#define XS_RDBLOCKED	0x004
#define XS_FLOW		0x008

/*
 * 781 driver per-board info structure
 *
 * note: xs_lock allows protected access to the 781 board and its registers.
 *       However, the user process must be sure to check the ARCP bit before
 *       writing to the 781 registers.  This is because another process may
 *       have started a command to the 781, released the lock, and the 781
 *       is still in the process of latching the command.  So, MAKE SURE THE
 *       BOARD IS IDLE BEFORE WRITING TO ITS REGISTERS.
 */
struct xsinfo {
	struct gen_device       *dev_ptr;
	int			first_map;
	hardware_781    	*xs_addr;
	idb_781			*idb;
	inbuf_array_781 	*xs_inbufs;
	outbuf_array_781	*xs_outbufs;
	lock_t			xs_lock;
	int			n_maps;
	struct xsstrtty		xs_strtty[16];
	ulong			xs_cflags;
	int 			boardnum;
};

/*
 * Macros for extracting line # and board # from dev #
 */
#define XSLINE(x)	(minor((x)) & 0x0f)
#define XSBOARD(x)	(minor((x)) >> 4)

/*
 * Macro for clearing 781 hardware register holding structure
 */
#define XS_CLEAR(xshw)					\
	{						\
	(xshw).low_rd_active = 0;		\
	(xshw).hi_rd_active  = 0;		\
	(xshw).low_wr_active = 0;		\
	(xshw).hi_wr_active  = 0;		\
	(xshw).cmd_report    = 0;		\
	(xshw).port          = 0;		\
	}
/*
 * Macro for reading values in 781 hardware registers
 */
#define XS_LOAD(ip, xsregs)				\
	{						\
	xsregs.low_rd_active = (ip)->xs_addr->low_rd_active; \
	xsregs.hi_rd_active =  (ip)->xs_addr->hi_rd_active; \
	xsregs.low_wr_active = (ip)->xs_addr->low_wr_active; \
	xsregs.hi_wr_active  = (ip)->xs_addr->hi_wr_active; \
	xsregs.cmd_report    = (ip)->xs_addr->cmd_report; \
	xsregs.port          = (ip)->xs_addr->port; \
	}
/*
 * Macros for determining state of 781 output buffers
 */

/* Access output buffer PUT pointer for a given line */
#define XS_PUT(ip, line)  ((ip)->xs_outbufs->obufs[(line)].put)

/* Access output buffer GET pointer for a given line */
#define XS_GET(ip, line)  ((ip)->xs_outbufs->obufs[(line)].get)

/* How much space (in chars) is left in the output buffer (allows wrapping) */
#define XS_OUTBUF_SPACE(get, put)	\
	(((((get) - (put) - 1) >= 0) && ((put) != 0)) ? (get) - (put) - 1 : \
	(get) - (put) - 1 + OBUFSIZE)
/* Is the output buffer empty? */
#define XS_OUTBUF_EMPTY(ip, line)  \
	(((vtoss(XS_PUT((ip), (line))) + 1) & OBUFSIZEDEC) == vtoss(XS_GET((ip), (line))))

/* Is the output buffer full? */
#define XS_OUTBUF_FULL(ip, line)   \
	(((vtoss(XS_PUT((ip),(line))) + 2) & OBUFSIZEDEC) == vtoss(XS_GET((ip),(line))))

/* Move the PUT pointer forward and report on whether the buffer was empty */
#define XS_OUTBUF_ADD(ip, line, count)	\
	(XS_PUT((ip), (line)) = ((XS_PUT((ip), (line)) + (count)) & OBUFSIZEDEC));

/* Return address of output buffer indexed by put + 1 (next write location) */
#define XS_PUT_ADDR(ip, line)	\
	(&(ip)->xs_outbufs->obufs[(line)].buffer[((vtoss(XS_PUT((ip),(line))) + 1) & OBUFSIZEDEC)])

#define TRUE		1
#define FALSE		0
#define XS_AVGCNT	5		/* Guessed avg # of bytes in a data msg */
#define XS_STDPUTBACK	1
#define XS_PRIPUTBACK	2

/* macro stovs does a AB to BA byte swap on a 16-bit value. */
/* this is required since the 781 swaps 16-bit values.. We  */
/* must compensate for this. macro vtoss does the same thing */
/* as stovs, but is included so the code reads easily.       */

#define vtoss(x) stovs(x)

#ifdef lint
#define stovs(arg) (((arg) & 0xff) << 8 | ((arg) >> 8 & 0xff))
#else
asm stovs(arg)
{
%con	arg;
/PEEPOFF
	xorl	%eax, %eax
/PEEPON
	movw	arg,%eax
	xchgb	%ah, %al
%reg	arg;
	mov	arg,%eax
	xchgb	%ah, %al
%mem	arg;
	movzwl	arg, %eax
	xchgb	%ah, %al
}
#endif


#define	_SYS_XS_H_
#endif	/* _SYS_XS_H_ */
