xref: /original-bsd/sys/sparc/sbus/cgthree.c (revision bf551665)
146883914Storek /*
21fd2d6dbSbostic  * Copyright (c) 1992, 1993
31fd2d6dbSbostic  *	The Regents of the University of California.  All rights reserved.
446883914Storek  *
546883914Storek  * This software was developed by the Computer Systems Engineering group
646883914Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
746883914Storek  * contributed to Berkeley.
846883914Storek  *
9552ae0faSbostic  * All advertising materials mentioning features or use of this software
10552ae0faSbostic  * must display the following acknowledgement:
11552ae0faSbostic  *	This product includes software developed by the University of
128939e7d1Storek  *	California, Lawrence Berkeley Laboratory.
13552ae0faSbostic  *
1446883914Storek  * %sccs.include.redist.c%
1546883914Storek  *
16*bf551665Storek  *	@(#)cgthree.c	8.2 (Berkeley) 10/30/93
1746883914Storek  *
18*bf551665Storek  * from: $Header: cgthree.c,v 1.8 93/10/31 05:09:24 torek Exp $
1946883914Storek  */
2046883914Storek 
2146883914Storek /*
2246883914Storek  * color display (cgthree) driver.
2346883914Storek  *
2446883914Storek  * Does not handle interrupts, even though they can occur.
25*bf551665Storek  *
26*bf551665Storek  * XXX should defer colormap updates to vertical retrace interrupts
2746883914Storek  */
2846883914Storek 
2946c886e9Sbostic #include <sys/param.h>
3046c886e9Sbostic #include <sys/buf.h>
3146c886e9Sbostic #include <sys/device.h>
3246c886e9Sbostic #include <sys/fbio.h>
3346c886e9Sbostic #include <sys/ioctl.h>
3446c886e9Sbostic #include <sys/malloc.h>
3546c886e9Sbostic #include <sys/mman.h>
3646c886e9Sbostic #include <sys/tty.h>
3746883914Storek 
3846c886e9Sbostic #include <machine/autoconf.h>
3946c886e9Sbostic #include <machine/pmap.h>
4046c886e9Sbostic #include <machine/fbvar.h>
4146883914Storek 
42*bf551665Storek #include <sparc/sbus/btreg.h>
43*bf551665Storek #include <sparc/sbus/btvar.h>
4446c886e9Sbostic #include <sparc/sbus/cgthreereg.h>
4546c886e9Sbostic #include <sparc/sbus/sbusvar.h>
4646883914Storek 
4746883914Storek /* per-display variables */
4846883914Storek struct cgthree_softc {
4946883914Storek 	struct	device sc_dev;		/* base device */
5046883914Storek 	struct	sbusdev sc_sd;		/* sbus device */
5146883914Storek 	struct	fbdevice sc_fb;		/* frame buffer device */
52*bf551665Storek 	volatile struct bt_regs *sc_bt;	/* Brooktree registers */
5346883914Storek 	caddr_t	sc_phys;		/* display RAM (phys addr) */
5446883914Storek 	int	sc_blanked;		/* true if blanked */
55*bf551665Storek 	union	bt_cmap sc_cmap;	/* Brooktree color map */
5646883914Storek };
5746883914Storek 
5846883914Storek /* autoconfiguration driver */
5946883914Storek static void	cgthreeattach(struct device *, struct device *, void *);
6046883914Storek struct cfdriver cgthreecd =
6146883914Storek     { NULL, "cgthree", matchbyname, cgthreeattach,
6246883914Storek       DV_DULL, sizeof(struct cgthree_softc) };
6346883914Storek 
6446883914Storek /* frame buffer generic driver */
6546883914Storek static void	cgthreeunblank(struct device *);
6646883914Storek static struct fbdriver cgthreefbdriver = { cgthreeunblank };
6746883914Storek 
6846883914Storek extern int fbnode;
6946883914Storek extern struct tty *fbconstty;
7046883914Storek extern int (*v_putc)();
7146883914Storek extern int nullop();
7246883914Storek static int cgthree_cnputc();
73*bf551665Storek 
74*bf551665Storek static void cgthreeloadcmap __P((struct cgthree_softc *, int, int));
7546883914Storek 
7646883914Storek #define	CGTHREE_MAJOR	55		/* XXX */
7746883914Storek 
7846883914Storek /*
7946883914Storek  * Attach a display.  We need to notice if it is the console, too.
8046883914Storek  */
8146883914Storek void
cgthreeattach(parent,self,args)8246883914Storek cgthreeattach(parent, self, args)
8346883914Storek 	struct device *parent, *self;
8446883914Storek 	void *args;
8546883914Storek {
8646883914Storek 	register struct cgthree_softc *sc = (struct cgthree_softc *)self;
8746883914Storek 	register struct sbus_attach_args *sa = args;
8846883914Storek 	register int node = sa->sa_ra.ra_node, ramsize, i;
89*bf551665Storek 	register volatile struct bt_regs *bt;
9046883914Storek 	register struct cgthree_all *p;
9146883914Storek 	int isconsole;
9246883914Storek 
9346883914Storek 	sc->sc_fb.fb_major = CGTHREE_MAJOR;	/* XXX to be removed */
9446883914Storek 
9546883914Storek 	sc->sc_fb.fb_driver = &cgthreefbdriver;
9646883914Storek 	sc->sc_fb.fb_device = &sc->sc_dev;
9746883914Storek 	/*
9846883914Storek 	 * The defaults below match my screen, but are not guaranteed
9946883914Storek 	 * to be correct as defaults go...
10046883914Storek 	 */
10146883914Storek 	sc->sc_fb.fb_type.fb_type = FBTYPE_SUN3COLOR;
10246883914Storek 	sc->sc_fb.fb_type.fb_width = getpropint(node, "width", 1152);
10346883914Storek 	sc->sc_fb.fb_type.fb_height = getpropint(node, "height", 900);
10446883914Storek 	sc->sc_fb.fb_linebytes = getpropint(node, "linebytes", 1152);
10546883914Storek 	ramsize = sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes;
10646883914Storek 	sc->sc_fb.fb_type.fb_depth = 8;
10746883914Storek 	sc->sc_fb.fb_type.fb_cmsize = 256;
10846883914Storek 	sc->sc_fb.fb_type.fb_size = ramsize;
10946883914Storek 	printf(": %s, %d x %d", getpropstring(node, "model"),
11046883914Storek 	    sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height);
11146883914Storek 
11246883914Storek 	/*
11346883914Storek 	 * When the ROM has mapped in a cgthree display, the address
11446883914Storek 	 * maps only the video RAM, so in any case we have to map the
11546883914Storek 	 * registers ourselves.  We only need the video RAM if we are
11646883914Storek 	 * going to print characters via rconsole.
11746883914Storek 	 */
11846883914Storek 	isconsole = node == fbnode && fbconstty != NULL;
11946883914Storek 	p = (struct cgthree_all *)sa->sa_ra.ra_paddr;
12046883914Storek 	if ((sc->sc_fb.fb_pixels = sa->sa_ra.ra_vaddr) == NULL && isconsole) {
12146883914Storek 		/* this probably cannot happen, but what the heck */
12246883914Storek 		sc->sc_fb.fb_pixels = mapiodev(p->ba_ram, ramsize);
12346883914Storek 	}
124*bf551665Storek 	sc->sc_bt = bt = (volatile struct bt_regs *)
125*bf551665Storek 	    mapiodev((caddr_t)&p->ba_btreg, sizeof(p->ba_btreg));
12646883914Storek 	sc->sc_phys = p->ba_ram;
12746883914Storek 
128*bf551665Storek 	/* grab initial (current) color map */
129*bf551665Storek 	bt->bt_addr = 0;
13046883914Storek 	for (i = 0; i < 256 * 3 / 4; i++)
131*bf551665Storek 		sc->sc_cmap.cm_chip[i] = bt->bt_cmap;
132*bf551665Storek 	/* make sure we are not blanked (see cgthreeunblank) */
133*bf551665Storek 	bt->bt_addr = 0x06;		/* command reg */
134*bf551665Storek 	bt->bt_ctrl = 0x73;		/* overlay plane */
135*bf551665Storek 	bt->bt_addr = 0x04;		/* read mask */
136*bf551665Storek 	bt->bt_ctrl = 0xff;		/* color planes */
13746883914Storek 
13846883914Storek 	if (isconsole) {
13946883914Storek 		printf(" (console)\n");
14046883914Storek #ifdef RCONSOLE
14146883914Storek 		rcons_init(&sc->sc_fb);
14246883914Storek #endif
14346883914Storek 	} else
14446883914Storek 		printf("\n");
14546883914Storek 	sbus_establish(&sc->sc_sd, &sc->sc_dev);
14646883914Storek 	if (node == fbnode)
14746883914Storek 		fb_attach(&sc->sc_fb);
14846883914Storek }
14946883914Storek 
15046883914Storek int
cgthreeopen(dev,flags,mode,p)15146883914Storek cgthreeopen(dev, flags, mode, p)
15246883914Storek 	dev_t dev;
15346883914Storek 	int flags, mode;
15446883914Storek 	struct proc *p;
15546883914Storek {
15646883914Storek 	int unit = minor(dev);
15746883914Storek 
15846883914Storek 	if (unit >= cgthreecd.cd_ndevs || cgthreecd.cd_devs[unit] == NULL)
15946883914Storek 		return (ENXIO);
16046883914Storek 	return (0);
16146883914Storek }
16246883914Storek 
16346883914Storek int
cgthreeclose(dev,flags,mode,p)16446883914Storek cgthreeclose(dev, flags, mode, p)
16546883914Storek 	dev_t dev;
16646883914Storek 	int flags, mode;
16746883914Storek 	struct proc *p;
16846883914Storek {
16946883914Storek 
17046883914Storek 	return (0);
17146883914Storek }
17246883914Storek 
17346883914Storek int
cgthreeioctl(dev,cmd,data,flags,p)17446883914Storek cgthreeioctl(dev, cmd, data, flags, p)
17546883914Storek 	dev_t dev;
17646883914Storek 	int cmd;
177*bf551665Storek 	register caddr_t data;
17846883914Storek 	int flags;
17946883914Storek 	struct proc *p;
18046883914Storek {
18146883914Storek 	register struct cgthree_softc *sc = cgthreecd.cd_devs[minor(dev)];
18246883914Storek 	register struct fbgattr *fba;
183*bf551665Storek 	int error;
18446883914Storek 
18546883914Storek 	switch (cmd) {
18646883914Storek 
18746883914Storek 	case FBIOGTYPE:
18846883914Storek 		*(struct fbtype *)data = sc->sc_fb.fb_type;
18946883914Storek 		break;
19046883914Storek 
19146883914Storek 	case FBIOGATTR:
19246883914Storek 		fba = (struct fbgattr *)data;
19346883914Storek 		fba->real_type = sc->sc_fb.fb_type.fb_type;
19446883914Storek 		fba->owner = 0;		/* XXX ??? */
19546883914Storek 		fba->fbtype = sc->sc_fb.fb_type;
19646883914Storek 		fba->sattr.flags = 0;
19746883914Storek 		fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
19846883914Storek 		fba->sattr.dev_specific[0] = -1;
19946883914Storek 		fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
20046883914Storek 		fba->emu_types[1] = -1;
20146883914Storek 		break;
20246883914Storek 
203*bf551665Storek 	case FBIOGETCMAP:
204*bf551665Storek 		return (bt_getcmap((struct fbcmap *)data, &sc->sc_cmap, 256));
20546883914Storek 
206*bf551665Storek 	case FBIOPUTCMAP:
207*bf551665Storek 		/* copy to software map */
208*bf551665Storek #define p ((struct fbcmap *)data)
209*bf551665Storek 		error = bt_putcmap(p, &sc->sc_cmap, 256);
210*bf551665Storek 		if (error)
211*bf551665Storek 			return (error);
212*bf551665Storek 		/* now blast them into the chip */
21346883914Storek 		/* XXX should use retrace interrupt */
214*bf551665Storek 		cgthreeloadcmap(sc, p->index, p->count);
215*bf551665Storek #undef p
21646883914Storek 		break;
21746883914Storek 
21846883914Storek 	case FBIOGVIDEO:
21946883914Storek 		*(int *)data = sc->sc_blanked;
22046883914Storek 		break;
22146883914Storek 
22246883914Storek 	case FBIOSVIDEO:
22346883914Storek 		if (*(int *)data)
22446883914Storek 			cgthreeunblank(&sc->sc_dev);
225*bf551665Storek 		else if (!sc->sc_blanked) {
226*bf551665Storek 			register volatile struct bt_regs *bt;
227*bf551665Storek 
228*bf551665Storek 			bt = sc->sc_bt;
229*bf551665Storek 			bt->bt_addr = 0x06;	/* command reg */
230*bf551665Storek 			bt->bt_ctrl = 0x70;	/* overlay plane */
231*bf551665Storek 			bt->bt_addr = 0x04;	/* read mask */
232*bf551665Storek 			bt->bt_ctrl = 0x00;	/* color planes */
233*bf551665Storek 			/*
234*bf551665Storek 			 * Set color 0 to black -- note that this overwrites
235*bf551665Storek 			 * R of color 1.
236*bf551665Storek 			 */
237*bf551665Storek 			bt->bt_addr = 0;
238*bf551665Storek 			bt->bt_cmap = 0;
23946883914Storek 
24046883914Storek 			sc->sc_blanked = 1;
24146883914Storek 		}
24246883914Storek 		break;
24346883914Storek 
24446883914Storek 	default:
24546883914Storek 		return (ENOTTY);
24646883914Storek 	}
24746883914Storek 	return (0);
24846883914Storek }
24946883914Storek 
250*bf551665Storek /*
251*bf551665Storek  * Undo the effect of an FBIOSVIDEO that turns the video off.
252*bf551665Storek  */
25346883914Storek static void
cgthreeunblank(dev)25446883914Storek cgthreeunblank(dev)
25546883914Storek 	struct device *dev;
25646883914Storek {
25746883914Storek 	struct cgthree_softc *sc = (struct cgthree_softc *)dev;
258*bf551665Storek 	register volatile struct bt_regs *bt;
25946883914Storek 
260*bf551665Storek 	if (sc->sc_blanked) {
26146883914Storek 		sc->sc_blanked = 0;
262*bf551665Storek 		bt = sc->sc_bt;
263*bf551665Storek 		/* restore color 0 (and R of color 1) */
264*bf551665Storek 		bt->bt_addr = 0;
265*bf551665Storek 		bt->bt_cmap = sc->sc_cmap.cm_chip[0];
266*bf551665Storek 
267*bf551665Storek 		/* restore read mask */
268*bf551665Storek 		bt->bt_addr = 0x06;	/* command reg */
269*bf551665Storek 		bt->bt_ctrl = 0x73;	/* overlay plane */
270*bf551665Storek 		bt->bt_addr = 0x04;	/* read mask */
271*bf551665Storek 		bt->bt_ctrl = 0xff;	/* color planes */
272*bf551665Storek 	}
273*bf551665Storek }
274*bf551665Storek 
275*bf551665Storek /*
276*bf551665Storek  * Load a subset of the current (new) colormap into the Brooktree DAC.
277*bf551665Storek  */
278*bf551665Storek static void
cgthreeloadcmap(sc,start,ncolors)279*bf551665Storek cgthreeloadcmap(sc, start, ncolors)
280*bf551665Storek 	register struct cgthree_softc *sc;
281*bf551665Storek 	register int start, ncolors;
282*bf551665Storek {
283*bf551665Storek 	register volatile struct bt_regs *bt;
284*bf551665Storek 	register u_int *ip;
285*bf551665Storek 	register int count;
286*bf551665Storek 
287*bf551665Storek 	ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)];	/* start/4 * 3 */
288*bf551665Storek 	count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
289*bf551665Storek 	bt = sc->sc_bt;
290*bf551665Storek 	bt->bt_addr = BT_D4M4(start);
291*bf551665Storek 	while (--count >= 0)
292*bf551665Storek 		bt->bt_cmap = *ip++;
29346883914Storek }
29446883914Storek 
29546883914Storek /*
29646883914Storek  * Return the address that would map the given device at the given
29746883914Storek  * offset, allowing for the given protection, or return -1 for error.
29846883914Storek  *
29946883914Storek  * The cg3 is mapped starting at 256KB, for pseudo-compatibility with
30046883914Storek  * the cg4 (which had an overlay plane in the first 128K and an enable
30146883914Storek  * plane in the next 128K).  X11 uses only 256k+ region but tries to
30246883914Storek  * map the whole thing, so we repeatedly map the first 256K to the
30346883914Storek  * first page of the color screen.  If someone tries to use the overlay
30446883914Storek  * and enable regions, they will get a surprise....
30546883914Storek  */
30646883914Storek int
cgthreemap(dev,off,prot)30746883914Storek cgthreemap(dev, off, prot)
30846883914Storek 	dev_t dev;
30946883914Storek 	int off, prot;
31046883914Storek {
31146883914Storek 	register struct cgthree_softc *sc = cgthreecd.cd_devs[minor(dev)];
31246883914Storek #define	START	(128*1024 + 128*1024)
31346883914Storek 
31446883914Storek 	if (off & PGOFSET)
31546883914Storek 		panic("cgthreemap");
31646883914Storek 	if ((unsigned)off < START)
31746883914Storek 		off = 0;
31846883914Storek 	else
31946883914Storek 		off -= START;
32046883914Storek 	if ((unsigned)off >= sc->sc_fb.fb_type.fb_size)
32146883914Storek 		return (-1);
32246883914Storek 	/*
32346883914Storek 	 * I turned on PMAP_NC here to disable the cache as I was
32446883914Storek 	 * getting horribly broken behaviour with it on.
32546883914Storek 	 */
32646883914Storek 	return ((int)sc->sc_phys + off + PMAP_OBIO + PMAP_NC);
32746883914Storek }
328