/*
 * Copyright (c) 1987, 1988 by
 * PARALLAX GRAPHICS, INCORPORATED, Santa Clara, California.
 * All rights reserved
 *
 * This software is furnished on an as-is basis, and may be used and copied
 * only with the inclusion of the above copyright notice.
 *
 * The information in this software is subject to change without notice.
 * No committment is made as to the usability or reliability of this
 * software.
 *
 * Parallax Graphics, Inc.
 * 2500 Condensa Street
 * Santa Clara, California  95051
 */

/* Author:	Robert L. Goodwin
 * Author:	Martin J. Levy
 *		Parallax Graphics
 * Date:	Sept 87, June 88
 */

/* "@(#)plxreg.h	1.27 10/18/88 Parallax Graphics Inc" */

/* Model 1280 Hardware Registers */
struct plx_device {
        u_short csr;		/* command/status register */
        u_short cdr;		/* command/data register */
};

struct plx_wholedevice {
	struct plx_device plx;	/* graphics channel */
	struct plx_device vt;	/* terminal emulator */
	struct plx_device sa;	/* serial port A (mouse) */
	struct plx_device sb;	/* serial port B (kbd) */
};

/*
 * Constants for DELAY(), should be microseconds.
 */
#define	INTR_DELAY	10000		/* time to wait for probe interupt */
#define	INSTR_DELAY	10000		/* time to wait for an instruction */
#define	IOCLEAR_DELAY	100		/* time to wait for an ioclear */

#define	COLDSTART_INC	5			/* check 5 times a second */
#define	COLDSTART_COUNT	(COLDSTART_INC*10)	/* wait 10 seconds, overkill */

/* Display CSR bits */
#define CSR_DAV		0x0001
#define	CSR_WC		0x0002
#define CSR_WAC		0x0004
#define CSR_DE		0x0010
#define CSR_IP		0x0020
#define CSR_IE		0x0040
#define CSR_READY	0x0080
#define CSR_ERR_BITS	0x3f00
#define CSR_USER	0x4000
#define	CSR_ERROR	0x8000
#define CSR_RESET	0x8000
#define Error_Code(csr)	(((csr) & CSR_ERR_BITS) >> 8)

/*
 * Display CDR instructions
 */
#define	CDR_NOOP	0x0000		/* null operation */
#define	CDR_PIO		0x0028		/* return to pio mode from DMA */
#define	CDR_HDMA	0x0228		/* host assisted dma */
#define	CDR_JUMP	0x0129		/* Jump: addL,addH */ 
#define	CDR_JUMPB	0x0329		/* Jump Buffer:addL,addH,word count */
#define	CDR_SHOW	0x002c		/* read configuration */
#define	CDR_SHOW2	0x012c		/* read configuration (rev 7+ ) */
#define	CDR_RESET	0x002d		/* Hard Reset */
#define	CDR_STAT	0x002e		/* return a 1-word status in cdr */
#define	CDR_BSWAP	0x013c		/* Byte swap */
#define	CDR_VTASCII	0x063e		/* Start ASCII keyboard */
#define	CDR_VTGO	0x013e		/* Turn on VT220 Emulator */
#define	CDR_STOPVT220	0x003e		/* Turn off VT220 Emulator */
#define CDR_VTSTOP	0x003e		/* Turn off VT220 Emulator */
#define CDR_VTRESIZE	0x073e		/* Resize virtual terminal */
#define	CDR_VTCHAR	0x043e		/* Send char to Emulator */
#define	CDR_VTCOLOR	0x083e		/* Set emulator color */
#define	CDR_SETVEC	0x003f		/* new vector follows */
#define	CDR_SETDMA	0x013f		/* VME address mofifier next */
#define CDR_CLT8	0x0013 		/* Set 8 plane color table entry */
#define CDR_BOX		0x0004		/* draw a box on the screen */

#define	DMA_ADD_MOD	0x3d		/* Address Modifier for DMA cycles */

#define	CDR_SHOW_REV(s)	(((s)&0x003f) >>  0)	/* revision level */
#define	CDR_SHOW_OPT(s)	(((s)&0x03c0) >>  6)	/* option number */ 
#define	CDR_SHOW_HDW(s)	(((s)&0x1c00) >> 10)	/* hardware model # */ 
#define	CDR_SHOW_JPR(s)	(((s)&0xe000) >> 13)	/* hardware jumpers */ 

#define	CDR_SHOW_REL(s)	(((s)&0x000f) + 10*(((s)&0x00f0)>>4))	/* release # */

/*
 * VT220 codes
 */

#define VT_CSI		0x9b		/* Control sequence intro */
#define	VT_ESC		0x1b		/* 7 bit version */

/* Serial Port's CSR bits */

/* when read */
#define	SCSR_IP		0x0020
#define	SCSR_RXRDY	0x0100
#define	SCSR_TXRDY	0x0400
#define	SCSR_RXOVERRUN	0x1000
#define	SCSR_RXPARITY	0x2000
#define	SCSR_RXFRAME	0x4000
#define	SCSR_RXBREAK	0x8000
#define	SCSR_RXERROR	0xf000		/* all of above */

/* when written */
#define	SCSR_IE		0x0040
#define	SCSR_RESET	0x8000

#define	SCSR_TX75	0x0000
#define	SCSR_TX110	0x0100
#define	SCSR_TX134	0x0200
#define	SCSR_TX150	0x0300
#define	SCSR_TX300	0x0400
#define	SCSR_TX600	0x0500
#define	SCSR_TX1200	0x0600
#define	SCSR_TX2000	0x0700
#define	SCSR_TX2400	0x0800
#define	SCSR_TX4800	0x0900
#define	SCSR_TX7800	0x0a00
#define	SCSR_TX9600	0x0b00
#define	SCSR_RX75	0x0000
#define	SCSR_RX110	0x1000
#define	SCSR_RX134	0x2000
#define	SCSR_RX150	0x3000
#define	SCSR_RX300	0x4000
#define	SCSR_RX600	0x5000
#define	SCSR_RX1200	0x6000
#define	SCSR_RX2000	0x7000
#define	SCSR_RX2400	0x8000
#define	SCSR_RX4800	0x9000
#define	SCSR_RX7800	0xa000
#define	SCSR_RX9600	0xb000

#ifdef SUPPORT_INPUT
/* Mouse software register block */
typedef struct _plx_mouse {
	int lastbuttons;
	int phase;
	int lastx;
	int mthreshold;			/* threshold for mouse movement */
	int mscale;			/* and scale for mouse movement */
} plx_mouse;
#endif /* SUPPORT_INPUT */

/*
 * the present board start is kept here.
 */
typedef struct _plx_softc {
	u_int	plx_attached:1,		/* 1 == attached, else 0 */
		plx_open:1,		/* 1 == open, else 0 */
		plx_ints_on:1,		/* 1 == use interupts */
		plx_busy:1,		/* 1 == busy due to xfer */
		plx_ringbusy:1,		/* 1 == busy due to ring xfer */
		plx_termbusy:1,		/* 1 == busy due to terminal xfer */
		plx_error:1,		/* 1 == error occured on xfer */
		plx_timeout:1,		/* 1 == timeout occured on xfer */
		plx_timeron:1,		/* 1 == timer running */
		plx_x11mode:1,		/* 1 == ms,kbd in X11 mode */
                plx_suspendcons:1,	/* 1 == suspend any console activity */
		plx_ms_tracking:1;	/* 1 == ms in word mode */
	struct buf *plx_bp;		/* current buffer */
	int	plx_state;		/* tracks state machine phases */
	int	plx_xfermode;		/* PIO/DMA etc */
	int	plx_usermode;		/* KERNEL/USER etc */
	int 	plx_phase;		/* dma phase */
	int	plx_resetinprogress;	/* Don't touch registers yet */
	u_short	plx_count;		/* word count for xfer */
	u_short	plx_wcrem;		/* word count remainder */
#if defined(vax) || defined(sun) || defined(interactive) || defined(is68k) || defined(ibm032)
	u_long	plx_addr1;		/* {uba|mb}setup() for ring buffer */
	u_short *plx_pioaddr;		/* the real addr for user pio */
#endif /* vax || sun || interactive || is68k || ibm032 */
#ifdef xenix
	u_short	plx_mmuselect;		/* descriptor for mmu sector */
	u_short far *plx_pioaddr;	/* the real addr for user pio */
#endif /* xenix */
#if defined(sun) || defined(motorola131) || defined(is68k)
	int	plx_vector;		/* saved vector, used on coldstart */
#endif /* sun || motorola || is68k */
#ifdef SUPPORT_ATBUS
	int	plx_channel;		/* DMA channel */
	int	plx_8237busy;		/* DMA chip in use by us */
#endif
	u_long	plx_addr2;		/* {uba|mb}setup() for user dma */
	u_long	plx_dmaaddr;		/* the real addr for user dma */
	struct	plx_infobuf plx_info;	/* info buffer (model #, rev #) */
	struct	plx_errbuf plx_err;	/* error buffer */
#if defined(sun) || defined(vax) || defined(is68k) || defined(ibm032)
	struct proc 	*plx_rselect;	/* read select process */
	struct proc 	*plx_wselect;	/* write select process */
#endif /* sun || vax || is68k || defined(ibm032) */
#ifdef SUPPORT_RINGBUFFER
	struct plx_ring *plx_ring;	/* ring buffer header */
#endif
#ifdef SUPPORT_INPUT
	vsEventQueue	plx_ms_evq;	/* event queue header */
	vsCursor	plx_ms_ms;	/* mouse */
	vsBox		plx_ms_box;	/* mouse box */
	plx_mouse	plx_ms_soft;	/* state varibles for mouse */
#endif /* SUPPORT_INPUT */
#ifdef 	SUPPORT_PLXCONSOLE
	u_long		consopen;	/* Reference count on console */
#endif	SUPPORT_PLXCONSOLE
    } plx_softc;

/*
 * plx_softc plx_state definitions
 */
#define	PIO_READY	1
#define	PIO_WAIT	2
#define	DMA_WAIT	3
#define	DMA_READY	4
#define	USER_DMA_WAIT	5
#define	USER_PIO_WAIT	6
#define	STAT_WAIT	7
#define	WAIT_TO_STAT	8

/* 
 * For interpreting special file minor device numbers
 *
 *	*****************************************
 *	*    *    *    *    *    *    *    *    *
 *	*    UNIT NUMBER    * PLX or  *  A or B *
 *	*                   *   TTY   *   RESET *
 *	*****************************************
 */

#define	PLXUNIT(d)	((minor(d)&0xf0) >> 4)		/* display number */
#define PLXDEV(u,m)	((u << 4) + m)			/* "inverse" of above */

#define	OPEN_PLX(d)	((minor(d)&0x0c) == 0x00)	/* parallax stream */
#define	OPEN_RESET(d)	((minor(d)&0x03) == 0x03)	/* hard reset on open */

#define	OPEN_TTY(d)	((minor(d)&0x0c) == 0x04)	/* serial tty port */
    
#define	PLXTTYUNIT(d)	((minor(d)&0x03) >> 0)		/* tty port number */

#if defined(SUPPORT_PLXCONSOLE) && defined(vax)
#define OPEN_VT(d)	((major(d) == CONSOLEMAJOR && minor(d) == 0) \
			 ?1:((minor(d)&0x0c) == 0x08))
#else
#define	OPEN_VT(d)	((minor(d)&0x0c) == 0x08)	/* virtual terminal */
#endif /* SUPPORT_PLXCONSOLE */

#define	OPEN_SPARE(d)	((minor(d)&0x0c) == 0x0c)	/* spare */

#define	OPEN_FB(d)	((minor(d)&0x0f) == 0x0f)	/* sun framebuffer */

/*
 * for sun framebuffer code
 */

#ifdef SUPPORT_FRAMEBUFFER
#define	FBTYPE_PLXTYPE1		FBTYPE_NOTSUN1
#endif /* SUPPORT_FRAMEBUFFER */

/*
 * debug stuff
 */
#define PLXDEBUG

#ifdef PLXDEBUG
extern int plx_debugflag;
#define	dprintf if (plx_debugflag) printf
#else
#define	dprintf if (0) printf
#endif /* PLXDEBUG */

#ifdef SUPPORT_INPUT

#define	EVQSIZE	64				/* Input Event Queue */
/*
 * In these access macros, sc is a pointer to the plx_softc for this unit
 * It is assumed that the producer writes at "tail" and the consumer
 * reads from "head".
 */
#define	InputIsEmpty(sp)	((sp)->plx_ms_evq.head == (sp)->plx_ms_evq.tail)

#define	InputIsFull(sp)		((sp)->plx_ms_evq.tail+1 == (sp)->plx_ms_evq.head || \
				 ((sp)->plx_ms_evq.tail+1 == (sp)->plx_ms_evq.size && \
				 (sp)->plx_ms_evq.head == 0))

#define	LastInputIndex(sc)	(((sc)->plx_ms_evq.tail == 0) ? ((sc)->plx_ms_evq.size-1) : \
							 ((sc)->plx_ms_evq.tail-1))
#endif /* SUPPORT_INPUT */
