xref: /csrg-svn/sys/sparc/sbus/cgthree.c (revision 64776)
155135Storek /*
263322Sbostic  * Copyright (c) 1992, 1993
363322Sbostic  *	The Regents of the University of California.  All rights reserved.
455135Storek  *
555135Storek  * This software was developed by the Computer Systems Engineering group
655135Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
755135Storek  * contributed to Berkeley.
855135Storek  *
955503Sbostic  * All advertising materials mentioning features or use of this software
1055503Sbostic  * must display the following acknowledgement:
1155503Sbostic  *	This product includes software developed by the University of
1259213Storek  *	California, Lawrence Berkeley Laboratory.
1355503Sbostic  *
1455135Storek  * %sccs.include.redist.c%
1555135Storek  *
16*64776Storek  *	@(#)cgthree.c	8.2 (Berkeley) 10/30/93
1755135Storek  *
18*64776Storek  * from: $Header: cgthree.c,v 1.8 93/10/31 05:09:24 torek Exp $
1955135Storek  */
2055135Storek 
2155135Storek /*
2255135Storek  * color display (cgthree) driver.
2355135Storek  *
2455135Storek  * Does not handle interrupts, even though they can occur.
25*64776Storek  *
26*64776Storek  * XXX should defer colormap updates to vertical retrace interrupts
2755135Storek  */
2855135Storek 
2956540Sbostic #include <sys/param.h>
3056540Sbostic #include <sys/buf.h>
3156540Sbostic #include <sys/device.h>
3256540Sbostic #include <sys/fbio.h>
3356540Sbostic #include <sys/ioctl.h>
3456540Sbostic #include <sys/malloc.h>
3556540Sbostic #include <sys/mman.h>
3656540Sbostic #include <sys/tty.h>
3755135Storek 
3856540Sbostic #include <machine/autoconf.h>
3956540Sbostic #include <machine/pmap.h>
4056540Sbostic #include <machine/fbvar.h>
4155135Storek 
42*64776Storek #include <sparc/sbus/btreg.h>
43*64776Storek #include <sparc/sbus/btvar.h>
4456540Sbostic #include <sparc/sbus/cgthreereg.h>
4556540Sbostic #include <sparc/sbus/sbusvar.h>
4655135Storek 
4755135Storek /* per-display variables */
4855135Storek struct cgthree_softc {
4955135Storek 	struct	device sc_dev;		/* base device */
5055135Storek 	struct	sbusdev sc_sd;		/* sbus device */
5155135Storek 	struct	fbdevice sc_fb;		/* frame buffer device */
52*64776Storek 	volatile struct bt_regs *sc_bt;	/* Brooktree registers */
5355135Storek 	caddr_t	sc_phys;		/* display RAM (phys addr) */
5455135Storek 	int	sc_blanked;		/* true if blanked */
55*64776Storek 	union	bt_cmap sc_cmap;	/* Brooktree color map */
5655135Storek };
5755135Storek 
5855135Storek /* autoconfiguration driver */
5955135Storek static void	cgthreeattach(struct device *, struct device *, void *);
6055135Storek struct cfdriver cgthreecd =
6155135Storek     { NULL, "cgthree", matchbyname, cgthreeattach,
6255135Storek       DV_DULL, sizeof(struct cgthree_softc) };
6355135Storek 
6455135Storek /* frame buffer generic driver */
6555135Storek static void	cgthreeunblank(struct device *);
6655135Storek static struct fbdriver cgthreefbdriver = { cgthreeunblank };
6755135Storek 
6855135Storek extern int fbnode;
6955135Storek extern struct tty *fbconstty;
7055135Storek extern int (*v_putc)();
7155135Storek extern int nullop();
7255135Storek static int cgthree_cnputc();
7355135Storek 
74*64776Storek static void cgthreeloadcmap __P((struct cgthree_softc *, int, int));
75*64776Storek 
7655135Storek #define	CGTHREE_MAJOR	55		/* XXX */
7755135Storek 
7855135Storek /*
7955135Storek  * Attach a display.  We need to notice if it is the console, too.
8055135Storek  */
8155135Storek void
cgthreeattach(parent,self,args)8255135Storek cgthreeattach(parent, self, args)
8355135Storek 	struct device *parent, *self;
8455135Storek 	void *args;
8555135Storek {
8655135Storek 	register struct cgthree_softc *sc = (struct cgthree_softc *)self;
8755135Storek 	register struct sbus_attach_args *sa = args;
8855135Storek 	register int node = sa->sa_ra.ra_node, ramsize, i;
89*64776Storek 	register volatile struct bt_regs *bt;
9055135Storek 	register struct cgthree_all *p;
9155135Storek 	int isconsole;
9255135Storek 
9355135Storek 	sc->sc_fb.fb_major = CGTHREE_MAJOR;	/* XXX to be removed */
9455135Storek 
9555135Storek 	sc->sc_fb.fb_driver = &cgthreefbdriver;
9655135Storek 	sc->sc_fb.fb_device = &sc->sc_dev;
9755135Storek 	/*
9855135Storek 	 * The defaults below match my screen, but are not guaranteed
9955135Storek 	 * to be correct as defaults go...
10055135Storek 	 */
10155135Storek 	sc->sc_fb.fb_type.fb_type = FBTYPE_SUN3COLOR;
10255135Storek 	sc->sc_fb.fb_type.fb_width = getpropint(node, "width", 1152);
10355135Storek 	sc->sc_fb.fb_type.fb_height = getpropint(node, "height", 900);
10455135Storek 	sc->sc_fb.fb_linebytes = getpropint(node, "linebytes", 1152);
10555135Storek 	ramsize = sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes;
10655135Storek 	sc->sc_fb.fb_type.fb_depth = 8;
10755135Storek 	sc->sc_fb.fb_type.fb_cmsize = 256;
10855135Storek 	sc->sc_fb.fb_type.fb_size = ramsize;
10955135Storek 	printf(": %s, %d x %d", getpropstring(node, "model"),
11055135Storek 	    sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height);
11155135Storek 
11255135Storek 	/*
11355135Storek 	 * When the ROM has mapped in a cgthree display, the address
11455135Storek 	 * maps only the video RAM, so in any case we have to map the
11555135Storek 	 * registers ourselves.  We only need the video RAM if we are
11655135Storek 	 * going to print characters via rconsole.
11755135Storek 	 */
11855135Storek 	isconsole = node == fbnode && fbconstty != NULL;
11955135Storek 	p = (struct cgthree_all *)sa->sa_ra.ra_paddr;
12055135Storek 	if ((sc->sc_fb.fb_pixels = sa->sa_ra.ra_vaddr) == NULL && isconsole) {
12155135Storek 		/* this probably cannot happen, but what the heck */
12255135Storek 		sc->sc_fb.fb_pixels = mapiodev(p->ba_ram, ramsize);
12355135Storek 	}
124*64776Storek 	sc->sc_bt = bt = (volatile struct bt_regs *)
125*64776Storek 	    mapiodev((caddr_t)&p->ba_btreg, sizeof(p->ba_btreg));
12655135Storek 	sc->sc_phys = p->ba_ram;
12755135Storek 
128*64776Storek 	/* grab initial (current) color map */
129*64776Storek 	bt->bt_addr = 0;
13055135Storek 	for (i = 0; i < 256 * 3 / 4; i++)
131*64776Storek 		sc->sc_cmap.cm_chip[i] = bt->bt_cmap;
132*64776Storek 	/* make sure we are not blanked (see cgthreeunblank) */
133*64776Storek 	bt->bt_addr = 0x06;		/* command reg */
134*64776Storek 	bt->bt_ctrl = 0x73;		/* overlay plane */
135*64776Storek 	bt->bt_addr = 0x04;		/* read mask */
136*64776Storek 	bt->bt_ctrl = 0xff;		/* color planes */
13755135Storek 
13855135Storek 	if (isconsole) {
13955135Storek 		printf(" (console)\n");
14055135Storek #ifdef RCONSOLE
14155135Storek 		rcons_init(&sc->sc_fb);
14255135Storek #endif
14355135Storek 	} else
14455135Storek 		printf("\n");
14555135Storek 	sbus_establish(&sc->sc_sd, &sc->sc_dev);
14655135Storek 	if (node == fbnode)
14755135Storek 		fb_attach(&sc->sc_fb);
14855135Storek }
14955135Storek 
15055135Storek int
cgthreeopen(dev,flags,mode,p)15155135Storek cgthreeopen(dev, flags, mode, p)
15255135Storek 	dev_t dev;
15355135Storek 	int flags, mode;
15455135Storek 	struct proc *p;
15555135Storek {
15655135Storek 	int unit = minor(dev);
15755135Storek 
15855135Storek 	if (unit >= cgthreecd.cd_ndevs || cgthreecd.cd_devs[unit] == NULL)
15955135Storek 		return (ENXIO);
16055135Storek 	return (0);
16155135Storek }
16255135Storek 
16355135Storek int
cgthreeclose(dev,flags,mode,p)16455135Storek cgthreeclose(dev, flags, mode, p)
16555135Storek 	dev_t dev;
16655135Storek 	int flags, mode;
16755135Storek 	struct proc *p;
16855135Storek {
16955135Storek 
17055135Storek 	return (0);
17155135Storek }
17255135Storek 
17355135Storek int
cgthreeioctl(dev,cmd,data,flags,p)17455135Storek cgthreeioctl(dev, cmd, data, flags, p)
17555135Storek 	dev_t dev;
17655135Storek 	int cmd;
177*64776Storek 	register caddr_t data;
17855135Storek 	int flags;
17955135Storek 	struct proc *p;
18055135Storek {
18155135Storek 	register struct cgthree_softc *sc = cgthreecd.cd_devs[minor(dev)];
18255135Storek 	register struct fbgattr *fba;
183*64776Storek 	int error;
18455135Storek 
18555135Storek 	switch (cmd) {
18655135Storek 
18755135Storek 	case FBIOGTYPE:
18855135Storek 		*(struct fbtype *)data = sc->sc_fb.fb_type;
18955135Storek 		break;
19055135Storek 
19155135Storek 	case FBIOGATTR:
19255135Storek 		fba = (struct fbgattr *)data;
19355135Storek 		fba->real_type = sc->sc_fb.fb_type.fb_type;
19455135Storek 		fba->owner = 0;		/* XXX ??? */
19555135Storek 		fba->fbtype = sc->sc_fb.fb_type;
19655135Storek 		fba->sattr.flags = 0;
19755135Storek 		fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
19855135Storek 		fba->sattr.dev_specific[0] = -1;
19955135Storek 		fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
20055135Storek 		fba->emu_types[1] = -1;
20155135Storek 		break;
20255135Storek 
203*64776Storek 	case FBIOGETCMAP:
204*64776Storek 		return (bt_getcmap((struct fbcmap *)data, &sc->sc_cmap, 256));
20555135Storek 
206*64776Storek 	case FBIOPUTCMAP:
207*64776Storek 		/* copy to software map */
208*64776Storek #define p ((struct fbcmap *)data)
209*64776Storek 		error = bt_putcmap(p, &sc->sc_cmap, 256);
210*64776Storek 		if (error)
211*64776Storek 			return (error);
212*64776Storek 		/* now blast them into the chip */
21355135Storek 		/* XXX should use retrace interrupt */
214*64776Storek 		cgthreeloadcmap(sc, p->index, p->count);
215*64776Storek #undef p
21655135Storek 		break;
21755135Storek 
21855135Storek 	case FBIOGVIDEO:
21955135Storek 		*(int *)data = sc->sc_blanked;
22055135Storek 		break;
22155135Storek 
22255135Storek 	case FBIOSVIDEO:
22355135Storek 		if (*(int *)data)
22455135Storek 			cgthreeunblank(&sc->sc_dev);
225*64776Storek 		else if (!sc->sc_blanked) {
226*64776Storek 			register volatile struct bt_regs *bt;
22755135Storek 
228*64776Storek 			bt = sc->sc_bt;
229*64776Storek 			bt->bt_addr = 0x06;	/* command reg */
230*64776Storek 			bt->bt_ctrl = 0x70;	/* overlay plane */
231*64776Storek 			bt->bt_addr = 0x04;	/* read mask */
232*64776Storek 			bt->bt_ctrl = 0x00;	/* color planes */
233*64776Storek 			/*
234*64776Storek 			 * Set color 0 to black -- note that this overwrites
235*64776Storek 			 * R of color 1.
236*64776Storek 			 */
237*64776Storek 			bt->bt_addr = 0;
238*64776Storek 			bt->bt_cmap = 0;
239*64776Storek 
24055135Storek 			sc->sc_blanked = 1;
24155135Storek 		}
24255135Storek 		break;
24355135Storek 
24455135Storek 	default:
24555135Storek 		return (ENOTTY);
24655135Storek 	}
24755135Storek 	return (0);
24855135Storek }
24955135Storek 
250*64776Storek /*
251*64776Storek  * Undo the effect of an FBIOSVIDEO that turns the video off.
252*64776Storek  */
25355135Storek static void
cgthreeunblank(dev)25455135Storek cgthreeunblank(dev)
25555135Storek 	struct device *dev;
25655135Storek {
25755135Storek 	struct cgthree_softc *sc = (struct cgthree_softc *)dev;
258*64776Storek 	register volatile struct bt_regs *bt;
25955135Storek 
260*64776Storek 	if (sc->sc_blanked) {
261*64776Storek 		sc->sc_blanked = 0;
262*64776Storek 		bt = sc->sc_bt;
263*64776Storek 		/* restore color 0 (and R of color 1) */
264*64776Storek 		bt->bt_addr = 0;
265*64776Storek 		bt->bt_cmap = sc->sc_cmap.cm_chip[0];
266*64776Storek 
267*64776Storek 		/* restore read mask */
268*64776Storek 		bt->bt_addr = 0x06;	/* command reg */
269*64776Storek 		bt->bt_ctrl = 0x73;	/* overlay plane */
270*64776Storek 		bt->bt_addr = 0x04;	/* read mask */
271*64776Storek 		bt->bt_ctrl = 0xff;	/* color planes */
272*64776Storek 	}
27355135Storek }
27455135Storek 
27555135Storek /*
276*64776Storek  * Load a subset of the current (new) colormap into the Brooktree DAC.
277*64776Storek  */
278*64776Storek static void
cgthreeloadcmap(sc,start,ncolors)279*64776Storek cgthreeloadcmap(sc, start, ncolors)
280*64776Storek 	register struct cgthree_softc *sc;
281*64776Storek 	register int start, ncolors;
282*64776Storek {
283*64776Storek 	register volatile struct bt_regs *bt;
284*64776Storek 	register u_int *ip;
285*64776Storek 	register int count;
286*64776Storek 
287*64776Storek 	ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)];	/* start/4 * 3 */
288*64776Storek 	count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
289*64776Storek 	bt = sc->sc_bt;
290*64776Storek 	bt->bt_addr = BT_D4M4(start);
291*64776Storek 	while (--count >= 0)
292*64776Storek 		bt->bt_cmap = *ip++;
293*64776Storek }
294*64776Storek 
295*64776Storek /*
29655135Storek  * Return the address that would map the given device at the given
29755135Storek  * offset, allowing for the given protection, or return -1 for error.
29855135Storek  *
29955135Storek  * The cg3 is mapped starting at 256KB, for pseudo-compatibility with
30055135Storek  * the cg4 (which had an overlay plane in the first 128K and an enable
30155135Storek  * plane in the next 128K).  X11 uses only 256k+ region but tries to
30255135Storek  * map the whole thing, so we repeatedly map the first 256K to the
30355135Storek  * first page of the color screen.  If someone tries to use the overlay
30455135Storek  * and enable regions, they will get a surprise....
30555135Storek  */
30655135Storek int
cgthreemap(dev,off,prot)30755135Storek cgthreemap(dev, off, prot)
30855135Storek 	dev_t dev;
30955135Storek 	int off, prot;
31055135Storek {
31155135Storek 	register struct cgthree_softc *sc = cgthreecd.cd_devs[minor(dev)];
31255135Storek #define	START	(128*1024 + 128*1024)
31355135Storek 
31455135Storek 	if (off & PGOFSET)
31555135Storek 		panic("cgthreemap");
31655135Storek 	if ((unsigned)off < START)
31755135Storek 		off = 0;
31855135Storek 	else
31955135Storek 		off -= START;
32055135Storek 	if ((unsigned)off >= sc->sc_fb.fb_type.fb_size)
32155135Storek 		return (-1);
32255135Storek 	/*
32355135Storek 	 * I turned on PMAP_NC here to disable the cache as I was
32455135Storek 	 * getting horribly broken behaviour with it on.
32555135Storek 	 */
32655135Storek 	return ((int)sc->sc_phys + off + PMAP_OBIO + PMAP_NC);
32755135Storek }
328