xref: /netbsd/sys/arch/sun3/dev/cg2.c (revision 3cd14f75)
1*3cd14f75Sthorpej /*	$NetBSD: cg2.c,v 1.5 1996/03/17 02:03:43 thorpej Exp $	*/
21feb639aSgwr 
31feb639aSgwr /*
41feb639aSgwr  * Copyright (c) 1992, 1993
51feb639aSgwr  *	The Regents of the University of California.  All rights reserved.
61feb639aSgwr  *
71feb639aSgwr  * This software was developed by the Computer Systems Engineering group
81feb639aSgwr  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
91feb639aSgwr  * contributed to Berkeley.
101feb639aSgwr  *
111feb639aSgwr  * All advertising materials mentioning features or use of this software
121feb639aSgwr  * must display the following acknowledgement:
131feb639aSgwr  *	This product includes software developed by the University of
141feb639aSgwr  *	California, Lawrence Berkeley Laboratory.
151feb639aSgwr  *
161feb639aSgwr  * Redistribution and use in source and binary forms, with or without
171feb639aSgwr  * modification, are permitted provided that the following conditions
181feb639aSgwr  * are met:
191feb639aSgwr  * 1. Redistributions of source code must retain the above copyright
201feb639aSgwr  *    notice, this list of conditions and the following disclaimer.
211feb639aSgwr  * 2. Redistributions in binary form must reproduce the above copyright
221feb639aSgwr  *    notice, this list of conditions and the following disclaimer in the
231feb639aSgwr  *    documentation and/or other materials provided with the distribution.
241feb639aSgwr  * 3. All advertising materials mentioning features or use of this software
251feb639aSgwr  *    must display the following acknowledgement:
261feb639aSgwr  *	This product includes software developed by the University of
271feb639aSgwr  *	California, Berkeley and its contributors.
281feb639aSgwr  * 4. Neither the name of the University nor the names of its contributors
291feb639aSgwr  *    may be used to endorse or promote products derived from this software
301feb639aSgwr  *    without specific prior written permission.
311feb639aSgwr  *
321feb639aSgwr  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
331feb639aSgwr  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
341feb639aSgwr  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
351feb639aSgwr  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
361feb639aSgwr  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
371feb639aSgwr  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
381feb639aSgwr  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
391feb639aSgwr  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
401feb639aSgwr  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
411feb639aSgwr  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
421feb639aSgwr  * SUCH DAMAGE.
431feb639aSgwr  *
441feb639aSgwr  *	from: @(#)cgthree.c	8.2 (Berkeley) 10/30/93
451feb639aSgwr  */
461feb639aSgwr 
471feb639aSgwr /*
481feb639aSgwr  * color display (cg2) driver.
491feb639aSgwr  *
501feb639aSgwr  * Does not handle interrupts, even though they can occur.
511feb639aSgwr  *
521feb639aSgwr  * XXX should defer colormap updates to vertical retrace interrupts
531feb639aSgwr  */
541feb639aSgwr 
551feb639aSgwr #include <sys/param.h>
561feb639aSgwr #include <sys/device.h>
571feb639aSgwr #include <sys/ioctl.h>
581feb639aSgwr #include <sys/malloc.h>
591feb639aSgwr #include <sys/mman.h>
601feb639aSgwr #include <sys/tty.h>
611feb639aSgwr 
621feb639aSgwr #include <vm/vm.h>
631feb639aSgwr 
641feb639aSgwr #include <machine/fbio.h>
651feb639aSgwr #include <machine/autoconf.h>
661feb639aSgwr #include <machine/pmap.h>
671feb639aSgwr #include <machine/cg2reg.h>
681feb639aSgwr 
691feb639aSgwr #include "fbvar.h"
701feb639aSgwr 
711feb639aSgwr #define	CMSIZE 256
721feb639aSgwr 
731feb639aSgwr /* offset to and size of mapped part of frame buffer */
741feb639aSgwr #define PLANEMAP_SIZE		0x100000
751feb639aSgwr #define PIXELMAP_SIZE		0x100000
761feb639aSgwr #define ROWOPMAP_SIZE		0x100000
771feb639aSgwr 
781feb639aSgwr #define	CTLREGS_OFF 		0x300000
791feb639aSgwr #define	CTLREGS_SIZE		 0x10600
801feb639aSgwr 
811feb639aSgwr #define	CG2_MAPPED_OFFSET	(PLANEMAP_SIZE + PIXELMAP_SIZE)
82a1cc6d49Sgwr #define	CG2_MAPPED_SIZE 	(CTLREGS_OFF + CTLREGS_SIZE)
831feb639aSgwr 
841feb639aSgwr /* per-display variables */
851feb639aSgwr struct cg2_softc {
861feb639aSgwr 	struct	device sc_dev;		/* base device */
871feb639aSgwr 	struct	fbdevice sc_fb;		/* frame buffer device */
881feb639aSgwr 	int 	sc_phys;		/* display RAM (phys addr) */
891feb639aSgwr 	int 	sc_pmtype;		/* pmap type bits */
901feb639aSgwr 	struct	cg2fb *sc_ctlreg;	/* control registers */
911feb639aSgwr };
921feb639aSgwr 
931feb639aSgwr /* autoconfiguration driver */
941feb639aSgwr static void	cg2attach __P((struct device *, struct device *, void *));
951feb639aSgwr static int	cg2match __P((struct device *, void *, void *));
961feb639aSgwr 
97*3cd14f75Sthorpej struct cfattach cgtwo_ca = {
98*3cd14f75Sthorpej 	sizeof(struct cg2_softc), cg2match, cg2attach
99*3cd14f75Sthorpej };
100*3cd14f75Sthorpej 
101*3cd14f75Sthorpej struct cfdriver cgtwo_cd = {
102*3cd14f75Sthorpej 	NULL, "cgtwo", DV_DULL
103*3cd14f75Sthorpej };
1041feb639aSgwr 
1051feb639aSgwr /* frame buffer generic driver */
106ca5caf00Smycroft int cg2open(), cg2close(), cg2mmap();
1071feb639aSgwr 
1081feb639aSgwr static int  cg2gattr __P((struct fbdevice *, struct fbgattr *));
1091feb639aSgwr static int  cg2gvideo __P((struct fbdevice *, int *));
1101feb639aSgwr static int	cg2svideo __P((struct fbdevice *, int *));
1111feb639aSgwr static int	cg2getcmap __P((struct fbdevice *, struct fbcmap *));
1121feb639aSgwr static int	cg2putcmap __P((struct fbdevice *, struct fbcmap *));
1131feb639aSgwr 
1141feb639aSgwr static struct fbdriver cg2fbdriver = {
115795010b5Smycroft 	cg2open, cg2close, cg2mmap, cg2gattr,
1161feb639aSgwr 	cg2gvideo, cg2svideo,
1171feb639aSgwr 	cg2getcmap, cg2putcmap };
1181feb639aSgwr 
1191feb639aSgwr static void cg2loadcmap __P((struct cg2_softc *, int, int));
1201feb639aSgwr static int cg2intr __P((void*));
1211feb639aSgwr 
1221feb639aSgwr /*
1231feb639aSgwr  * Match a cg2.
1241feb639aSgwr  */
1251feb639aSgwr static int
1261feb639aSgwr cg2match(parent, vcf, args)
1271feb639aSgwr 	struct device *parent;
1281feb639aSgwr 	void *vcf, *args;
1291feb639aSgwr {
1301feb639aSgwr 	struct confargs *ca = args;
1311feb639aSgwr 	int x;
1321feb639aSgwr 
1331feb639aSgwr 	if (ca->ca_paddr == -1)
1341feb639aSgwr 		return (0);
1351feb639aSgwr 
1361feb639aSgwr 	if (ca->ca_bustype != BUS_VME16)
1371feb639aSgwr 		return (0);
1381feb639aSgwr 
139a1cc6d49Sgwr 	x = bus_peek(ca->ca_bustype, ca->ca_paddr + CTLREGS_OFF, 1);
1401feb639aSgwr 	if (x == -1)
1411feb639aSgwr 		return (0);
1421feb639aSgwr 
1431feb639aSgwr 	/* XXX */
144a1cc6d49Sgwr 	/* printf("cg2: id=0x%x\n", x); */
1451feb639aSgwr 
1461feb639aSgwr 	return (1);
1471feb639aSgwr }
1481feb639aSgwr 
1491feb639aSgwr /*
1501feb639aSgwr  * Attach a display.  We need to notice if it is the console, too.
1511feb639aSgwr  */
1521feb639aSgwr static void
1531feb639aSgwr cg2attach(parent, self, args)
1541feb639aSgwr 	struct device *parent, *self;
1551feb639aSgwr 	void *args;
1561feb639aSgwr {
1571feb639aSgwr 	struct cg2_softc *sc = (struct cg2_softc *)self;
1581feb639aSgwr 	struct fbdevice *fb = &sc->sc_fb;
1591feb639aSgwr 	struct confargs *ca = args;
1601feb639aSgwr 	struct fbtype *fbt;
1611feb639aSgwr 	int i, ramsize, pa;
1621feb639aSgwr 
1631feb639aSgwr 	sc->sc_phys = ca->ca_paddr;
1641feb639aSgwr 	sc->sc_pmtype = PMAP_NC | PMAP_VME16;
1651feb639aSgwr 
1661feb639aSgwr 	sc->sc_ctlreg = (struct cg2fb *) bus_mapin(ca->ca_bustype,
1671feb639aSgwr 			ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE);
1681feb639aSgwr 
1691feb639aSgwr 	isr_add_vectored(cg2intr, (void*)sc,
1701feb639aSgwr 					 ca->ca_intpri, ca->ca_intvec);
1711feb639aSgwr 
1721feb639aSgwr 	/*
1731feb639aSgwr 	 * XXX - Initialize?  Determine type?
1741feb639aSgwr 	 */
1751feb639aSgwr 	sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec;
1761feb639aSgwr 	sc->sc_ctlreg->status.word = 1;
1771feb639aSgwr 
1781feb639aSgwr 	fb->fb_driver = &cg2fbdriver;
1791feb639aSgwr 	fb->fb_private = sc;
1801feb639aSgwr 	fb->fb_name = sc->sc_dev.dv_xname;
1811feb639aSgwr 
1821feb639aSgwr 	fbt = &fb->fb_fbtype;
1831feb639aSgwr 	fbt->fb_type = FBTYPE_SUN2COLOR;
1841feb639aSgwr 	fbt->fb_depth = 8;
1851feb639aSgwr 	fbt->fb_cmsize = CMSIZE;
1861feb639aSgwr 
1871feb639aSgwr 	fbt->fb_width = 1152;
1881feb639aSgwr 	fbt->fb_height = 900;
1891feb639aSgwr 	fbt->fb_size = CG2_MAPPED_SIZE;
1901feb639aSgwr 
1911feb639aSgwr 	printf(" (%dx%d)\n", fbt->fb_width, fbt->fb_height);
1921feb639aSgwr 	fb_attach(fb, 2);
1931feb639aSgwr }
1941feb639aSgwr 
1951feb639aSgwr int
1961feb639aSgwr cg2open(dev, flags, mode, p)
1971feb639aSgwr 	dev_t dev;
1981feb639aSgwr 	int flags, mode;
1991feb639aSgwr 	struct proc *p;
2001feb639aSgwr {
2011feb639aSgwr 	int unit = minor(dev);
2021feb639aSgwr 
203*3cd14f75Sthorpej 	if (unit >= cgtwo_cd.cd_ndevs || cgtwo_cd.cd_devs[unit] == NULL)
2041feb639aSgwr 		return (ENXIO);
2051feb639aSgwr 	return (0);
2061feb639aSgwr }
2071feb639aSgwr 
2081feb639aSgwr int
2091feb639aSgwr cg2close(dev, flags, mode, p)
2101feb639aSgwr 	dev_t dev;
2111feb639aSgwr 	int flags, mode;
2121feb639aSgwr 	struct proc *p;
2131feb639aSgwr {
2141feb639aSgwr 
2151feb639aSgwr 	return (0);
2161feb639aSgwr }
2171feb639aSgwr 
2181feb639aSgwr int
2191feb639aSgwr cg2ioctl(dev, cmd, data, flags, p)
2201feb639aSgwr 	dev_t dev;
2211feb639aSgwr 	u_long cmd;
2221feb639aSgwr 	caddr_t data;
2231feb639aSgwr 	int flags;
2241feb639aSgwr 	struct proc *p;
2251feb639aSgwr {
226*3cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2271feb639aSgwr 
2281feb639aSgwr 	return (fbioctlfb(&sc->sc_fb, cmd, data));
2291feb639aSgwr }
2301feb639aSgwr 
2311feb639aSgwr /*
2321feb639aSgwr  * Return the address that would map the given device at the given
2331feb639aSgwr  * offset, allowing for the given protection, or return -1 for error.
2341feb639aSgwr  */
2351feb639aSgwr int
236ca5caf00Smycroft cg2mmap(dev, off, prot)
2371feb639aSgwr 	dev_t dev;
2381feb639aSgwr 	int off, prot;
2391feb639aSgwr {
240*3cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2411feb639aSgwr 	int realoff;
2421feb639aSgwr 
2431feb639aSgwr 	if (off & PGOFSET)
244795010b5Smycroft 		panic("cg2mmap");
2451feb639aSgwr 
246a1cc6d49Sgwr 	if ((unsigned)off >= CG2_MAPPED_SIZE)
2471feb639aSgwr 		return (-1);
2481feb639aSgwr 
2491feb639aSgwr 	/*
2501feb639aSgwr 	 * I turned on PMAP_NC here to disable the cache as I was
2511feb639aSgwr 	 * getting horribly broken behaviour with it on.
2521feb639aSgwr 	 */
2531feb639aSgwr 	return ((sc->sc_phys + off) | sc->sc_pmtype);
2541feb639aSgwr }
2551feb639aSgwr 
2561feb639aSgwr /*
2571feb639aSgwr  * Internal ioctl functions.
2581feb639aSgwr  */
2591feb639aSgwr 
2601feb639aSgwr /* FBIOGATTR: */
2611feb639aSgwr static int  cg2gattr(fb, fba)
2621feb639aSgwr 	struct fbdevice *fb;
2631feb639aSgwr 	struct fbgattr *fba;
2641feb639aSgwr {
2651feb639aSgwr 
2661feb639aSgwr 	fba->real_type = fb->fb_fbtype.fb_type;
2671feb639aSgwr 	fba->owner = 0;		/* XXX - TIOCCONS stuff? */
2681feb639aSgwr 	fba->fbtype = fb->fb_fbtype;
2691feb639aSgwr 	fba->sattr.flags = 0;
2701feb639aSgwr 	fba->sattr.emu_type = fb->fb_fbtype.fb_type;
2711feb639aSgwr 	fba->sattr.dev_specific[0] = -1;
2721feb639aSgwr 	fba->emu_types[0] = fb->fb_fbtype.fb_type;
2731feb639aSgwr 	fba->emu_types[1] = -1;
2741feb639aSgwr 	return (0);
2751feb639aSgwr }
2761feb639aSgwr 
2771feb639aSgwr /* FBIOGVIDEO: */
2781feb639aSgwr static int  cg2gvideo(fb, on)
2791feb639aSgwr 	struct fbdevice *fb;
2801feb639aSgwr 	int *on;
2811feb639aSgwr {
2821feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
2831feb639aSgwr 
2841feb639aSgwr 	*on = sc->sc_ctlreg->status.reg.video_enab;
2851feb639aSgwr 	return (0);
2861feb639aSgwr }
2871feb639aSgwr 
2881feb639aSgwr /* FBIOSVIDEO: */
2891feb639aSgwr static int cg2svideo(fb, on)
2901feb639aSgwr 	struct fbdevice *fb;
2911feb639aSgwr 	int *on;
2921feb639aSgwr {
2931feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
2941feb639aSgwr 
2951feb639aSgwr 	sc->sc_ctlreg->status.reg.video_enab = (*on) & 1;
2961feb639aSgwr 
2971feb639aSgwr 	return (0);
2981feb639aSgwr }
2991feb639aSgwr 
3001feb639aSgwr /* FBIOGETCMAP: */
3011feb639aSgwr static int cg2getcmap(fb, cmap)
3021feb639aSgwr 	struct fbdevice *fb;
3031feb639aSgwr 	struct fbcmap *cmap;
3041feb639aSgwr {
3051feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3061feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
3071feb639aSgwr 	int error, start, count, ecount;
3081feb639aSgwr 	register u_int i;
3091feb639aSgwr 	register u_short *p;
3101feb639aSgwr 
3111feb639aSgwr 	start = cmap->index;
3121feb639aSgwr 	count = cmap->count;
3131feb639aSgwr 	ecount = start + count;
3141feb639aSgwr 	if (start >= CMSIZE || ecount > CMSIZE)
3151feb639aSgwr 		return (EINVAL);
3161feb639aSgwr 
3171feb639aSgwr 	/* XXX - Wait for retrace? */
3181feb639aSgwr 
3191feb639aSgwr 	/* Copy hardware to local arrays. */
3201feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3211feb639aSgwr 	for (i = start; i < ecount; i++)
3221feb639aSgwr 		red[i] = *p++;
3231feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3241feb639aSgwr 	for (i = start; i < ecount; i++)
3251feb639aSgwr 		green[i] = *p++;
3261feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3271feb639aSgwr 	for (i = start; i < ecount; i++)
3281feb639aSgwr 		blue[i] = *p++;
3291feb639aSgwr 
3301feb639aSgwr 	/* Copy local arrays to user space. */
3311feb639aSgwr 	if ((error = copyout(red + start, cmap->red, count)) != 0)
3321feb639aSgwr 		return (error);
3331feb639aSgwr 	if ((error = copyout(green + start, cmap->green, count)) != 0)
3341feb639aSgwr 		return (error);
3351feb639aSgwr 	if ((error = copyout(blue + start, cmap->blue, count)) != 0)
3361feb639aSgwr 		return (error);
3371feb639aSgwr 
3381feb639aSgwr 	return (0);
3391feb639aSgwr }
3401feb639aSgwr 
3411feb639aSgwr /* FBIOPUTCMAP: */
3421feb639aSgwr static int cg2putcmap(fb, cmap)
3431feb639aSgwr 	struct fbdevice *fb;
3441feb639aSgwr 	struct fbcmap *cmap;
3451feb639aSgwr {
3461feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3471feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
3481feb639aSgwr 	int error, start, count, ecount;
3491feb639aSgwr 	register u_int i;
3501feb639aSgwr 	register u_short *p;
3511feb639aSgwr 
3521feb639aSgwr 	start = cmap->index;
3531feb639aSgwr 	count = cmap->count;
3541feb639aSgwr 	ecount = start + count;
3551feb639aSgwr 	if (start >= CMSIZE || ecount > CMSIZE)
3561feb639aSgwr 		return (EINVAL);
3571feb639aSgwr 
3581feb639aSgwr 	/* Copy from user space to local arrays. */
3591feb639aSgwr 	if ((error = copyin(cmap->red, red + start, count)) != 0)
3601feb639aSgwr 		return (error);
3611feb639aSgwr 	if ((error = copyin(cmap->green, green + start, count)) != 0)
3621feb639aSgwr 		return (error);
3631feb639aSgwr 	if ((error = copyin(cmap->blue, blue + start, count)) != 0)
3641feb639aSgwr 		return (error);
3651feb639aSgwr 
3661feb639aSgwr 	/* XXX - Wait for retrace? */
3671feb639aSgwr 
3681feb639aSgwr 	/* Copy from local arrays to hardware. */
3691feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3701feb639aSgwr 	for (i = start; i < ecount; i++)
3711feb639aSgwr 		*p++ = red[i];
3721feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3731feb639aSgwr 	for (i = start; i < ecount; i++)
3741feb639aSgwr 		*p++ = green[i];
3751feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3761feb639aSgwr 	for (i = start; i < ecount; i++)
3771feb639aSgwr 		*p++ = blue[i];
3781feb639aSgwr 
3791feb639aSgwr 	return (0);
3801feb639aSgwr 
3811feb639aSgwr }
3821feb639aSgwr 
3831feb639aSgwr static int
3841feb639aSgwr cg2intr(vsc)
3851feb639aSgwr 	void *vsc;
3861feb639aSgwr {
3871feb639aSgwr 	struct cg2_softc *sc = vsc;
3881feb639aSgwr 
3891feb639aSgwr 	/* XXX - Just disable interrupts for now. */
3901feb639aSgwr 	sc->sc_ctlreg->status.reg.inten = 0;
3911feb639aSgwr 
3921feb639aSgwr 	printf("cg2intr\n");
3931feb639aSgwr 	return (1);
3941feb639aSgwr }
395