/* @(#)cg2reg.h 1.11 88/02/08 SMI */

/*
 * Copyright 1983, 1987 by Sun Microsystems, Inc.
 */

#ifndef	cg2reg_DEFINED
#define	cg2reg_DEFINED

/*
 * cg2 -- color frame buffers with rasterop chips
 *
 * The frame buffer address space looks like this:
 *
 * 0x000000	plane mode memory
 * 0x100000	pixel mode memory
 * 0x200000	rop mode memory
 * 0x300000	control registers
 * 0x310000	color map
 *
 * To save on virtual address space, we don't map the plane or pixel mode
 * memory (first two megabytes).  However, when calling mmap the user has
 * to add 2M to the desired offset anyway (goofy, huh?).
 *
 * The board can also be jumpered so the plane and pixel mode memory are
 * not accessible at all, and the rop mode memory and control registers
 * are decoded starting at address offset 0.
 */

/* offset to and size of mapped part of frame buffer */
#define	CG2_MAPPED_OFFSET	(sizeof (struct cg2memfb))
#define	CG2_MAPPED_SIZE		(sizeof (struct cg2fb))

/* interrupt priority */
#define	CG2_INT_PRI	4

/* frame buffer resolution constants */
#define CG2_WIDTH	1152
#define CG2_HEIGHT	900
#define CG2_SQUARE	1024
#define CG2_DEPTH	8

/* 
 * Structure describing plane and pixel mode memory -- pretty useless
 * since we don't map that part of the frame buffer.
 */
struct	cg2memfb {
	union bitplane {			/* word mode memory */
		short word[CG2_HEIGHT][CG2_WIDTH/(8*sizeof(short))];
		short sword[CG2_SQUARE][CG2_SQUARE/(8*sizeof(short))];
	} memplane[8];
	union byteplane {			/* pixel mode memory */
		u_char pixel[CG2_HEIGHT][CG2_WIDTH];
		u_char spixel[CG2_SQUARE][CG2_SQUARE];
	} pixplane;
};

/* control/status register */
struct cg2statusreg {
	u_int unused : 2;	/* reserved for future use */
	u_int fastread : 1;	/* has fast read feature */
	u_int id : 1;		/* has ID, extended status registers */
	u_int resolution : 4;	/* screen resolution */
#define	CG2_SCR_1152X900	0
#define	CG2_SCR_1024X1024	1
#define	CG2_SCR_1600X1280	2
#define	CG2_SCR_1440X1440	3
	unsigned retrace : 1;	/* rdonly: monitor in retrace */
	unsigned inpend  : 1;	/* rdonly: interrupt pending */
	unsigned ropmode : 3;	/* Rasterop mode */
	unsigned inten   : 1;	/* enab interrupt at end of retrace */
	unsigned update_cmap : 1;
			/* copy TTL cmap to ECL cmap next vert retrace*/
			/* silently disables writing to TTL cmap */
	unsigned video_enab  : 1;	/* enab video DACs */
};

/* extended status register */
struct cg2_status2 {
	u_int gpintreq : 1;	/* GP interrupt request */
	u_int gpintdis : 1;	/* GP interrupt disable */
	u_int unused : 13;	/* reserved for future use */
	u_int gpbus : 1;	/* GP bus enabled (read only) */
};

/* double buffering control register */
struct dblbufreg {
	u_int display_b : 1;	/* Display memory set B or A. */
			/* Synchronized to start of vertical retrace. */
	u_int read_b : 1;	/* Read memory set B or A. */
	u_int nowrite_b : 1;	/* Do not update memory set B on writes. */
	u_int nowrite_a : 1;	/* Do not update memory set A on writes. */
	u_int read_ecmap : 1;/* ECL to TTL cmap transfer direction. */
			/* Synchronized to start of Vertical retrace. */
	u_int fast_read : 1; /* Return invalid data but fast Dtack on read */
	u_int wait : 1;	/* Write a '1' to set.  Bit will remain */
			/* high until a full vertical retrace period has */
			/* elapsed.  The bit clears itself. */
	u_int update_ecmap : 1;
	u_int reserved : 8;
};

/* zoom/pan registers; Sun-2 color board only */
struct cg2_zoom {
	union {				/*----- word pan register */
		unsigned short reg;		/* hi 16 of 20 bit pix addr */
						/* pix addr = CG2_WIDTH*y+x */
		char pad[4096];
	} wordpan;
	union {				/*----- zoom and line offset register */
		struct {
		    unsigned unused  : 8;
		    unsigned lineoff : 4;	/* y offset into zoomed pixel */
		    unsigned pixzoom : 4;	/* zoomed pixel size - 1 */
		} reg;
		short word;
		char pad[4096];
	} zoom;
	union {				/*----- pixel pan register */
		struct {
		    unsigned unused   : 8;
		    unsigned lorigin  : 4;	/* lo 4 bits of pix addr   */
		    unsigned pixeloff : 4;	/* zoomed pixel x offset/4 */
		} reg;
		short word;
		char pad[4096];
	} pixpan;
	union {				/*----- variable zoom register */
						/* reset zoom after line no */
		unsigned short reg;		/* line number 0..1024/4  */
		char pad[4096];
	} varzoom;
};

/* misc. control registers; Sun-3 color board etc. */
struct cg2_nozoom {
	union {				/*----- double buffering register */
		struct dblbufreg reg;
		short word;
		char pad[4096];
	} dblbuf;
	union {				/*----- dma window origin register */
		unsigned short reg;
		char pad [4096];
	} dmabase;
	union {				/*----- dma window width register */
		unsigned short reg;		/* reg * 16 specifies width */
		char pad [4096];		/* of dma window.  8 bit. */
	} dmawidth;
	union {				/*----- frame count register */
		unsigned short reg;		/* 8 bit. Read-only. */
			/* Returns frame number mod 256. */
		char pad[4096];
	} framecnt;
};

/* structure describing mapped part of frame buffer */
struct cg2fb {
	union {					/* ROP mode memory */
		union bitplane ropplane[8];	/* word mode memory with ROP */
		union byteplane roppixel;	/* pixel mode memory with ROP */
	} ropio;
	union {					/* rasterop unit control */
		struct memropc ropregs;		/* normal register access */
		struct {
			char pad[2048];		/* for pixmode src reg prime */
			struct memropc ropregs;	/* byte xfer loads alternate */
		} prime;			/* src register bits */
		char pad[4096];
	} ropcontrol[9];
	union {				/*----- status register */
		struct cg2statusreg reg;
		short word;
		char pad[4096];
	} status;
	union {				/*----- per plane mask register */
		unsigned short reg;		/* 8 bits 1bit -> wr to plane*/
		char pad[4096];
	} ppmask;
	union {
		struct cg2_zoom zoom;
		struct cg2_nozoom nozoom;
	} misc;
	union {				/*----- interrupt vector register */
		unsigned short reg;		/* line number 0..1024/4  */
		char pad[32];
	} intrptvec;
	union {				/* board ID */
		u_short reg;
		char pad[16];
	} id;
	union {				/* extended status */
		struct cg2_status2 reg;
		u_short word;
		char pad[16];
	} status2;
	union {				/* auxiliary ropmode register */
		u_short reg;
		char pad[4032];
	} ropmode;
	u_short redmap[256];			/* shadow color maps */
	u_short greenmap[256];
	u_short bluemap[256];
};

/*
 *	ROPMODE		    PARALLEL	     LD_DST  LD_SRC   Description
 *					       ON      ON		*/
#define	PRWWRD	0	/* parallel 8 plane,  read    write,	wrdmode */
#define	SRWPIX	1	/* single     pixel,  read    write, 	pixmode */
#define	PWWWRD	2	/* parallel 8 plane,  write   write,	wrdmode */
#define	SWWPIX	3	/* single     pixel,  write   write,	pixmode */
#define	PRRWRD	4	/* parallel 8 plane,  read    read,	wrdmode */
#define	PRWPIX	5	/* parallel16 pixel,  read    write,	pixmode */
#define	PWRWRD	6	/* parallel 8 plane,  write   read,	wrdmode */
#define	PWWPIX	7	/* parallel16 pixel,  write   write,	pixmode */

/*
 * ROP control unit numbers
 */
#define CG2_ROP0	0	/* rasterop unit for bit plane 0 */
#define CG2_ROP1	1	/* rasterop unit for bit plane 1 */
#define CG2_ROP2	2
#define CG2_ROP3	3
#define CG2_ROP4	4
#define CG2_ROP5	5
#define CG2_ROP6	6
#define CG2_ROP7	7
#define CG2_ALLROP	8	/* writes to all units enabled by PPMASK */
				/* reads from plane zero */
				
#define	CG_SRC		0xCC
#define	CG_DEST		0xAA
#define	CG_MASK		0xf0
#define	CG_NOTMASK	0x0f
#define	CGOP_NEEDS_MASK(op)		( (((op)>>4)^(op)) & CG_NOTMASK)

/*
 *----------- Defines for accessing the rasterop units
 */
#define	cg2_setrsource(fb, ropunit, val)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_source1 = (val))
#define	cg2_setrsource_pix(fb, ropunit, val) \
		((fb)->ropcontrol[(ropunit)].prime.ropregs.mrc_source1 = (val))
#define	cg2_setlsource(fb, ropunit, val)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_source2 = (val))
#define	cg2_setlsource_pix(fb, ropunit, val) \
		((fb)->ropcontrol[(ropunit)].prime.ropregs.mrc_source2 = (val))
#define	cg2_setpattern(fb, ropunit, val)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_pattern = (val))
#define	cg2_setlmask(fb, ropunit, val) \
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_mask1 = (val))
#define	cg2_setrmask(fb, ropunit, val) \
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_mask2 = (val))
#define	cg2_setshift(fb, ropunit, shft, dir)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_shift =	\
		 (shft)|((dir)<<8)	)
#define	cg2_setfunction(fb, ropunit, val)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_op = (val))
#define	cg2_setwidth(fb, ropunit, w, count)				\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_width = (w));	\
		((fb)->ropcontrol[(ropunit)].ropregs.mrc_opcount = (count))

/*
 *----------- Defines for accessing the zoom and pan registers
 */
#define	cg2_setzoom(fb, pixsize)					\
		((fb)->misc.zoom.zoom.reg.pixzoom = (pixsize)-1)
#define	cg2_setpanoffset(fb, xoff, yoff)				\
		((fb)->misc.zoom.pixpan.reg.pixeloff = (xoff)>>2; \
		 (fb)->misc.zoom.zoom.reg.lineoff = (yoff))
#define	cg2_setpanorigin(fb, x, y)					\
		((y) = ((fb)->misc.zoom.status.reg.resolution == 1) ? \
			(y)*CG2_SQUARE+(x) : (y)*CG2_WIDTH+(x); \
		 (fb)->misc.zoom.pixpan.reg.lorigin = (y)&0xf; \
		 (fb)->misc.zoom.wordpan.reg = (y)>>4)
#define	cg2_setzoomstop(fb, y) \
		((fb)->misc.zoom.varzoom.reg = (y)>>2)

/*
 *      Defines that facilitate addressing the frame buffer
 */

#define	cg2_pixaddr(fb, x, y)						\
		(((fb)->status.reg.resolution) ?			\
			&(fb)->pixplane.spixel[(y)][(x)] :		\
			&(fb)->pixplane.pixel[(y)][(x)] )
#define	cg2_wordaddr(fb, plane, x, y)					\
		(((fb)->status.reg.resolution) ?			\
			&(fb)->memplane[(plane)].sword[(y)][(x)>>4] :	\
			&(fb)->memplane[(plane)].word[(y)][(x)>>4])
#define	cg2_roppixaddr(fb, x, y)					\
		(((fb)->status.reg.resolution) ?			\
			&(fb)->ropio.roppixel.spixel[(y)][(x)] :	\
			&(fb)->ropio.roppixel.pixel[(y)][(x)])
#define	cg2_ropwordaddr(fb, plane, x, y)				\
		(((fb)->status.reg.resolution) ?			\
			&(fb)->ropio.ropplane[(plane)].sword[(y)][(x)>>4]:\
			&(fb)->ropio.ropplane[(plane)].word[(y)][(x)>>4])
#define	cg2_width(fb )							\
		( ((fb)->status.reg.resolution)	? CG2_SQUARE : CG2_WIDTH )
#define	cg2_height(fb )							\
		( ((fb)->status.reg.resolution)	? CG2_SQUARE : CG2_HEIGHT )
#define	cg2_linebytes(fb, mode)						\
		( ((fb)->status.reg.resolution)				\
			? ( ((mode)&1)?CG2_SQUARE:CG2_SQUARE/8 )	\
			: ( ((mode)&1)?CG2_WIDTH:CG2_WIDTH/8   ))

#define	cg2_prskew(x)	((x) & 15)

#define	cg2_touch(a)	((a)=0)

#endif /* 	cg2reg_DEFINED */
