code:
/*	$OpenBSD: cgfour.c,v 1.30 2013/10/20 20:07:25 miod Exp $	*/
/*	$NetBSD: cgfour.c,v 1.13 1997/05/24 20:16:06 pk Exp $	*/

/*
 * Coyrpight (c) 2002 Miodrag Vallat.  All rights reserved.
 * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
 * Copyright (c) 1995 Theo de Raadt.  All rights reserved.
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from @(#)cgthree.c	8.2 (Berkeley) 10/30/93
 */

/*
 * color display (cgfour) driver.
 *
 * Does not handle interrupts, even though they can occur.
 *
 * XXX should defer colormap updates to vertical retrace interrupts
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/tty.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>		/* NBPG */

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/eeprom.h>
#include <machine/conf.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <machine/fbvar.h>

#include <sparc/dev/btreg.h>
#include <sparc/dev/btvar.h>
#include <sparc/dev/pfourreg.h>

/* per-display variables */
struct cgfour_softc {
	struct	sunfb sc_sunfb;		/* common base part */
	struct rom_reg	sc_phys;	/* display RAM (phys addr) */
	volatile struct fbcontrol *sc_fbc;	/* Brooktree registers */
	union	bt_cmap sc_cmap;	/* Brooktree color map */
};

int	cgfour_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t	cgfour_mmap(void *, off_t, int);
void	cgfour_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);

struct wsdisplay_accessops cgfour_accessops = {
	.ioctl = cgfour_ioctl,
	.mmap = cgfour_mmap,
	.burn_screen = fb_pfour_burner
};

void	cgfourattach(struct device *, struct device *, void *);
int	cgfourmatch(struct device *, void *, void *);

struct cfattach cgfour_ca = {
	sizeof(struct cgfour_softc), cgfourmatch, cgfourattach
};

struct cfdriver cgfour_cd = {
	NULL, "cgfour", DV_DULL
};

int
cgfourmatch(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
		return (0);

	if (!CPU_ISSUN4 || ca->ca_bustype != BUS_OBIO)
		return (0);

	if (probeget(ra->ra_vaddr, 4) == -1)
		return (0);

	/*
	 * Check the pfour register.
	 */
	if (fb_pfour_id(ra->ra_vaddr) == PFOUR_ID_COLOR8P1)
		return (1);

	return (0);
}

void
cgfourattach(struct device *parent, struct device *self, void *args)
{
	struct cgfour_softc *sc = (struct cgfour_softc *)self;
	struct confargs *ca = args;
	int node = 0;
	volatile struct bt_regs *bt;
	int isconsole = 0;

	printf(": p4");

	/* Map the pfour register. */
	SET(sc->sc_sunfb.sf_flags, FB_PFOUR);
	sc->sc_sunfb.sf_pfour = (volatile u_int32_t *)
		mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t));

	if (cputyp == CPU_SUN4) {
		struct eeprom *eep = (struct eeprom *)eeprom_va;

		/*
		 * Assume this is the console if there's no eeprom info
		 * to be found.
		 */
		if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_P4)
			isconsole = 1;
	}

	/*
	 * When the ROM has mapped in a cgfour display, the address
	 * maps only the video RAM, so in any case we have to map the
	 * registers ourselves.  We only need the video RAM if we are
	 * going to print characters via rconsole.
	 */

	sc->sc_phys = ca->ca_ra.ra_reg[0];

	/* enable video */
	fb_pfour_burner(sc, 1, 0);
	bt = &sc->sc_fbc->fbc_dac;
	BT_INIT(bt, 24);

	/*
	 * XXX should initialize the enable plane, instead of expecting the
	 * PROM to do so for us
	 */

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
	/*
	 * XXX this only maps the color plane, not the overlay or the enable
	 * planes
	 */
	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
	    PFOUR_COLOR_OFF_COLOR, round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, cgfour_setcolor);
	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &cgfour_accessops, isconsole);
}

int
cgfour_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct cgfour_softc *sc = v;
	struct wsdisplay_fbinfo *wdf;
	struct wsdisplay_cmap *cm;
	int error;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNCG4;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width  = sc->sc_sunfb.sf_width;
		wdf->depth  = sc->sc_sunfb.sf_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		break;

	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_getcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		break;

	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_putcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		bt_loadcmap(&sc->sc_cmap, &sc->sc_fbc->fbc_dac,
		    cm->index, cm->count, 1);
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	case WSDISPLAYIO_GCURPOS:
	case WSDISPLAYIO_SCURPOS:
	case WSDISPLAYIO_GCURMAX:
	case WSDISPLAYIO_GCURSOR:
	case WSDISPLAYIO_SCURSOR:
	default:
		return (-1);	/* not supported yet */
        }

	return (0);
}

paddr_t
cgfour_mmap(void *v, off_t offset, int prot)
{
	struct cgfour_softc *sc = v;

	if (offset & PGOFSET)
		return (-1);

	if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
		return (REG2PHYS(&sc->sc_phys,
		    PFOUR_COLOR_OFF_COLOR + offset) | PMAP_NC);
	}

	return (-1);
}

void
cgfour_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
	struct cgfour_softc *sc = v;

	bt_setcolor(&sc->sc_cmap, &sc->sc_fbc->fbc_dac, index, r, g, b, 1);
}


code:
/*	$OpenBSD: cgfourteen.c,v 1.38 2013/10/20 20:07:25 miod Exp $	*/
/*	$NetBSD: cgfourteen.c,v 1.7 1997/05/24 20:16:08 pk Exp $ */

/*
 * Copyright (c) 2002, 2003, 2005 Miodrag Vallat.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * Copyright (c) 1996
 *	The President and Fellows of Harvard College. All rights reserved.
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by Harvard University.
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 *	This product includes software developed by Harvard University and
 *	its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *   Based on:
 *	NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp
 *	NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp
 */

/*
 * Driver for Campus-II on-board mbus-based video (cgfourteen).
 *
 * XXX should bring hardware cursor code back
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/tty.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/cpu.h>
#include <machine/conf.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <machine/fbvar.h>

#include <sparc/dev/cgfourteenreg.h>

#include <dev/cons.h>	/* for prom console hook */

/*
 * Per-display variables/state
 */

union cgfourteen_cmap {
	u_char  	cm_map[256][4];	/* 256 R/G/B/A entries (B is high)*/
	u_int32_t   	cm_chip[256];	/* the way the chip gets loaded */
};

struct cgfourteen_softc {
	struct	sunfb sc_sunfb;		/* common base part */

	struct 	rom_reg	sc_phys;	/* phys address of frame buffer */
	union	cgfourteen_cmap sc_cmap; /* current colormap */
	u_int	sc_cmap_start, sc_cmap_count;	/* deferred cmap range */

	/* registers mappings */
	struct	cg14ctl  *sc_ctl;
	struct	cg14curs *sc_hwc;
	struct 	cg14dac	 *sc_dac;
	struct	cg14xlut *sc_xlut;
	struct 	cg14clut *sc_clut1;
	struct	cg14clut *sc_clut2;
	struct	cg14clut *sc_clut3;
	u_int32_t *sc_autoincr;

	int	sc_rev;			/* VSIMM revision */
	int	sc_32;			/* can do 32bit at this resolution */
	size_t	sc_vramsize;		/* total video memory size */
	int	sc_isconsole;

	struct	intrhand sc_ih;
};

int	cgfourteen_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t	cgfourteen_mmap(void *, off_t, int);
void	cgfourteen_reset(struct cgfourteen_softc *, int);
void	cgfourteen_burner(void *, u_int, u_int);

int	cgfourteen_getcmap(union cgfourteen_cmap *, struct wsdisplay_cmap *);
int	cgfourteen_intr(void *);
void	cgfourteen_loadcmap_deferred(struct cgfourteen_softc *, u_int, u_int);
void	cgfourteen_loadcmap_immediate(struct cgfourteen_softc *, u_int, u_int);
void	cgfourteen_prom(struct cgfourteen_softc *);
int	cgfourteen_putcmap(union cgfourteen_cmap *, struct wsdisplay_cmap *);
void	cgfourteen_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);

struct wsdisplay_accessops cgfourteen_accessops = {
	.ioctl = cgfourteen_ioctl,
	.mmap = cgfourteen_mmap,
	.burn_screen = cgfourteen_burner
};

void	cgfourteenattach(struct device *, struct device *, void *);
int	cgfourteenmatch(struct device *, void *, void *);
int	cgfourteenactivate(struct device *, int);

struct cfattach cgfourteen_ca = {
	sizeof(struct cgfourteen_softc), cgfourteenmatch, cgfourteenattach,
	NULL, cgfourteenactivate
};

struct cfdriver cgfourteen_cd = {
	NULL, "cgfourteen", DV_DULL
};

/*
 * Match a cgfourteen.
 */
int
cgfourteenmatch(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
		return (0);

	/*
	 * This driver should not be attached without an "addr" locator,
	 * as this is the only way to differentiate the main and secondary
	 * VSIMM.
	 */
	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)ra->ra_paddr)
		return (0);

	/*
	 * The cgfourteen is a local-bus video adaptor, accessed directly
	 * via the processor, and not through device space or an external
	 * bus. Thus we look _only_ at the obio bus.
	 * Additionally, these things exist only on the Sun4m.
	 */
	if (CPU_ISSUN4M && ca->ca_bustype == BUS_OBIO)
		return (1);

	return (0);
}

/*
 * Attach a display.
 */
void
cgfourteenattach(struct device *parent, struct device *self, void *args)
{
	struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self;
	struct confargs *ca = args;
	int node, pri, i;
	u_int32_t *lut;
	char *nam;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	/*
	 * Sanity checks
	 */
	if (ca->ca_ra.ra_len < 0x10000) {
		printf("expected %x bytes of control registers, got %x\n",
		    0x10000, ca->ca_ra.ra_len);
		return;
	}
	if (ca->ca_ra.ra_nreg < CG14_NREG) {
		printf("expected %d registers, got %d\n",
		    CG14_NREG, ca->ca_ra.ra_nreg);
		return;
	}
	if (ca->ca_ra.ra_nintr != 1) {
		printf("expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
		return;
	}

	node = ca->ca_ra.ra_node;
	nam = getpropstring(node, "model");
	if (*nam != '\0')
		printf("%s, ", nam);

	sc->sc_isconsole = node == fbnode;

	/*
	 * Map in the 8 useful pages of registers
	 */
	sc->sc_ctl = (struct cg14ctl *) mapiodev(
	    &ca->ca_ra.ra_reg[CG14_REG_CONTROL], 0, ca->ca_ra.ra_len);

	sc->sc_hwc = (struct cg14curs *) ((u_int)sc->sc_ctl +
					  CG14_OFFSET_CURS);
	sc->sc_dac = (struct cg14dac *) ((u_int)sc->sc_ctl +
					 CG14_OFFSET_DAC);
	sc->sc_xlut = (struct cg14xlut *) ((u_int)sc->sc_ctl +
					   CG14_OFFSET_XLUT);
	sc->sc_clut1 = (struct cg14clut *) ((u_int)sc->sc_ctl +
					    CG14_OFFSET_CLUT1);
	sc->sc_clut2 = (struct cg14clut *) ((u_int)sc->sc_ctl +
					    CG14_OFFSET_CLUT2);
	sc->sc_clut3 = (struct cg14clut *) ((u_int)sc->sc_ctl +
					    CG14_OFFSET_CLUT3);
	sc->sc_autoincr = (u_int32_t *) ((u_int)sc->sc_ctl +
				     CG14_OFFSET_AUTOINCR);

	sc->sc_rev =
	    (sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) >> CG14_RSR_REVSHIFT;

	printf("%dMB, rev %d.%d", ca->ca_ra.ra_reg[CG14_REG_VRAM].rr_len >> 20,
	    sc->sc_rev, sc->sc_ctl->ctl_rsr & CG14_RSR_IMPLMASK);

	sc->sc_phys = ca->ca_ra.ra_reg[CG14_REG_VRAM];

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);

	/*
	 * The prom will report depth == 8, since this is the mode it will
	 * get initialized in.
	 * Check if we will be able to use 32 bit mode later (i.e. if it will
	 * fit in the video memory. Note that, if this is not the case, the
	 * VSIMM will usually not appear in the OBP device tree!
	 */
	sc->sc_vramsize = ca->ca_ra.ra_reg[CG14_REG_VRAM].rr_len;
	sc->sc_32 = sc->sc_sunfb.sf_fbsize * 4 <= sc->sc_vramsize;

	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&ca->ca_ra.ra_reg[CG14_REG_VRAM],
	    0,	/* CHUNKY_XBGR */
	    sc->sc_vramsize);

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	sc->sc_ih.ih_fun = cgfourteen_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	/*
	 * Reset frame buffer controls
	 */
	sc->sc_sunfb.sf_depth = 0;	/* force action */
	cgfourteen_reset(sc, 8);

	/*
	 * Grab the initial colormap
	 */
	lut = (u_int32_t *)sc->sc_clut1->clut_lut;
	for (i = 0; i < CG14_CLUT_SIZE; i++)
		sc->sc_cmap.cm_chip[i] = lut[i];

	/*
	 * Enable the video.
	 */
	cgfourteen_burner(sc, 1, 0);

	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, sc->sc_isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, cgfourteen_setcolor);

	if (sc->sc_isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &cgfourteen_accessops, sc->sc_isconsole);
}

int
cgfourteenactivate(struct device *self, int act)
{
	struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self;
	int ret = 0;

	switch (act) {
	case DVACT_POWERDOWN:
		if (sc->sc_isconsole)
			cgfourteen_prom(sc);
		break;
	}

	return (ret);
}

int
cgfourteen_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct cgfourteen_softc *sc = dev;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int error;

	/*
	 * Note that, although the emulation (text) mode is running in a
	 * 8-bit plane, we advertize the frame buffer as 32-bit if it can
	 * support this mode.
	 */
	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNCG14;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width = sc->sc_sunfb.sf_width;
		wdf->depth = sc->sc_32 ? 32 : 8;
		wdf->cmsize = sc->sc_32 ? 0 : 256;
		break;
	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
		if (sc->sc_32)
			*(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
		else
			return (-1);
		break;
	case WSDISPLAYIO_LINEBYTES:
		if (sc->sc_32)
			*(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
		else
			*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		break;

	case WSDISPLAYIO_GETCMAP:
		if (sc->sc_32 == 0) {
			cm = (struct wsdisplay_cmap *)data;
			error = cgfourteen_getcmap(&sc->sc_cmap, cm);
			if (error)
				return (error);
		}
		break;
	case WSDISPLAYIO_PUTCMAP:
		if (sc->sc_32 == 0) {
			cm = (struct wsdisplay_cmap *)data;
			error = cgfourteen_putcmap(&sc->sc_cmap, cm);
			if (error)
				return (error);
			cgfourteen_loadcmap_deferred(sc, cm->index, cm->count);
		}
		break;

	case WSDISPLAYIO_SMODE:
		if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
			/* Back from X11 to text mode */
			cgfourteen_reset(sc, 8);
		} else {
			/* Starting X11, try to switch to 32 bit mode */
			if (sc->sc_32)
				cgfourteen_reset(sc, 32);
		}
		break;

	case WSDISPLAYIO_GVIDEO:
	case WSDISPLAYIO_SVIDEO:
		break;

	default:
		return (-1);	/* not supported yet */
	}
	return (0);
}

/*
 * Return the address that would map the given device at the given
 * offset, allowing for the given protection, or return -1 for error.
 */
paddr_t
cgfourteen_mmap(void *v, off_t offset, int prot)
{
	struct cgfourteen_softc *sc = v;

	if (offset & PGOFSET || offset < 0)
		return (-1);

	/* Allow mapping as a dumb framebuffer from offset 0 */
	if (offset < sc->sc_sunfb.sf_fbsize * (sc->sc_32 ? 4 : 1)) {
		return (REG2PHYS(&sc->sc_phys, offset) | PMAP_NC);
	}

	return (-1);
}

/* Initialize the framebuffer, storing away useful state for later reset */
void
cgfourteen_reset(struct cgfourteen_softc *sc, int depth)
{
	u_int i;

	if (sc->sc_sunfb.sf_depth != depth) {
		if (depth == 8) {
			/*
			 * Enable the video and put it in 8 bit mode
			 */
			if (sc->sc_rev == 0)
				sc->sc_ctl->ctl_mctl = CG14_MCTL_R0_ENABLEHW |
				    CG14_MCTL_PIXMODE_8;
			else
				sc->sc_ctl->ctl_mctl = CG14_MCTL_R1_ENABLEHW |
				    CG14_MCTL_R1_ENABLEVID |
				    CG14_MCTL_PIXMODE_8;

			fbwscons_setcolormap(&sc->sc_sunfb,
			    cgfourteen_setcolor);
		} else {
			/*
			 * Clear the screen to black
			 */
			bzero(sc->sc_sunfb.sf_ro.ri_bits,
			    sc->sc_sunfb.sf_fbsize);

			/*
			 * Enable the video, and put in 32 bit mode
			 */
			if (sc->sc_rev == 0)
				sc->sc_ctl->ctl_mctl = CG14_MCTL_R0_ENABLEHW |
				    CG14_MCTL_PIXMODE_32;
			else
				sc->sc_ctl->ctl_mctl = CG14_MCTL_R1_ENABLEHW |
				    CG14_MCTL_R1_ENABLEVID |
				    CG14_MCTL_PIXMODE_32;

			/*
			 * Zero the xlut to enable direct-color mode
			 */
			sc->sc_xlut->xlut_lutinc[0] = 0;
			for (i = CG14_CLUT_SIZE; i; i--)
				*sc->sc_autoincr = 0;
		}
	}

	sc->sc_cmap_count = 0;
	sc->sc_sunfb.sf_depth = depth;
}

void
cgfourteen_prom(struct cgfourteen_softc *sc)
{
	extern struct consdev consdev_prom;

	if (sc->sc_sunfb.sf_depth != 8) {
		/*
		 * Go back to 8-bit mode.
		 */
		cgfourteen_reset(sc, 8);

		/*
		 * Go back to prom output for the last few messages, so they
		 * will be displayed correctly.
		 */
		cn_tab = &consdev_prom;
	}
}

void
cgfourteen_burner(void *v, u_int on, u_int flags)
{
	struct cgfourteen_softc *sc = v;
	u_int bits;

	/*
	 * We can only use DPMS to power down the display if the chip revision
	 * is greater than 0.
	 */
	if (sc->sc_rev == 0)
		bits = CG14_MCTL_R0_ENABLEHW;
	else
		bits = CG14_MCTL_R1_ENABLEHW | CG14_MCTL_R1_ENABLEVID;

	if (on) {
		sc->sc_ctl->ctl_mctl |= bits;
	} else {
		sc->sc_ctl->ctl_mctl &= ~bits;
	}
}

/* Read the software shadow colormap */
int
cgfourteen_getcmap(union cgfourteen_cmap *cm, struct wsdisplay_cmap *rcm)
{
	u_int index = rcm->index, count = rcm->count, i;
	int error;

	if (index >= CG14_CLUT_SIZE || count > CG14_CLUT_SIZE - index)
                return (EINVAL);

	for (i = 0; i < count; i++) {
		if ((error = copyout(&cm->cm_map[index + i][3],
		    &rcm->red[i], 1)) != 0)
			return (error);
		if ((error = copyout(&cm->cm_map[index + i][2],
		    &rcm->green[i], 1)) != 0)
			return (error);
		if ((error = copyout(&cm->cm_map[index + i][1],
		    &rcm->blue[i], 1)) != 0)
			return (error);
	}
	return (0);
}

/* Write the software shadow colormap */
int
cgfourteen_putcmap(union cgfourteen_cmap *cm, struct wsdisplay_cmap *rcm)
{
	u_int index = rcm->index, count = rcm->count, i;
	int error;

	if (index >= CG14_CLUT_SIZE || count > CG14_CLUT_SIZE - index)
                return (EINVAL);

	for (i = 0; i < count; i++) {
		if ((error = copyin(&rcm->red[i],
		    &cm->cm_map[index + i][3], 1)) != 0)
			return (error);
		if ((error = copyin(&rcm->green[i],
		    &cm->cm_map[index + i][2], 1)) != 0)
			return (error);
		if ((error = copyin(&rcm->blue[i],
		    &cm->cm_map[index + i][1], 1)) != 0)
			return (error);
		cm->cm_map[index +i][0] = 0;	/* no alpha channel */
	}
	return (0);
}

void
cgfourteen_loadcmap_deferred(struct cgfourteen_softc *sc, u_int start,
    u_int ncolors)
{
	u_int end;

	/* Grow the deferred colormap update range if necessary */
	if (sc->sc_cmap_count == 0) {
		sc->sc_cmap_start = start;
		sc->sc_cmap_count = ncolors;
	} else {
		end = MAX(start + ncolors,
		    sc->sc_cmap_start + sc->sc_cmap_count);
		sc->sc_cmap_start = min(sc->sc_cmap_start, start);
		sc->sc_cmap_count = end - sc->sc_cmap_start;
	}

	/* Enable interrupts */
	sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEINTR;
}

void
cgfourteen_loadcmap_immediate(struct cgfourteen_softc *sc, u_int start,
    u_int ncolors)
{
	u_int32_t *colp = &sc->sc_cmap.cm_chip[start];

	sc->sc_clut1->clut_lutinc[start] = 0;
	while (ncolors-- != 0)
		*sc->sc_autoincr = *colp++;
}

void
cgfourteen_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
	struct cgfourteen_softc *sc = v;

	sc->sc_cmap.cm_map[index][3] = r;
	sc->sc_cmap.cm_map[index][2] = g;
	sc->sc_cmap.cm_map[index][1] = b;
	sc->sc_cmap.cm_map[index][0] = 0;	/* no alpha channel */

	cgfourteen_loadcmap_immediate(sc, index, 1);
}

int
cgfourteen_intr(void *v)
{
	struct cgfourteen_softc *sc = v;
	u_int msr;
	int claim = 0;

	msr = sc->sc_ctl->ctl_msr;

	/* check that the interrupt is ours */
	if (!ISSET(msr, CG14_MSR_PENDING) ||
	    !ISSET(sc->sc_ctl->ctl_mctl, CG14_MCTL_ENABLEINTR)) {
		return (0);
	}

	/* vertical retrace interrupt */
	if (ISSET(msr, CG14_MSR_VRETRACE)) {
		/* acknowledge by writing to the (read only) msr */
		sc->sc_ctl->ctl_msr = 0;

		/* disable interrupts until next colormap change */
		sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEINTR;

		cgfourteen_loadcmap_immediate(sc,
		    sc->sc_cmap_start, sc->sc_cmap_count);

		claim = 1;
	}

	/* engine fault */
	if (ISSET(msr, CG14_MSR_FAULT)) {
		/* acknowledge by reading the fault status register */
		claim = 1 | sc->sc_ctl->ctl_fsr;
	}

	if (claim == 0) {
#ifdef DEBUG
		printf("%s: unknown interrupt cause, msr=%x\n",
		    sc->sc_sunfb.sf_dev.dv_xname, msr);
#endif
		claim = 1;	/* claim anyway */
	}

	return (claim & 1);
}

license: unknown


code:
/*	$OpenBSD: cgfourteenreg.h,v 1.4 2005/03/15 18:50:43 miod Exp $	*/
/*	$NetBSD: cgfourteenreg.h,v 1.1 1996/09/30 22:41:02 abrown Exp $ */

/*
 * Copyright (c) 1996
 *	The President and Fellows of Harvard College. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Harvard University and
 *	its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Register/dac/clut/cursor definitions for cgfourteen frame buffer
 */

/* Control registers */
#define	CG14_REG_CONTROL	0
#define	CG14_REG_VRAM		1

#define	CG14_NREG		2

/* Locations of control registers in cg14 register set */
#define	CG14_OFFSET_CURS	0x1000
#define CG14_OFFSET_DAC		0x2000
#define CG14_OFFSET_XLUT	0x3000
#define CG14_OFFSET_CLUT1	0x4000
#define CG14_OFFSET_CLUT2	0x5000
#define CG14_OFFSET_CLUT3	0x6000
#define CG14_OFFSET_AUTOINCR	0xf000

/* Main control register set */
struct cg14ctl {
	volatile u_int8_t	ctl_mctl;	/* main control register */
#define CG14_MCTL_ENABLEINTR	0x80		/* interrupts */
#define CG14_MCTL_R0_ENABLEHW	0x40		/* hardware enable */
#define	CG14_MCTL_R1_ENABLEHW	0x01
#define	CG14_MCTL_R1_ENABLEVID	0x40		/* display enable */
#define CG14_MCTL_PIXMODE_MASK	0x30
#define		CG14_MCTL_PIXMODE_8	0x00	/* data is 16 8-bit pixels */
#define		CG14_MCTL_PIXMODE_16	0x20	/* data is 8 16-bit pixels */
#define		CG14_MCTL_PIXMODE_32	0x30	/* data is 4 32-bit pixels */
#define CG14_MCTL_PIXMODE_SHIFT	4
#define	CG14_MCTL_TMR		0x0c
#define CG14_MCTL_ENABLETMR	0x02
#define CG14_MCTL_R0_RESET	0x01
	volatile u_int8_t	ctl_ppr;	/* packed pixel register */
	volatile u_int8_t	ctl_tmsr0; 	/* test status reg. 0 */
	volatile u_int8_t	ctl_tmsr1;	/* test status reg. 1 */
	volatile u_int8_t	ctl_msr;	/* master status register */
#define	CG14_MSR_PENDING	0x20		/* interrupt pending */
#define	CG14_MSR_VRETRACE	0x10		/* vertical retrace interrupt */
#define	CG14_MSR_FAULT		0x01		/* fault interrupt */
	volatile u_int8_t	ctl_fsr;	/* fault status register */
	volatile u_int8_t	ctl_rsr;	/* revision status register */
#define CG14_RSR_REVMASK	0xf0 		/*  mask to get revision */
#define CG14_RSR_REVSHIFT	4
#define CG14_RSR_IMPLMASK	0x0f		/*  mask to get impl. code */
	volatile u_int8_t	ctl_ccr;	/* clock control register */
	/* XXX etc. */
};

/* Hardware cursor map */
#define CG14_CURS_SIZE		32
#define	CG14_CURS_MASK		0x1f
struct cg14curs {
	volatile u_int32_t	curs_plane0[CG14_CURS_SIZE];	/* plane 0 */
	volatile u_int32_t	curs_plane1[CG14_CURS_SIZE];
	volatile u_int8_t	curs_ctl;	/* control register */
#define CG14_CURS_ENABLE	0x4
#define CG14_CURS_DOUBLEBUFFER	0x2 		/* use X-channel for curs */
	volatile u_int8_t	pad0[3];
	volatile u_int16_t	curs_x;		/* x position */
	volatile u_int16_t	curs_y;		/* y position */
	volatile u_int32_t	curs_color1;	/* color register 1 */
	volatile u_int32_t	curs_color2;	/* color register 2 */
	volatile u_int32_t	pad[444];	/* pad to 2KB boundary */
	volatile u_int32_t	curs_plane0incr[CG14_CURS_SIZE]; /* autoincr */
	volatile u_int32_t	curs_plane1incr[CG14_CURS_SIZE]; /* autoincr */
};

/* DAC */
struct cg14dac {
	volatile u_int8_t	dac_addr;	/* address register */
	volatile u_int8_t	pad0[255];
	volatile u_int8_t	dac_gammalut;	/* gamma LUT */
	volatile u_int8_t	pad1[255];
	volatile u_int8_t	dac_regsel;	/* register select */
	volatile u_int8_t	pad2[255];
	volatile u_int8_t	dac_mode;	/* mode register */
};

#define CG14_CLUT_SIZE	256

/* XLUT registers */
struct cg14xlut {
	volatile u_int8_t	xlut_lut[CG14_CLUT_SIZE];	/* the LUT */
	volatile u_int8_t	xlut_lutd[CG14_CLUT_SIZE];	/* ??? */
	volatile u_int8_t	pad0[0x600];
	volatile u_int8_t	xlut_lutinc[CG14_CLUT_SIZE];	/* autoincrLUT*/
	volatile u_int8_t	xlut_lutincd[CG14_CLUT_SIZE];
};

/* Color Look-Up Table (CLUT) */
struct cg14clut {
	volatile u_int32_t	clut_lut[CG14_CLUT_SIZE];	/* the LUT */
	volatile u_int32_t	clut_lutd[CG14_CLUT_SIZE];	/* ??? */
	volatile u_int32_t	clut_lutinc[CG14_CLUT_SIZE];	/* autoincr */
	volatile u_int32_t	clut_lutincd[CG14_CLUT_SIZE];
};


code:
/*	$OpenBSD: cgsix.c,v 1.44 2013/10/20 20:07:25 miod Exp $	*/
/*	$NetBSD: cgsix.c,v 1.33 1997/08/07 19:12:30 pk Exp $ */

/*
 * Copyright (c) 2002 Miodrag Vallat.  All rights reserved.
 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Effort sponsored in part by the Defense Advanced Research Projects
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
 *
 *
 * Copyright (c) 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)cgsix.c	8.4 (Berkeley) 1/21/94
 */

/*
 * color display (cgsix) driver.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/cpu.h>
#if defined(SUN4)
#include <machine/eeprom.h>
#endif
#include <machine/conf.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <machine/fbvar.h>

#include <sparc/dev/btreg.h>
#include <sparc/dev/btvar.h>
#include <sparc/dev/cgsixreg.h>
#include <dev/ic/bt458reg.h>

#if defined(SUN4)
#include <sparc/dev/pfourreg.h>
#endif

/* per-display variables */
struct cgsix_softc {
	struct	sunfb sc_sunfb;		/* common base part */
	struct	rom_reg sc_phys;	/* phys addr of h/w */
	volatile struct bt_regs *sc_bt;		/* Brooktree registers */
	volatile int *sc_fhc;			/* FHC register */
	volatile struct cgsix_thc *sc_thc;	/* THC registers */
	volatile struct cgsix_fbc *sc_fbc;	/* FBC registers */
	volatile struct cgsix_tec_xxx *sc_tec;	/* TEC registers */
	union	bt_cmap sc_cmap;	/* Brooktree color map */
	struct	intrhand sc_ih;
};

void	cgsix_burner(void *, u_int, u_int);
int	cgsix_intr(void *);
int	cgsix_ioctl(void *, u_long, caddr_t, int, struct proc *);
static __inline__
void	cgsix_loadcmap_deferred(struct cgsix_softc *, u_int, u_int);
paddr_t	cgsix_mmap(void *, off_t, int);
void	cgsix_reset(struct cgsix_softc *, u_int);
void	cgsix_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);

int	cgsix_ras_copyrows(void *, int, int, int);
int	cgsix_ras_copycols(void *, int, int, int, int);
int	cgsix_ras_do_cursor(struct rasops_info *);
int	cgsix_ras_erasecols(void *, int, int, int, long);
int	cgsix_ras_eraserows(void *, int, int, long);
void	cgsix_ras_init(struct cgsix_softc *);

struct wsdisplay_accessops cgsix_accessops = {
	.ioctl = cgsix_ioctl,
	.mmap = cgsix_mmap,
	.burn_screen = cgsix_burner
};

int	cgsixmatch(struct device *, void *, void *);
void	cgsixattach(struct device *, struct device *, void *);

struct cfattach cgsix_ca = {
	sizeof(struct cgsix_softc), cgsixmatch, cgsixattach
};

struct cfdriver cgsix_cd = {
	NULL, "cgsix", DV_DULL
};

int
cgsixmatch(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp(ra->ra_name, cf->cf_driver->cd_name) &&
	    strcmp(ra->ra_name, "SUNW,cgsix"))
		return (0);

	switch (ca->ca_bustype) {
	case BUS_SBUS:
		return (1);
	case BUS_OBIO:
#if defined(SUN4)
		if (CPU_ISSUN4) {
			void *tmp;

			/*
			 * Check for a pfour framebuffer.  This is done
			 * somewhat differently on the cgsix than other
			 * pfour framebuffers.
			 */
			bus_untmp();
			tmp = (caddr_t)mapdev(ra->ra_reg, TMPMAP_VA,
			    CGSIX_FHC_OFFSET, NBPG);
			if (probeget(tmp, 4) == -1)
				return (0);

			if (fb_pfour_id(tmp) == PFOUR_ID_FASTCOLOR)
				return (1);
		}
#endif
		/* FALLTHROUGH */
	default:
		return (0);
	}
}

void
cgsixattach(struct device *parent, struct device *self, void *args)
{
	struct cgsix_softc *sc = (struct cgsix_softc *)self;
	struct confargs *ca = args;
	int node, pri;
	int isconsole = 0, sbus = 1;
	char *nam;
	u_int fhcrev;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	/*
	 * Map just BT, FHC, FBC, THC, and video RAM.
	 */
	sc->sc_phys = ca->ca_ra.ra_reg[0];
	sc->sc_bt = (volatile struct bt_regs *)
	   mapiodev(ca->ca_ra.ra_reg, CGSIX_BT_OFFSET, CGSIX_BT_SIZE);
	sc->sc_fhc = (volatile int *)
	   mapiodev(ca->ca_ra.ra_reg, CGSIX_FHC_OFFSET, CGSIX_FHC_SIZE);
	sc->sc_thc = (volatile struct cgsix_thc *)
	   mapiodev(ca->ca_ra.ra_reg, CGSIX_THC_OFFSET, CGSIX_THC_SIZE);
	sc->sc_fbc = (volatile struct cgsix_fbc *)
	   mapiodev(ca->ca_ra.ra_reg, CGSIX_FBC_OFFSET, CGSIX_FBC_SIZE);
	sc->sc_tec = (volatile struct cgsix_tec_xxx *)
	   mapiodev(ca->ca_ra.ra_reg, CGSIX_TEC_OFFSET, CGSIX_TEC_SIZE);

	switch (ca->ca_bustype) {
	case BUS_OBIO:
		sbus = node = 0;
		SET(sc->sc_sunfb.sf_flags, FB_PFOUR);
		nam = "p4";
		break;
	case BUS_SBUS:
		node = ca->ca_ra.ra_node;
		nam = getpropstring(node, "model");
		break;
	}

	if (*nam != '\0')
		printf("%s, ", nam);

#if defined(SUN4)
	if (CPU_ISSUN4) {
		struct eeprom *eep = (struct eeprom *)eeprom_va;
		int constype = ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR) ?
		    EED_CONS_P4 : EED_CONS_COLOR;
		/*
		 * Assume this is the console if there's no eeprom info
		 * to be found.
		 */
		if (eep == NULL || eep->ee_diag.eed_console == constype)
			isconsole = 1;
	}
#endif

	if (!CPU_ISSUN4)
		isconsole = node == fbnode;

	fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) &
	    (FHC_REV_MASK >> FHC_REV_SHIFT);

	sc->sc_ih.ih_fun = cgsix_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	/* reset cursor & frame buffer controls */
	cgsix_reset(sc, fhcrev);

	/* enable video */
	cgsix_burner(sc, 1, 0);

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
        sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
	    CGSIX_VID_OFFSET, round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	printf("%dx%d, rev %d\n", sc->sc_sunfb.sf_width,
	    sc->sc_sunfb.sf_height, fhcrev);

	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, cgsix_setcolor);

	/*
	 * Old rev. cg6 cards do not like the current acceleration code.
	 *
	 * Some hints from Sun point out at timing and cache problems, which
	 * will be investigated later.
	 */
	if (fhcrev >= 5) {
		sc->sc_sunfb.sf_ro.ri_ops.copyrows = cgsix_ras_copyrows;
		sc->sc_sunfb.sf_ro.ri_ops.copycols = cgsix_ras_copycols;
		sc->sc_sunfb.sf_ro.ri_ops.eraserows = cgsix_ras_eraserows;
		sc->sc_sunfb.sf_ro.ri_ops.erasecols = cgsix_ras_erasecols;
		sc->sc_sunfb.sf_ro.ri_do_cursor = cgsix_ras_do_cursor;
		cgsix_ras_init(sc);
	}

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &cgsix_accessops, isconsole);
}

int
cgsix_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct cgsix_softc *sc = dev;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int error;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNCG6;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width  = sc->sc_sunfb.sf_width;
		wdf->depth  = sc->sc_sunfb.sf_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		break;

	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_getcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		break;

	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_putcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		cgsix_loadcmap_deferred(sc, cm->index, cm->count);
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	case WSDISPLAYIO_GCURPOS:
	case WSDISPLAYIO_SCURPOS:
	case WSDISPLAYIO_GCURMAX:
	case WSDISPLAYIO_GCURSOR:
	case WSDISPLAYIO_SCURSOR:
	default:
		return (-1);	/* not supported yet */
	}

	return (0);
}

/*
 * Clean up hardware state (e.g., after bootup or after X crashes).
 */
void
cgsix_reset(struct cgsix_softc *sc, u_int fhcrev)
{
	volatile struct cgsix_tec_xxx *tec;
	int fhc;
	volatile struct bt_regs *bt;

	/* hide the cursor, just in case */
	sc->sc_thc->thc_cursxy = THC_CURSOFF;

	/* turn off frobs in transform engine (makes X11 work) */
	tec = sc->sc_tec;
	tec->tec_mv = 0;
	tec->tec_clip = 0;
	tec->tec_vdc = 0;

	/* take care of hardware bugs in old revisions */
	if (fhcrev < 5) {
		/*
		 * Keep current resolution; set cpu to 68020, set test
		 * window (size 1Kx1K), and for rev 1, disable dest cache.
		 */
		fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 |
		    FHC_TEST |
		    (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT);
		if (fhcrev < 2)
			fhc |= FHC_DST_DISABLE;
		*sc->sc_fhc = fhc;
	}

	/* Enable cursor in Brooktree DAC. */
	bt = sc->sc_bt;
	bt->bt_addr = BT_CR << 24;
	bt->bt_ctrl |= (BTCR_DISPENA_OV1 | BTCR_DISPENA_OV0) << 24;
}

paddr_t
cgsix_mmap(void *v, off_t offset, int prot)
{
	struct cgsix_softc *sc = v;

	if (offset & PGOFSET)
		return (-1);

	/* Allow mapping as a dumb framebuffer from offset 0 */
	if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
		return (REG2PHYS(&sc->sc_phys, offset + CGSIX_VID_OFFSET) |
		    PMAP_NC);
	}

	return (-1);
}

void
cgsix_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
	struct cgsix_softc *sc = v;

	bt_setcolor(&sc->sc_cmap, sc->sc_bt, index, r, g, b, 1);
}

static __inline__ void
cgsix_loadcmap_deferred(struct cgsix_softc *sc, u_int start, u_int ncolors)
{
	u_int32_t thcm;

	thcm = sc->sc_thc->thc_misc;
	thcm &= ~THC_MISC_RESET;
	thcm |= THC_MISC_INTEN;
	sc->sc_thc->thc_misc = thcm;
}

void
cgsix_burner(void *v, u_int on, u_int flags)
{
	struct cgsix_softc *sc = v;
	int s;
	u_int32_t thcm;

	s = splhigh();
	thcm = sc->sc_thc->thc_misc;
	if (on)
		thcm |= THC_MISC_VIDEN | THC_MISC_SYNCEN;
	else {
		thcm &= ~THC_MISC_VIDEN;
		if (flags & WSDISPLAY_BURN_VBLANK)
			thcm &= ~THC_MISC_SYNCEN;
	}
	sc->sc_thc->thc_misc = thcm;
	splx(s);
}

int
cgsix_intr(void *v)
{
	struct cgsix_softc *sc = v;
	u_int32_t thcm;

	thcm = sc->sc_thc->thc_misc;
	if ((thcm & (THC_MISC_INTEN | THC_MISC_INTR)) !=
	    (THC_MISC_INTEN | THC_MISC_INTR)) {
		/* Not expecting an interrupt, it's not for us. */
		return (0);
	}

	/* Acknowledge the interrupt and disable it. */
	thcm &= ~(THC_MISC_RESET | THC_MISC_INTEN);
	thcm |= THC_MISC_INTR;
	sc->sc_thc->thc_misc = thcm;
	bt_loadcmap(&sc->sc_cmap, sc->sc_bt, 0, 256, 1);
	return (1);
}

/*
 * Specifics rasops handlers for accelerated console
 */

#define	CG6_BLIT_WAIT(fbc) \
	while (((fbc)->fbc_blit & (FBC_BLIT_UNKNOWN | FBC_BLIT_GXFULL)) == \
	    (FBC_BLIT_UNKNOWN | FBC_BLIT_GXFULL))
#define	CG6_DRAW_WAIT(fbc) \
	while (((fbc)->fbc_draw & (FBC_DRAW_UNKNOWN | FBC_DRAW_GXFULL)) == \
	    (FBC_DRAW_UNKNOWN | FBC_DRAW_GXFULL))
#define	CG6_DRAIN(fbc) \
	while ((fbc)->fbc_s & FBC_S_GXINPROGRESS)

void
cgsix_ras_init(struct cgsix_softc *sc)
{
	u_int32_t m;

	CG6_DRAIN(sc->sc_fbc);
	m = sc->sc_fbc->fbc_mode;
	m &= ~FBC_MODE_MASK;
	m |= FBC_MODE_VAL;
	sc->sc_fbc->fbc_mode = m;
}

int
cgsix_ras_copyrows(void *cookie, int src, int dst, int n)
{
	struct rasops_info *ri = cookie;
	struct cgsix_softc *sc = ri->ri_hw;
	volatile struct cgsix_fbc *fbc = sc->sc_fbc;

	if (dst == src)
		return 0;
	if (src < 0) {
		n += src;
		src = 0;
	}
	if (src + n > ri->ri_rows)
		n = ri->ri_rows - src;
	if (dst < 0) {
		n += dst;
		dst = 0;
	}
	if (dst + n > ri->ri_rows)
		n = ri->ri_rows - dst;
	if (n <= 0)
		return 0;
	n *= ri->ri_font->fontheight;
	src *= ri->ri_font->fontheight;
	dst *= ri->ri_font->fontheight;

	fbc->fbc_clip = 0;
	fbc->fbc_s = 0;
	fbc->fbc_offx = 0;
	fbc->fbc_offy = 0;
	fbc->fbc_clipminx = 0;
	fbc->fbc_clipminy = 0;
	fbc->fbc_clipmaxx = ri->ri_width - 1;
	fbc->fbc_clipmaxy = ri->ri_height - 1;
	fbc->fbc_alu = FBC_ALU_COPY;
	fbc->fbc_x0 = ri->ri_xorigin;
	fbc->fbc_y0 = ri->ri_yorigin + src;
	fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
	fbc->fbc_y1 = ri->ri_yorigin + src + n - 1;
	fbc->fbc_x2 = ri->ri_xorigin;
	fbc->fbc_y2 = ri->ri_yorigin + dst;
	fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1;
	fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1;
	CG6_BLIT_WAIT(fbc);
	CG6_DRAIN(fbc);

	return 0;
}

int
cgsix_ras_copycols(void *cookie, int row, int src, int dst, int n)
{
	struct rasops_info *ri = cookie;
	struct cgsix_softc *sc = ri->ri_hw;
	volatile struct cgsix_fbc *fbc = sc->sc_fbc;

	if (dst == src)
		return 0;
	if ((row < 0) || (row >= ri->ri_rows))
		return 0;
	if (src < 0) {
		n += src;
		src = 0;
	}
	if (src + n > ri->ri_cols)
		n = ri->ri_cols - src;
	if (dst < 0) {
		n += dst;
		dst = 0;
	}
	if (dst + n > ri->ri_cols)
		n = ri->ri_cols - dst;
	if (n <= 0)
		return 0;
	n *= ri->ri_font->fontwidth;
	src *= ri->ri_font->fontwidth;
	dst *= ri->ri_font->fontwidth;
	row *= ri->ri_font->fontheight;

	fbc->fbc_clip = 0;
	fbc->fbc_s = 0;
	fbc->fbc_offx = 0;
	fbc->fbc_offy = 0;
	fbc->fbc_clipminx = 0;
	fbc->fbc_clipminy = 0;
	fbc->fbc_clipmaxx = ri->ri_width - 1;
	fbc->fbc_clipmaxy = ri->ri_height - 1;
	fbc->fbc_alu = FBC_ALU_COPY;
	fbc->fbc_x0 = ri->ri_xorigin + src;
	fbc->fbc_y0 = ri->ri_yorigin + row;
	fbc->fbc_x1 = ri->ri_xorigin + src + n - 1;
	fbc->fbc_y1 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
	fbc->fbc_x2 = ri->ri_xorigin + dst;
	fbc->fbc_y2 = ri->ri_yorigin + row;
	fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1;
	fbc->fbc_y3 = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
	CG6_BLIT_WAIT(fbc);
	CG6_DRAIN(fbc);

	return 0;
}

int
cgsix_ras_erasecols(void *cookie, int row, int col, int n, long attr)
{
	struct rasops_info *ri = cookie;
	struct cgsix_softc *sc = ri->ri_hw;
	volatile struct cgsix_fbc *fbc = sc->sc_fbc;
	int fg, bg;

	if ((row < 0) || (row >= ri->ri_rows))
		return 0;
	if (col < 0) {
		n += col;
		col = 0;
	}
	if (col + n > ri->ri_cols)
		n = ri->ri_cols - col;
	if (n <= 0)
		return 0;
	n *= ri->ri_font->fontwidth;
	col *= ri->ri_font->fontwidth;
	row *= ri->ri_font->fontheight;

	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);

	fbc->fbc_clip = 0;
	fbc->fbc_s = 0;
	fbc->fbc_offx = 0;
	fbc->fbc_offy = 0;
	fbc->fbc_clipminx = 0;
	fbc->fbc_clipminy = 0;
	fbc->fbc_clipmaxx = ri->ri_width - 1;
	fbc->fbc_clipmaxy = ri->ri_height - 1;
	fbc->fbc_alu = FBC_ALU_FILL;
	fbc->fbc_fg = ri->ri_devcmap[bg];
	fbc->fbc_arecty = ri->ri_yorigin + row;
	fbc->fbc_arectx = ri->ri_xorigin + col;
	fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
	fbc->fbc_arectx = ri->ri_xorigin + col + n - 1;
	CG6_DRAW_WAIT(fbc);
	CG6_DRAIN(fbc);

	return 0;
}

int
cgsix_ras_eraserows(void *cookie, int row, int n, long attr)
{
	struct rasops_info *ri = cookie;
	struct cgsix_softc *sc = ri->ri_hw;
	volatile struct cgsix_fbc *fbc = sc->sc_fbc;
	int fg, bg;

	if (row < 0) {
		n += row;
		row = 0;
	}
	if (row + n > ri->ri_rows)
		n = ri->ri_rows - row;
	if (n <= 0)
		return 0;

	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);

	fbc->fbc_clip = 0;
	fbc->fbc_s = 0;
	fbc->fbc_offx = 0;
	fbc->fbc_offy = 0;
	fbc->fbc_clipminx = 0;
	fbc->fbc_clipminy = 0;
	fbc->fbc_clipmaxx = ri->ri_width - 1;
	fbc->fbc_clipmaxy = ri->ri_height - 1;
	fbc->fbc_alu = FBC_ALU_FILL;
	fbc->fbc_fg = ri->ri_devcmap[bg];
	if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
		fbc->fbc_arecty = 0;
		fbc->fbc_arectx = 0;
		fbc->fbc_arecty = ri->ri_height - 1;
		fbc->fbc_arectx = ri->ri_width - 1;
	} else {
		row *= ri->ri_font->fontheight;
		fbc->fbc_arecty = ri->ri_yorigin + row;
		fbc->fbc_arectx = ri->ri_xorigin;
		fbc->fbc_arecty =
		    ri->ri_yorigin + row + (n * ri->ri_font->fontheight) - 1;
		fbc->fbc_arectx =
		    ri->ri_xorigin + ri->ri_emuwidth - 1;
	}
	CG6_DRAW_WAIT(fbc);
	CG6_DRAIN(fbc);

	return 0;
}

int
cgsix_ras_do_cursor(struct rasops_info *ri)
{
	struct cgsix_softc *sc = ri->ri_hw;
	int row, col;
	volatile struct cgsix_fbc *fbc = sc->sc_fbc;

	row = ri->ri_crow * ri->ri_font->fontheight;
	col = ri->ri_ccol * ri->ri_font->fontwidth;
	fbc->fbc_clip = 0;
	fbc->fbc_s = 0;
	fbc->fbc_offx = 0;
	fbc->fbc_offy = 0;
	fbc->fbc_clipminx = 0;
	fbc->fbc_clipminy = 0;
	fbc->fbc_clipmaxx = ri->ri_width - 1;
	fbc->fbc_clipmaxy = ri->ri_height - 1;
	fbc->fbc_alu = FBC_ALU_FLIP;
	fbc->fbc_arecty = ri->ri_yorigin + row;
	fbc->fbc_arectx = ri->ri_xorigin + col;
	fbc->fbc_arecty = ri->ri_yorigin + row + ri->ri_font->fontheight - 1;
	fbc->fbc_arectx = ri->ri_xorigin + col + ri->ri_font->fontwidth - 1;
	CG6_DRAW_WAIT(fbc);
	CG6_DRAIN(fbc);

	return 0;
}


code:
/*	$OpenBSD: cgsixreg.h,v 1.6 2003/06/02 23:27:54 millert Exp $	*/
/*	$NetBSD: cgsixreg.h,v 1.4 1996/02/27 22:09:31 thorpej Exp $ */

/*
 * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)cgsixreg.h	8.4 (Berkeley) 1/21/94
 */

/*
 * CG6 display registers.
 *
 * The cg6 is a complicated beastie.  We have been unable to extract any
 * documentation and most of the following are guesses based on a limited
 * amount of reverse engineering.
 *
 * A cg6 is composed of numerous groups of control registers, all with TLAs:
 *	FBC - frame buffer control?
 *	FHC - fbc hardware configuration / control? register (32 bits)
 *	DHC - ???
 *	TEC - transform engine control?
 *	THC - TEC Hardware Configuration
 *	ROM - a 64Kbyte ROM with who knows what in it.
 *	colormap - see below
 *	frame buffer memory (video RAM)
 *	possible other stuff
 *
 * Like the cg3, the cg6 uses a Brooktree Video DAC (see btreg.h).
 *
 * Various revisions of the cgsix have various hardware bugs.  So far,
 * we have only seen rev 1 & 2.
 */

/* offsets */
#define	CGSIX_ROM_OFFSET	0x000000
#define	CGSIX_BT_OFFSET		0x200000
#define	CGSIX_BT_SIZE		(sizeof(u_int32_t) * 4)
#define	CGSIX_DHC_OFFSET	0x240000
#define	CGSIX_ALT_OFFSET	0x280000
#define	CGSIX_FHC_OFFSET	0x300000
#define	CGSIX_FHC_SIZE		(sizeof(u_int32_t) * 1)
#define	CGSIX_THC_OFFSET	0x301000
#define	CGSIX_THC_SIZE		(sizeof(u_int32_t) * 640)
#define	CGSIX_FBC_OFFSET	0x700000
#define	CGSIX_FBC_SIZE		0x1000
#define	CGSIX_TEC_OFFSET	0x701000
#define	CGSIX_TEC_SIZE		(sizeof(u_int32_t) * 3)
#define	CGSIX_VID_OFFSET	0x800000
#define	CGSIX_VID_SIZE		(1024 * 1024)

#define	CG6_FHC			0x0		/* fhc register */

/* bits in FHC register */
#define	FHC_FBID_MASK		0xff000000	/* frame buffer id */
#define	FHC_FBID_SHIFT		24
#define	FHC_REV_MASK		0x00f00000	/* revision */
#define	FHC_REV_SHIFT		20
#define	FHC_FROP_DISABLE	0x00080000	/* disable fast rasterop */
#define	FHC_ROW_DISABLE		0x00040000	/* ??? */
#define	FHC_SRC_DISABLE		0x00020000	/* ??? */
#define	FHC_DST_DISABLE		0x00010000	/* disable dst cache */
#define	FHC_RESET		0x00008000	/* ??? */
#define	FHC_LEBO		0x00002000	/* set little endian order */
#define	FHC_RES_MASK		0x00001800	/* resolution: */
#define	FHC_RES_1024		0x00000000	/*  1024x768 */
#define	FHC_RES_1152		0x00000800	/*  1152x900 */
#define	FHC_RES_1280		0x00001000	/*  1280x1024 */
#define	FHC_RES_1600		0x00001800	/*  1600x1200 */
#define	FHC_CPU_MASK		0x00000600	/* cpu type: */
#define	FHC_CPU_SPARC		0x00000000	/*  sparc */
#define	FHC_CPU_68020		0x00000200	/*  68020 */
#define	FHC_CPU_386		0x00000400	/*  i386 */
#define	FHC_TEST		0x00000100	/* test window */
#define	FHC_TESTX_MASK		0x000000f0	/* test window X */
#define	FHC_TESTX_SHIFT		4
#define	FHC_TESTY_MASK		0x0000000f	/* test window Y */
#define	FHC_TESTY_SHIFT		0

struct cgsix_fbc {
	u_int32_t		fbc_xxx0[1];
	u_int32_t		fbc_mode;	/* mode setting */
	u_int32_t		fbc_clip;	/* ??? */
	u_int32_t		fbc_xxx1[1];
	u_int32_t		fbc_s;		/* global status */
	u_int32_t		fbc_draw;	/* drawing pipeline status */
	u_int32_t		fbc_blit;	/* blitter status */
	u_int32_t		fbc_xxx2[25];
	u_int32_t		fbc_x0;		/* blitter, src llx */
	u_int32_t		fbc_y0;		/* blitter, src lly */
	u_int32_t		fbc_xxx3[2];
	u_int32_t		fbc_x1;		/* blitter, src urx */
	u_int32_t		fbc_y1;		/* blitter, src ury */
	u_int32_t		fbc_xxx4[2];
	u_int32_t		fbc_x2;		/* blitter, dst llx */
	u_int32_t		fbc_y2;		/* blitter, dst lly */
	u_int32_t		fbc_xxx5[2];
	u_int32_t		fbc_x3;		/* blitter, dst urx */
	u_int32_t		fbc_y3;		/* blitter, dst ury */
	u_int32_t		fbc_xxx6[2];
	u_int32_t		fbc_offx;	/* x offset for drawing */
	u_int32_t		fbc_offy;	/* y offset for drawing */
	u_int32_t		fbc_xxx7[6];
	u_int32_t		fbc_clipminx;	/* clip rectangle llx */
	u_int32_t		fbc_clipminy;	/* clip rectangle lly */
	u_int32_t		fbc_xxx8[2];
	u_int32_t		fbc_clipmaxx;	/* clip rectangle urx */
	u_int32_t		fbc_clipmaxy;	/* clip rectangle ury */
	u_int32_t		fbc_xxx9[2];
	u_int32_t		fbc_fg;		/* fg value for rop */
	u_int32_t		fbc_xxx10[1];
	u_int32_t		fbc_alu;	/* operation */
	u_int32_t		fbc_xxx11[509];
	u_int32_t		fbc_arectx;	/* rectangle drawing, x coord */
	u_int32_t		fbc_arecty;	/* rectangle drawing, y coord */
};

#define FBC_MODE_MASK	(						\
	  0x00300000 /* GX_BLIT_ALL */					\
	| 0x00060000 /* GX_MODE_ALL */					\
	| 0x00018000 /* GX_DRAW_ALL */					\
	| 0x00006000 /* GX_BWRITE0_ALL */				\
	| 0x00001800 /* GX_BWRITE1_ALL */				\
	| 0x00000600 /* GX_BREAD_ALL */					\
	| 0x00000180 /* GX_BDISP_ALL */					\
)

#define	FBC_MODE_VAL	(						\
	  0x00200000 /* GX_BLIT_SRC */					\
	| 0x00020000 /* GX_MODE_COLOR8 */				\
	| 0x00008000 /* GX_DRAW_RENDER */				\
	| 0x00002000 /* GX_BWRITE0_ENABLE */				\
	| 0x00001000 /* GX_BWRITE1_DISABLE */				\
	| 0x00000200 /* GX_BREAD_0 */					\
	| 0x00000080 /* GX_BDISP_0 */					\
)

#define	FBC_S_GXINPROGRESS	0x10000000	/* drawing in progress */

#define	FBC_BLIT_UNKNOWN	0x80000000	/* ??? */
#define	FBC_BLIT_GXFULL		0x20000000	/* queue is full */

#define	FBC_DRAW_UNKNOWN	0x80000000	/* ??? */
#define	FBC_DRAW_GXFULL		0x20000000

/* Value for the alu register for screen-to-screen copies */
#define FBC_ALU_COPY    (						\
	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
	| 0x0000cccc /* ALU = src */					\
)

/* Value for the alu register for region fills */
#define FBC_ALU_FILL	(						\
	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
	| 0x0000ff00 /* ALU = fg color */				\
)

/* Value for the alu register for toggling an area */
#define FBC_ALU_FLIP	(						\
	  0x80000000 /* GX_PLANE_ONES (ignore planemask register) */	\
	| 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */	\
	| 0x00800000 /* GX_ATTR_SUPP (function unknown) */		\
	| 0x00000000 /* GX_RAST_BOOL (function unknown) */		\
	| 0x00000000 /* GX_PLOT_PLOT (function unknown) */		\
	| 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */		\
	| 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */	\
	| 0x00005555 /* ALU = ~dst */					\
)

/*
 * The layout of the THC.
 */
struct cgsix_thc {
	u_int32_t	thc_xxx0[512];	/* ??? */
	u_int32_t	thc_hsync1;	/* horizontal sync timing */
	u_int32_t	thc_hsync2;	/* more hsync timing */
	u_int32_t	thc_hsync3;	/* yet more hsync timing */
	u_int32_t	thc_vsync1;	/* vertical sync timing */
	u_int32_t	thc_vsync2;	/* only two of these */
	u_int32_t	thc_refresh;	/* refresh counter */
	u_int32_t	thc_misc;	/* miscellaneous control & status */
	u_int32_t	thc_xxx1[56];	/* ??? */
	u_int32_t	thc_cursxy;	/* cursor x,y position (16 bits each) */
	u_int32_t	thc_cursmask[32]; /* cursor mask bits */
	u_int32_t	thc_cursbits[32]; /* what to show where mask enabled */
};

/* cursor x/y position for 'off' */
#define	THC_CURSOFF		((65536-32) | ((65536-32) << 16))

#define	THC_MISC_REV_M		0x000f0000	/* chip revision */
#define	THC_MISC_REV_S		16
#define	THC_MISC_RESET		0x00001000	/* reset */
#define	THC_MISC_VIDEN		0x00000400	/* video enable */
#define	THC_MISC_SYNC		0x00000200	/* not sure what ... */
#define	THC_MISC_VSYNC		0x00000100	/* ... these really are */
#define	THC_MISC_SYNCEN		0x00000080	/* sync enable */
#define	THC_MISC_CURSRES	0x00000040	/* cursor resolution */
#define	THC_MISC_INTEN		0x00000020	/* v.retrace intr enable */
#define	THC_MISC_INTR		0x00000010	/* intr pending/ack */
#define	THC_MISC_CYCLS		0x0000000f	/* cycles before transfer */

/*
 * Partial description of TEC (needed to get around FHC rev 1 bugs).
 */
struct cgsix_tec_xxx {
	u_int32_t	tec_mv;		/* matrix stuff */
	u_int32_t	tec_clip;	/* clipping stuff */
	u_int32_t	tec_vdc;	/* ??? */
};


code:
/*	$OpenBSD: cgthree.c,v 1.37 2015/03/28 19:07:07 miod Exp $	*/
/*	$NetBSD: cgthree.c,v 1.33 1997/05/24 20:16:11 pk Exp $ */

/*
 * Copyright (c) 2002 Miodrag Vallat.  All rights reserved.
 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Effort sponsored in part by the Defense Advanced Research Projects
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
 *
 *
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)cgthree.c	8.2 (Berkeley) 10/30/93
 */

/*
 * Color display (cgthree) driver.
 * Works with the real Sun hardware, as well as various clones from Tatung,
 * Integrix (S20), and the Vigra VS10-EK.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/cpu.h>
#include <machine/conf.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <machine/fbvar.h>

#include <sparc/dev/btreg.h>
#include <sparc/dev/btvar.h>
#include <sparc/dev/cgthreereg.h>

/* per-display variables */
struct cgthree_softc {
	struct	sunfb sc_sunfb;		/* common base part */
	struct rom_reg	sc_phys;	/* phys address description */
	volatile struct fbcontrol *sc_fbc;	/* Brooktree registers */
	union	bt_cmap sc_cmap;	/* Brooktree color map */
	struct intrhand sc_ih;
};

void	cgthree_burner(void *, u_int, u_int);
int	cgthree_intr(void *);
int	cgthree_ioctl(void *, u_long, caddr_t, int, struct proc *);
static __inline__
void	cgthree_loadcmap_deferred(struct cgthree_softc *, u_int, u_int);
paddr_t	cgthree_mmap(void *, off_t, int);
void	cgthree_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);

struct wsdisplay_accessops cgthree_accessops = {
	.ioctl = cgthree_ioctl,
	.mmap = cgthree_mmap,
	.burn_screen = cgthree_burner
};

int	cgthreematch(struct device *, void *, void *);
void	cgthreeattach(struct device *, struct device *, void *);

struct cfattach cgthree_ca = {
	sizeof (struct cgthree_softc), cgthreematch, cgthreeattach
};

struct cfdriver cgthree_cd = {
	NULL, "cgthree", DV_DULL
};

/* Video control parameters */
struct cg3_videoctrl {
	u_int8_t	sense;
	u_int8_t	vctrl[12];
} cg3_videoctrl[] = {
	{	/* cpd-1790 */
		FBS_1152X900 | FBS_ID_COLOR,
		{ 0xbb, 0x2b, 0x04, 0x14, 0xae, 0x03,
		  0xa8, 0x24, 0x01, 0x05, 0xff, 0x01 },
	},
	{	/* gdm-20e20 */
		FBS_1280X1024 | FBS_ID_COLOR,
		{ 0xb7, 0x27, 0x03, 0x0f, 0xae, 0x03,
		  0xae, 0x2a, 0x01, 0x09, 0xff, 0x01 },
	},
	{	/* defaults, should be last */
		0xff,
		{ 0xbb, 0x2b, 0x03, 0x0b, 0xb3, 0x03,
		  0xaf, 0x2b, 0x02, 0x0a, 0xff, 0x01 },
	},
};

int
cgthreematch(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
	    strcmp("cgRDI", ra->ra_name))
		return (0);

	if (ca->ca_bustype != BUS_SBUS)
		return (0);

	return (1);
}

void
cgthreeattach(struct device *parent, struct device *self, void *args)
{
	struct cgthree_softc *sc = (struct cgthree_softc *)self;
	struct confargs *ca = args;
	int node, pri, isrdi = 0, i;
	volatile struct bt_regs *bt;
	int isconsole;
	char *nam;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	node = ca->ca_ra.ra_node;

	if (strcmp(ca->ca_ra.ra_name, "cgRDI") == 0) {
		isrdi = 1;
		nam = "cgRDI";
	} else
		nam = getpropstring(node, "model");

	if (nam != NULL && *nam != '\0')
		printf("%s, ", nam);

	isconsole = node == fbnode;

	sc->sc_fbc = (volatile struct fbcontrol *)
	    mapiodev(ca->ca_ra.ra_reg, CG3REG_REG,
		     sizeof(struct fbcontrol));

	/* Transfer video magic to board, if it's not running */
	if (isrdi == 0 && (sc->sc_fbc->fbc_ctrl & FBC_TIMING) == 0)
		for (i = 0; i < nitems(cg3_videoctrl); i++) {
			volatile struct fbcontrol *fbc = sc->sc_fbc;
			if (cg3_videoctrl[i].sense == 0xff ||
			    (fbc->fbc_status & FBS_MSENSE) ==
			     cg3_videoctrl[i].sense) {
				int j;
#ifdef DEBUG
				printf(" (setting video ctrl)");
#endif
				for (j = 0; j < 12; j++)
					fbc->fbc_vcontrol[j] =
						cg3_videoctrl[i].vctrl[j];
				fbc->fbc_ctrl |= FBC_TIMING;
				break;
			}
		}

	sc->sc_phys = ca->ca_ra.ra_reg[0];

	sc->sc_ih.ih_fun = cgthree_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	/* enable video */
	cgthree_burner(sc, 1, 0);
	bt = &sc->sc_fbc->fbc_dac;
	BT_INIT(bt, 0);

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM,
	    round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, isconsole);
}

int
cgthree_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct cgthree_softc *sc = v;
	struct wsdisplay_fbinfo *wdf;
	struct wsdisplay_cmap *cm;
	int error;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNCG3;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width  = sc->sc_sunfb.sf_width;
		wdf->depth  = sc->sc_sunfb.sf_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		break;

	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_getcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		break;

	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		error = bt_putcmap(&sc->sc_cmap, cm);
		if (error)
			return (error);
		cgthree_loadcmap_deferred(sc, cm->index, cm->count);
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	case WSDISPLAYIO_GCURPOS:
	case WSDISPLAYIO_SCURPOS:
	case WSDISPLAYIO_GCURMAX:
	case WSDISPLAYIO_GCURSOR:
	case WSDISPLAYIO_SCURSOR:
	default:
		return (-1);	/* not supported yet */
        }

	return (0);
}

paddr_t
cgthree_mmap(void *v, off_t offset, int prot)
{
	struct cgthree_softc *sc = v;

	if (offset & PGOFSET)
		return (-1);

	if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
		return (REG2PHYS(&sc->sc_phys,
		    CG3REG_MEM + offset) | PMAP_NC);
	}

	return (-1);
}

void
cgthree_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
{
	struct cgthree_softc *sc = v;

	bt_setcolor(&sc->sc_cmap, &sc->sc_fbc->fbc_dac, index, r, g, b, 0);
}

static __inline__ void
cgthree_loadcmap_deferred(struct cgthree_softc *sc, u_int start, u_int ncolors)
{

	sc->sc_fbc->fbc_ctrl |= FBC_IENAB;
}

void
cgthree_burner(void *v, u_int on, u_int flags)
{
	struct cgthree_softc *sc = v;
	int s;

	s = splhigh();
	if (on)
		sc->sc_fbc->fbc_ctrl |= FBC_VENAB | FBC_TIMING;
	else {
		sc->sc_fbc->fbc_ctrl &= ~FBC_VENAB;
		if (flags & WSDISPLAY_BURN_VBLANK)
			sc->sc_fbc->fbc_ctrl &= ~FBC_TIMING;
	}
	splx(s);
}

int
cgthree_intr(void *v)
{
	struct cgthree_softc *sc = v;

	if (!ISSET(sc->sc_fbc->fbc_ctrl, FBC_IENAB) ||
	    !ISSET(sc->sc_fbc->fbc_status, FBS_INTR)) {
		/* Not expecting an interrupt, it's not for us. */
		return (0);
	}

	/* Acknowledge the interrupt and disable it. */
	sc->sc_fbc->fbc_ctrl &= ~FBC_IENAB;

	bt_loadcmap(&sc->sc_cmap, &sc->sc_fbc->fbc_dac, 0, 256, 0);
	return (1);
}


code:
/*	$OpenBSD: cgthreereg.h,v 1.4 2003/06/02 23:27:54 millert Exp $	*/
/*	$NetBSD: cgthreereg.h,v 1.5 1996/02/27 00:14:17 pk Exp $ */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)cgthreereg.h	8.2 (Berkeley) 10/30/93
 */

/*
 * cgthree display registers.  Much like bwtwo registers, except that
 * there is a Brooktree Video DAC in there (so we also use btreg.h).
 */

/* offsets */
#define	CG3REG_ID	0
#define	CG3REG_REG	0x400000
#define	CG3REG_MEM	0x800000

/* same, but for gdb */
struct cgthree_all {
	long	ba_id;			/* ID = 0xfe010104 on my IPC */
	char	ba_xxx0[0x400000-4];
	struct	fbcontrol ba_fbc;	/* Brooktree regs (+ misc control) */
	char	ba_xxx1[0x400000-sizeof(struct fbcontrol)];
	char	ba_ram[4096];		/* actually larger */
};


code:
/*	$OpenBSD: cgtwelve.c,v 1.20 2015/03/28 19:07:07 miod Exp $	*/

/*
 * Copyright (c) 2002, 2003 Miodrag Vallat.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * cgtwelve (GS) accelerated 24-bit framebuffer driver.
 *
 * Enough experiments and SMI's cg12reg.h made this possible.
 */

/*
 * The cgtwelve framebuffer is a 3-slot SBUS card, that will fit only in
 * SPARCstation 1, 1+, 2 and 5, or in an xbox SBUS extension.
 *
 * It is a 24-bit 3D accelerated framebuffer made by Matrox, featuring 4MB
 * (regular model) or 8MB (high-res model) of video memory, a complex
 * windowing engine, double buffering modes, three video planes (overlay,
 * 8 bit and 24 bit color), and a lot of colormap combinations.
 *
 * All of this is driven by a set of three Bt462 ramdacs (latched unless
 * explicitely programmed), and a couple of other Matrox-specific chips.
 *
 * XXX The high res card is untested.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/tty.h>
#include <sys/conf.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/cpu.h>
#include <machine/conf.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <machine/fbvar.h>

#include <sparc/dev/cgtwelvereg.h>

#include <dev/cons.h>	/* for prom console hook */

/* per-display variables */
struct cgtwelve_softc {
	struct	sunfb	sc_sunfb;	/* common base device */
	struct	rom_reg sc_phys;

	volatile struct cgtwelve_dpu *sc_dpu;
	volatile struct cgtwelve_apu *sc_apu;
	volatile struct cgtwelve_dac *sc_ramdac;	/* RAMDAC registers */
	volatile u_char *sc_overlay;	/* overlay or enable plane */
	volatile u_long *sc_inten;	/* true color plane */

	int	sc_highres;
	int	sc_isconsole;
};

int	cgtwelve_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t	cgtwelve_mmap(void *, off_t, int);
void	cgtwelve_prom(struct cgtwelve_softc *);
static __inline__
void	cgtwelve_ramdac_wraddr(struct cgtwelve_softc *, u_int32_t);
void	cgtwelve_reset(struct cgtwelve_softc *, int);

struct wsdisplay_accessops cgtwelve_accessops = {
	.ioctl = cgtwelve_ioctl,
	.mmap = cgtwelve_mmap
};

int	cgtwelvematch(struct device *, void *, void *);
void	cgtwelveattach(struct device *, struct device *, void *);
int	cgtwelveactivate(struct device *, int);

struct cfattach cgtwelve_ca = {
	sizeof(struct cgtwelve_softc), cgtwelvematch, cgtwelveattach,
	NULL, cgtwelveactivate
};

struct cfdriver cgtwelve_cd = {
	NULL, "cgtwelve", DV_DULL
};

int
cgtwelvematch(struct device *parent, void *vcf, void *aux)
{
	struct cfdata *cf = vcf;
	struct confargs *ca = aux;
	struct romaux *ra = &ca->ca_ra;

	if (strcmp(cf->cf_driver->cd_name, ra->ra_name) != 0)
		return (0);

	return (1);
}

void
cgtwelveattach(struct device *parent, struct device *self, void *args)
{
	struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
	struct confargs *ca = args;
	int node;
	char *ps;

	node = ca->ca_ra.ra_node;

	printf(": %s", getpropstring(node, "model"));
	ps = getpropstring(node, "dev_id");
	if (*ps != '\0')
		printf(" (%s)", ps);
	printf("\n");

	sc->sc_isconsole = node == fbnode;

	sc->sc_phys = ca->ca_ra.ra_reg[0];

	/*
	 * Map registers
	 */
	sc->sc_dpu = (struct cgtwelve_dpu *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_DPU, sizeof(struct cgtwelve_dpu));
	sc->sc_apu = (struct cgtwelve_apu *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_APU, sizeof(struct cgtwelve_apu));
	sc->sc_ramdac = (struct cgtwelve_dac *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_DAC, sizeof(struct cgtwelve_dac));

	/*
	 * The console is using the 1-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 */
	fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT,
	    node, ca->ca_bustype);
	sc->sc_sunfb.sf_depth = 1;
	sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height *
	    sc->sc_sunfb.sf_linebytes;

	sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR;

	/*
	 * Map planes
	 */
	sc->sc_overlay = mapiodev(ca->ca_ra.ra_reg,
	    sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0,
	    round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR :
	        CG12_SIZE_OVERLAY));
	sc->sc_inten = mapiodev(ca->ca_ra.ra_reg,
	    sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN,
	    round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR :
	        CG12_SIZE_COLOR24));

	/* reset cursor & frame buffer controls */
	sc->sc_sunfb.sf_depth = 0;	/* force action */
	cgtwelve_reset(sc, 1);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay;
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, sc->sc_isconsole);

	if (sc->sc_isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	printf("%s: %dx%d", self->dv_xname,
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
	ps = getpropstring(node, "ucoderev");
	if (*ps != '\0')
		printf(", microcode rev. %s", ps);
	printf("\n");

	fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, sc->sc_isconsole);
}

int
cgtwelveactivate(struct device *self, int act)
{
	struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
	int ret = 0;

	switch (act) {
	case DVACT_POWERDOWN:
		if (sc->sc_isconsole)
			cgtwelve_prom(sc);
		break;
	}

	return (ret);
}

int
cgtwelve_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct cgtwelve_softc *sc = dev;
	struct wsdisplay_fbinfo *wdf;

	/*
	 * Note that, although the emulation (text) mode is running in the
	 * overlay plane, we advertize the frame buffer as the full-blown
	 * 32-bit beast it is.
	 */
	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNCG12;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width = sc->sc_sunfb.sf_width;
		wdf->depth = 32;
		wdf->cmsize = 0;
		break;
	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
		*(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = sc->sc_sunfb.sf_linebytes * 32;
		break;

	case WSDISPLAYIO_GETCMAP:
	case WSDISPLAYIO_PUTCMAP:
		break;

	case WSDISPLAYIO_SMODE:
		if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
			/* Back from X11 to text mode */
			cgtwelve_reset(sc, 1);
		} else {
			/* Starting X11, switch to 32 bit mode */
			cgtwelve_reset(sc, 32);
		}
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	default:
		return (-1);	/* not supported yet */
	}

	return (0);
}

void
cgtwelve_reset(struct cgtwelve_softc *sc, int depth)
{
	u_int32_t c;

	if (sc->sc_sunfb.sf_depth != depth) {
		if (depth == 1) {
			/*
			 * Select the enable plane as sc_overlay, and fill it.
			 */
			sc->sc_apu->hpage = sc->sc_highres ?
			    CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE;
			sc->sc_apu->haccess = CG12_HACCESS_ENABLE;
			sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE;
			sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE;
			sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE;

			memset((void *)sc->sc_overlay, 0xff, sc->sc_highres ?
			    CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE);

			/*
			 * Select the overlay plane as sc_overlay.
			 */
			sc->sc_apu->hpage = sc->sc_highres ?
			    CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY;
			sc->sc_apu->haccess = CG12_HACCESS_OVERLAY;
			sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY;
			sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY;
			sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY;

			/*
			 * Upload a strict mono colormap, or the text
			 * upon returning from 32 bit mode would appear
			 * as (slightly dark) white on white.
			 */
			cgtwelve_ramdac_wraddr(sc, 0);
			sc->sc_ramdac->color = 0x00000000;
			for (c = 1; c < 256; c++)
				sc->sc_ramdac->color = 0x00ffffff;
		} else {
			/*
			 * Select the overlay plane as sc_overlay.
			 */
			sc->sc_apu->hpage = sc->sc_highres ?
			    CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY;
			sc->sc_apu->haccess = CG12_HACCESS_OVERLAY;
			sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY;
			sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY;
			sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY;

			/*
			 * Do not attempt to somewhat preserve screen
			 * contents - reading the overlay plane and writing
			 * to the color plane at the same time is not
			 * reliable, and allocating memory to save a copy
			 * of the overlay plane would be awful.
			 */
			bzero((void *)sc->sc_overlay, sc->sc_highres ?
			    CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY);

			/*
			 * Select the enable plane as sc_overlay, and clear it.
			 */
			sc->sc_apu->hpage = sc->sc_highres ?
			    CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE;
			sc->sc_apu->haccess = CG12_HACCESS_ENABLE;
			sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE;
			sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE;
			sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE;

			bzero((void *)sc->sc_overlay, sc->sc_highres ?
			    CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE);

			/*
			 * Select the intensity (color) plane, and clear it.
			 */
			sc->sc_apu->hpage = sc->sc_highres ?
			    CG12_HPAGE_24BIT_HR : CG12_HPAGE_24BIT;
			sc->sc_apu->haccess = CG12_HACCESS_24BIT;
			sc->sc_dpu->pln_sl_host = CG12_PLN_SL_24BIT;
			sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_24BIT;
			sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_24BIT;

			memset((void *)sc->sc_inten, 0x00ffffff,
			    sc->sc_highres ?
			      CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24);

			/*
			 * Use a direct colormap (ramp)
			 */
			cgtwelve_ramdac_wraddr(sc, 0);
			for (c = 0; c < 256; c++)
				sc->sc_ramdac->color = c | (c << 8) | (c << 16);
		}
	}

	sc->sc_sunfb.sf_depth = depth;
}

paddr_t
cgtwelve_mmap(void *v, off_t offset, int prot)
{
	struct cgtwelve_softc *sc = v;

	if (offset & PGOFSET || offset < 0)
		return (-1);

	/*
	 * Note that mmap() will invoke this function only if we are NOT
	 * in emulation mode, so we can assume 32 bit mode safely here.
	 */
	if (offset < sc->sc_sunfb.sf_fbsize * 32) {
		return (REG2PHYS(&sc->sc_phys,
		    (sc->sc_highres ? CG12_OFF_INTEN_HR :
		    CG12_OFF_INTEN) + offset) | PMAP_NC);
	}

	return (-1);
}

/*
 * Simple Bt462 programming routines.
 */

static __inline__ void
cgtwelve_ramdac_wraddr(struct cgtwelve_softc *sc, u_int32_t addr)
{
	sc->sc_ramdac->addr_lo = (addr & 0xff);
	sc->sc_ramdac->addr_hi = ((addr >> 8) & 0xff);
}

/*
 * Shutdown hook used to restore PROM-compatible video mode on shutdown,
 * so that the PROM prompt is visible again.
 */
void
cgtwelve_prom(struct cgtwelve_softc *sc)
{
	extern struct consdev consdev_prom;

	if (sc->sc_sunfb.sf_depth != 1) {
		cgtwelve_reset(sc, 1);

		/*
		 * Go back to prom output for the last few messages, so they
		 * will be displayed correctly.
		 */
		cn_tab = &consdev_prom;
	}
}


code:
/*	$OpenBSD: cgtwelvereg.h,v 1.2 2006/07/20 11:23:49 martin Exp $	*/

/*
 * Copyright (c) 2002 Miodrag Vallat.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * cgtwelve (GS) accelerated 24-bit framebuffer driver.
 *
 * Memory layout and scarce register information from SMI's cg12reg.h
 */

#define	CG12_HEIGHT		900
#define	CG12_WIDTH		1152

#define	CG12_HEIGHT_HR		1024
#define	CG12_WIDTH_HR		1280

/* offsets from the card mapping */
#define	CG12_OFF_DPU		0x040100
#define	CG12_OFF_APU		0x040200
#define	CG12_OFF_DAC		0x040300
#define	CG12_OFF_OVERLAY0	0x700000
#define	CG12_OFF_OVERLAY1	0x780000
#define	CG12_OFF_INTEN		0xc00000

#define	CG12_OFF_OVERLAY0_HR	0xe00000
#define	CG12_OFF_OVERLAY1_HR	0xf00000
#define	CG12_OFF_INTEN_HR	0x800000

/* sizes of various parts */
#define	CG12_SIZE_DPU		0x000100
#define	CG12_SIZE_APU		0x000100
#define	CG12_SIZE_DAC		0x000400
#define	CG12_SIZE_OVERLAY	0x020000
#define	CG12_SIZE_ENABLE	0x020000
#define	CG12_SIZE_COLOR8	0x100000
#define	CG12_SIZE_COLOR24	0x400000

#define	CG12_SIZE_OVERLAY_HR	0x030000
#define	CG12_SIZE_ENABLE_HR	0x030000
#define	CG12_SIZE_COLOR8_HR	0x180000
#define	CG12_SIZE_COLOR24_HR	0x600000

/*
 * The "direct port access" register constants.
 * All HACCESS values include noHSTXY, noHCLIP, and SWAP.
 */

#define	CG12_HPAGE_OVERLAY	0x00000700	/* overlay page */
#define	CG12_HPAGE_OVERLAY_HR	0x00000e00
#define	CG12_HACCESS_OVERLAY	0x00000020	/* 1bit/pixel */
#define	CG12_PLN_SL_OVERLAY	0x00000017	/* plane 23 */
#define	CG12_PLN_WR_OVERLAY	0x00800000	/* write mask */
#define	CG12_PLN_RD_OVERLAY	0xffffffff	/* read mask */

#define	CG12_HPAGE_ENABLE	0x00000700	/* overlay page */
#define	CG12_HPAGE_ENABLE_HR	0x00000e00
#define	CG12_HACCESS_ENABLE	0x00000020	/* 1bit/pixel */
#define	CG12_PLN_SL_ENABLE	0x00000016	/* plane 22 */
#define	CG12_PLN_WR_ENABLE	0x00400000
#define	CG12_PLN_RD_ENABLE	0xffffffff

#define	CG12_HPAGE_24BIT	0x00000500	/* intensity page */
#define	CG12_HPAGE_24BIT_HR	0x00000a00
#define	CG12_HACCESS_24BIT	0x00000025	/* 32bits/pixel */
#define	CG12_PLN_SL_24BIT	0x00000000	/* planes 0-31 */
#define	CG12_PLN_WR_24BIT	0x00ffffff
#define	CG12_PLN_RD_24BIT	0x00ffffff

#define	CG12_HPAGE_8BIT		0x00000500	/* intensity page */
#define	CG12_HPAGE_8BIT_HR	0x00000a00
#define	CG12_HACCESS_8BIT	0x00000023	/* 8bits/pixel */
#define	CG12_PLN_SL_8BIT	0x00000000	/* planes 0-7 */
#define	CG12_PLN_WR_8BIT	0x00ffffff
#define	CG12_PLN_RD_8BIT	0x000000ff

#define	CG12_HPAGE_WID		0x00000700	/* overlay page */
#define	CG12_HPAGE_WID_HR	0x00000e00
#define	CG12_HACCESS_WID	0x00000023	/* 8bits/pixel */
#define	CG12_PLN_SL_WID		0x00000010	/* planes 16-23 */
#define	CG12_PLN_WR_WID		0x003f0000
#define	CG12_PLN_RD_WID		0x003f0000

#define	CG12_HPAGE_ZBUF		0x00000000	/* depth page */
#define	CG12_HPAGE_ZBUF_HR	0x00000000
#define	CG12_HACCESS_ZBUF	0x00000024	/* 16bits/pixel */
#define	CG12_PLN_SL_ZBUF	0x00000060
#define	CG12_PLN_WR_ZBUF	0xffffffff
#define	CG12_PLN_RD_ZBUF	0xffffffff

/* Direct Port Unit */
struct cgtwelve_dpu {
	u_int32_t	r[8];
	u_int32_t	reload_ctl;
	u_int32_t	reload_stb;
	u_int32_t	alu_ctl;
	u_int32_t	blu_ctl;
	u_int32_t	control;
	u_int32_t	xleft;
	u_int32_t	shift0;
	u_int32_t	shift1;
	u_int32_t	zoom;
	u_int32_t	bsr;
	u_int32_t	color0;
	u_int32_t	color1;
	u_int32_t	compout;
	u_int32_t	pln_rd_msk_host;
	u_int32_t	pln_wr_msk_host;
	u_int32_t	pln_rd_msk_local;
	u_int32_t	pln_wr_msk_local;
	u_int32_t	scis_ctl;
	u_int32_t	csr;
	u_int32_t	pln_reg_sl;
	u_int32_t	pln_sl_host;
	u_int32_t	pln_sl_local0;
	u_int32_t	pln_sl_local1;
	u_int32_t	broadcast;
};

/* APU */
struct cgtwelve_apu {
	u_int32_t	imsg0;
	u_int32_t	msg0;
	u_int32_t	imsg1;
	u_int32_t	msg1;
	u_int32_t	ien0;
	u_int32_t	ien1;
	u_int32_t	iclear;
	u_int32_t	istatus;
	u_int32_t	cfcnt;
	u_int32_t	cfwptr;
	u_int32_t	cfrptr;
	u_int32_t	cfilev0;
	u_int32_t	cfilev1;
	u_int32_t	rfcnt;
	u_int32_t	rfwptr;
	u_int32_t	rfrptr;
	u_int32_t	rfilev0;
	u_int32_t	rfilev1;
	u_int32_t	size;
	u_int32_t	res0;
	u_int32_t	res1;
	u_int32_t	res2;
	u_int32_t	haccess;
	u_int32_t	hpage;
	u_int32_t	laccess;
	u_int32_t	lpage;
	u_int32_t	maccess;
	u_int32_t	ppage;
	u_int32_t	dwg_ctl;
	u_int32_t	sam;
	u_int32_t	sgn;
	u_int32_t	length;
	u_int32_t	dwg[8];
	u_int32_t	reload_ctl;
	u_int32_t	reload_stb;
	u_int32_t	c_xleft;
	u_int32_t	c_ytop;
	u_int32_t	c_xright;
	u_int32_t	c_ybot;
	u_int32_t	f_xleft;
	u_int32_t	f_xright;
	u_int32_t	x_dst;
	u_int32_t	y_dst;
	u_int32_t	dst_ctl;
	u_int32_t	morigin;
	u_int32_t	vsg_ctl;
	u_int32_t	h_sync;
	u_int32_t	hblank;
	u_int32_t	v_sync;
	u_int32_t	vblank;
	u_int32_t	vdpyint;
	u_int32_t	vssyncs;
	u_int32_t	hdelays;
	u_int32_t	stdaddr;
	u_int32_t	hpitches;
	u_int32_t	zoom;
	u_int32_t	test;
};

struct cgtwelve_dac
{
	u_int32_t	addr_lo;
	u_int8_t	pad1[0x100 - 4];
	u_int32_t	addr_hi;
	u_int8_t	pad2[0x100 - 4];
	u_int32_t	control;
	u_int8_t	pad3[0x100 - 4];
	u_int32_t	color;
	u_int8_t	pad4[0x100 - 4];
};