xref: /netbsd/sys/arch/sun3/dev/cg2.c (revision e0cc03a0)
1*e0cc03a0Sjdolecek /*	$NetBSD: cg2.c,v 1.22 2002/10/23 09:12:24 jdolecek 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>
560c5e3e49Sgwr #include <sys/systm.h>
570c5e3e49Sgwr #include <sys/conf.h>
581feb639aSgwr #include <sys/device.h>
591feb639aSgwr #include <sys/ioctl.h>
601feb639aSgwr #include <sys/malloc.h>
611feb639aSgwr #include <sys/mman.h>
620c5e3e49Sgwr #include <sys/proc.h>
631feb639aSgwr #include <sys/tty.h>
641feb639aSgwr 
659c11d316Smrg #include <uvm/uvm_extern.h>
661feb639aSgwr 
67e38a2e56Sthorpej #include <dev/sun/fbio.h>
681feb639aSgwr #include <machine/autoconf.h>
691feb639aSgwr #include <machine/pmap.h>
701feb639aSgwr #include <machine/cg2reg.h>
711feb639aSgwr 
721feb639aSgwr #include "fbvar.h"
731feb639aSgwr 
741feb639aSgwr #define	CMSIZE 256
751feb639aSgwr 
761feb639aSgwr /* offset to and size of mapped part of frame buffer */
771feb639aSgwr #define PLANEMAP_SIZE		0x100000
781feb639aSgwr #define PIXELMAP_SIZE		0x100000
791feb639aSgwr #define ROWOPMAP_SIZE		0x100000
801feb639aSgwr 
811feb639aSgwr #define	CTLREGS_OFF 		0x300000
821feb639aSgwr #define	CTLREGS_SIZE		 0x10600
831feb639aSgwr 
841feb639aSgwr #define	CG2_MAPPED_OFFSET	(PLANEMAP_SIZE + PIXELMAP_SIZE)
85a1cc6d49Sgwr #define	CG2_MAPPED_SIZE 	(CTLREGS_OFF + CTLREGS_SIZE)
861feb639aSgwr 
871feb639aSgwr /* per-display variables */
881feb639aSgwr struct cg2_softc {
891feb639aSgwr 	struct	device sc_dev;		/* base device */
901feb639aSgwr 	struct	fbdevice sc_fb;		/* frame buffer device */
911feb639aSgwr 	int 	sc_phys;		/* display RAM (phys addr) */
921feb639aSgwr 	int 	sc_pmtype;		/* pmap type bits */
931feb639aSgwr 	struct	cg2fb *sc_ctlreg;	/* control registers */
941feb639aSgwr };
951feb639aSgwr 
961feb639aSgwr /* autoconfiguration driver */
971feb639aSgwr static void	cg2attach __P((struct device *, struct device *, void *));
980c5e3e49Sgwr static int	cg2match __P((struct device *, struct cfdata *, void *));
991feb639aSgwr 
10082af7d52Sthorpej CFATTACH_DECL(cgtwo, sizeof(struct cg2_softc),
1014bf871a7Sthorpej     cg2match, cg2attach, NULL, NULL);
1023cd14f75Sthorpej 
103119b962aSgwr extern struct cfdriver cgtwo_cd;
104119b962aSgwr 
10577a6b82bSgehenna dev_type_open(cg2open);
10677a6b82bSgehenna dev_type_ioctl(cg2ioctl);
10777a6b82bSgehenna dev_type_mmap(cg2mmap);
10877a6b82bSgehenna 
10977a6b82bSgehenna const struct cdevsw cgtwo_cdevsw = {
11077a6b82bSgehenna 	cg2open, nullclose, noread, nowrite, cg2ioctl,
111*e0cc03a0Sjdolecek 	nostop, notty, nopoll, cg2mmap, nokqfilter,
11277a6b82bSgehenna };
11377a6b82bSgehenna 
1140c5e3e49Sgwr static int  cg2gattr __P((struct fbdevice *,  void *));
1150c5e3e49Sgwr static int  cg2gvideo __P((struct fbdevice *, void *));
1160c5e3e49Sgwr static int	cg2svideo __P((struct fbdevice *, void *));
1170c5e3e49Sgwr static int	cg2getcmap __P((struct fbdevice *, void *));
1180c5e3e49Sgwr static int	cg2putcmap __P((struct fbdevice *, void *));
1191feb639aSgwr 
1201feb639aSgwr static struct fbdriver cg2fbdriver = {
121*e0cc03a0Sjdolecek 	cg2open, nullclose, cg2mmap, nokqfilter, cg2gattr,
1221feb639aSgwr 	cg2gvideo, cg2svideo,
1231feb639aSgwr 	cg2getcmap, cg2putcmap };
1241feb639aSgwr 
1251feb639aSgwr static int cg2intr __P((void*));
1261feb639aSgwr 
1271feb639aSgwr /*
1281feb639aSgwr  * Match a cg2.
1291feb639aSgwr  */
1301feb639aSgwr static int
131703ed32eSgwr cg2match(parent, cf, aux)
1321feb639aSgwr 	struct device *parent;
1330c5e3e49Sgwr 	struct cfdata *cf;
134703ed32eSgwr 	void *aux;
1351feb639aSgwr {
136703ed32eSgwr 	struct confargs *ca = aux;
137703ed32eSgwr 	int probe_addr;
1381feb639aSgwr 
139703ed32eSgwr 	/* No default VME address. */
1401feb639aSgwr 	if (ca->ca_paddr == -1)
1411feb639aSgwr 		return (0);
1421feb639aSgwr 
143703ed32eSgwr 	/* Make sure something is there... */
144703ed32eSgwr 	probe_addr = ca->ca_paddr + CTLREGS_OFF;
145703ed32eSgwr 	if (bus_peek(ca->ca_bustype, probe_addr, 1) == -1)
1461feb639aSgwr 		return (0);
1471feb639aSgwr 
148703ed32eSgwr 	/* XXX: look at the ID reg? */
149a087bfebSchristos 	/* printf("cg2: id=0x%x\n", x); */
1501feb639aSgwr 
151703ed32eSgwr 	/* Default interrupt priority. */
152703ed32eSgwr 	if (ca->ca_intpri == -1)
153703ed32eSgwr 		ca->ca_intpri = 4;
154703ed32eSgwr 
1551feb639aSgwr 	return (1);
1561feb639aSgwr }
1571feb639aSgwr 
1581feb639aSgwr /*
1591feb639aSgwr  * Attach a display.  We need to notice if it is the console, too.
1601feb639aSgwr  */
1611feb639aSgwr static void
1621feb639aSgwr cg2attach(parent, self, args)
1631feb639aSgwr 	struct device *parent, *self;
1641feb639aSgwr 	void *args;
1651feb639aSgwr {
1661feb639aSgwr 	struct cg2_softc *sc = (struct cg2_softc *)self;
1671feb639aSgwr 	struct fbdevice *fb = &sc->sc_fb;
1681feb639aSgwr 	struct confargs *ca = args;
1691feb639aSgwr 	struct fbtype *fbt;
1701feb639aSgwr 
1711feb639aSgwr 	sc->sc_phys = ca->ca_paddr;
1721feb639aSgwr 	sc->sc_pmtype = PMAP_NC | PMAP_VME16;
1731feb639aSgwr 
1741feb639aSgwr 	sc->sc_ctlreg = (struct cg2fb *) bus_mapin(ca->ca_bustype,
1751feb639aSgwr 			ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE);
1761feb639aSgwr 
1771feb639aSgwr 	isr_add_vectored(cg2intr, (void*)sc,
1781feb639aSgwr 					 ca->ca_intpri, ca->ca_intvec);
1791feb639aSgwr 
1801feb639aSgwr 	/*
1811feb639aSgwr 	 * XXX - Initialize?  Determine type?
1821feb639aSgwr 	 */
1831feb639aSgwr 	sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec;
1841feb639aSgwr 	sc->sc_ctlreg->status.word = 1;
1851feb639aSgwr 
1861feb639aSgwr 	fb->fb_driver = &cg2fbdriver;
1871feb639aSgwr 	fb->fb_private = sc;
1881feb639aSgwr 	fb->fb_name = sc->sc_dev.dv_xname;
1891feb639aSgwr 
1901feb639aSgwr 	fbt = &fb->fb_fbtype;
1911feb639aSgwr 	fbt->fb_type = FBTYPE_SUN2COLOR;
1921feb639aSgwr 	fbt->fb_depth = 8;
1931feb639aSgwr 	fbt->fb_cmsize = CMSIZE;
1941feb639aSgwr 
1951feb639aSgwr 	fbt->fb_width = 1152;
1961feb639aSgwr 	fbt->fb_height = 900;
1971feb639aSgwr 	fbt->fb_size = CG2_MAPPED_SIZE;
1981feb639aSgwr 
199a087bfebSchristos 	printf(" (%dx%d)\n", fbt->fb_width, fbt->fb_height);
2001feb639aSgwr 	fb_attach(fb, 2);
2011feb639aSgwr }
2021feb639aSgwr 
2031feb639aSgwr int
2041feb639aSgwr cg2open(dev, flags, mode, p)
2051feb639aSgwr 	dev_t dev;
2061feb639aSgwr 	int flags, mode;
2071feb639aSgwr 	struct proc *p;
2081feb639aSgwr {
2091feb639aSgwr 	int unit = minor(dev);
2101feb639aSgwr 
2113cd14f75Sthorpej 	if (unit >= cgtwo_cd.cd_ndevs || cgtwo_cd.cd_devs[unit] == NULL)
2121feb639aSgwr 		return (ENXIO);
2131feb639aSgwr 	return (0);
2141feb639aSgwr }
2151feb639aSgwr 
2161feb639aSgwr int
2171feb639aSgwr cg2ioctl(dev, cmd, data, flags, p)
2181feb639aSgwr 	dev_t dev;
2191feb639aSgwr 	u_long cmd;
2201feb639aSgwr 	caddr_t data;
2211feb639aSgwr 	int flags;
2221feb639aSgwr 	struct proc *p;
2231feb639aSgwr {
2243cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2251feb639aSgwr 
2261feb639aSgwr 	return (fbioctlfb(&sc->sc_fb, cmd, data));
2271feb639aSgwr }
2281feb639aSgwr 
2291feb639aSgwr /*
2301feb639aSgwr  * Return the address that would map the given device at the given
2311feb639aSgwr  * offset, allowing for the given protection, or return -1 for error.
2321feb639aSgwr  */
233889c658bSsimonb paddr_t
234ca5caf00Smycroft cg2mmap(dev, off, prot)
2351feb639aSgwr 	dev_t dev;
236889c658bSsimonb 	off_t off;
237889c658bSsimonb 	int prot;
2381feb639aSgwr {
2393cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2401feb639aSgwr 
2411feb639aSgwr 	if (off & PGOFSET)
242795010b5Smycroft 		panic("cg2mmap");
2431feb639aSgwr 
244889c658bSsimonb 	if (off >= CG2_MAPPED_SIZE)
2451feb639aSgwr 		return (-1);
2461feb639aSgwr 
2471feb639aSgwr 	/*
2481feb639aSgwr 	 * I turned on PMAP_NC here to disable the cache as I was
2491feb639aSgwr 	 * getting horribly broken behaviour with it on.
2501feb639aSgwr 	 */
2511feb639aSgwr 	return ((sc->sc_phys + off) | sc->sc_pmtype);
2521feb639aSgwr }
2531feb639aSgwr 
2541feb639aSgwr /*
2551feb639aSgwr  * Internal ioctl functions.
2561feb639aSgwr  */
2571feb639aSgwr 
2581feb639aSgwr /* FBIOGATTR: */
2590c5e3e49Sgwr static int  cg2gattr(fb, data)
2601feb639aSgwr 	struct fbdevice *fb;
2610c5e3e49Sgwr 	void *data;
2621feb639aSgwr {
2630c5e3e49Sgwr 	struct fbgattr *fba = data;
2641feb639aSgwr 
2651feb639aSgwr 	fba->real_type = fb->fb_fbtype.fb_type;
2661feb639aSgwr 	fba->owner = 0;		/* XXX - TIOCCONS stuff? */
2671feb639aSgwr 	fba->fbtype = fb->fb_fbtype;
2681feb639aSgwr 	fba->sattr.flags = 0;
2691feb639aSgwr 	fba->sattr.emu_type = fb->fb_fbtype.fb_type;
2701feb639aSgwr 	fba->sattr.dev_specific[0] = -1;
2711feb639aSgwr 	fba->emu_types[0] = fb->fb_fbtype.fb_type;
2721feb639aSgwr 	fba->emu_types[1] = -1;
2731feb639aSgwr 	return (0);
2741feb639aSgwr }
2751feb639aSgwr 
2761feb639aSgwr /* FBIOGVIDEO: */
2770c5e3e49Sgwr static int  cg2gvideo(fb, data)
2781feb639aSgwr 	struct fbdevice *fb;
2790c5e3e49Sgwr 	void *data;
2801feb639aSgwr {
2810c5e3e49Sgwr 	int *on = data;
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: */
2890c5e3e49Sgwr static int cg2svideo(fb, data)
2901feb639aSgwr 	struct fbdevice *fb;
2910c5e3e49Sgwr 	void *data;
2921feb639aSgwr {
2930c5e3e49Sgwr 	int *on = data;
2941feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
2951feb639aSgwr 
2961feb639aSgwr 	sc->sc_ctlreg->status.reg.video_enab = (*on) & 1;
2971feb639aSgwr 
2981feb639aSgwr 	return (0);
2991feb639aSgwr }
3001feb639aSgwr 
3011feb639aSgwr /* FBIOGETCMAP: */
3020c5e3e49Sgwr static int cg2getcmap(fb, data)
3031feb639aSgwr 	struct fbdevice *fb;
3040c5e3e49Sgwr 	void *data;
3051feb639aSgwr {
3060c5e3e49Sgwr 	struct fbcmap *cmap = data;
3071feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3081feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
3091feb639aSgwr 	int error, start, count, ecount;
310eabd6921Stsutsui 	u_int i;
311eabd6921Stsutsui 	u_short *p;
3121feb639aSgwr 
3131feb639aSgwr 	start = cmap->index;
3141feb639aSgwr 	count = cmap->count;
3151feb639aSgwr 	ecount = start + count;
3168dd04cdcSitojun 	if (start >= CMSIZE || count > CMSIZE - start)
3171feb639aSgwr 		return (EINVAL);
3181feb639aSgwr 
3191feb639aSgwr 	/* XXX - Wait for retrace? */
3201feb639aSgwr 
3211feb639aSgwr 	/* Copy hardware to local arrays. */
3221feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3231feb639aSgwr 	for (i = start; i < ecount; i++)
3241feb639aSgwr 		red[i] = *p++;
3251feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3261feb639aSgwr 	for (i = start; i < ecount; i++)
3271feb639aSgwr 		green[i] = *p++;
3281feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3291feb639aSgwr 	for (i = start; i < ecount; i++)
3301feb639aSgwr 		blue[i] = *p++;
3311feb639aSgwr 
3321feb639aSgwr 	/* Copy local arrays to user space. */
3331feb639aSgwr 	if ((error = copyout(red + start, cmap->red, count)) != 0)
3341feb639aSgwr 		return (error);
3351feb639aSgwr 	if ((error = copyout(green + start, cmap->green, count)) != 0)
3361feb639aSgwr 		return (error);
3371feb639aSgwr 	if ((error = copyout(blue + start, cmap->blue, count)) != 0)
3381feb639aSgwr 		return (error);
3391feb639aSgwr 
3401feb639aSgwr 	return (0);
3411feb639aSgwr }
3421feb639aSgwr 
3431feb639aSgwr /* FBIOPUTCMAP: */
3440c5e3e49Sgwr static int cg2putcmap(fb, data)
3451feb639aSgwr 	struct fbdevice *fb;
3460c5e3e49Sgwr 	void *data;
3471feb639aSgwr {
3480c5e3e49Sgwr 	struct fbcmap *cmap = data;
3491feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3501feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
35174954dadSjdolecek 	int error;
35274954dadSjdolecek 	u_int start, count, ecount;
353eabd6921Stsutsui 	u_int i;
354eabd6921Stsutsui 	u_short *p;
3551feb639aSgwr 
3561feb639aSgwr 	start = cmap->index;
3571feb639aSgwr 	count = cmap->count;
3581feb639aSgwr 	ecount = start + count;
3598dd04cdcSitojun 	if (start >= CMSIZE || count > CMSIZE - start)
3601feb639aSgwr 		return (EINVAL);
3611feb639aSgwr 
3621feb639aSgwr 	/* Copy from user space to local arrays. */
3631feb639aSgwr 	if ((error = copyin(cmap->red, red + start, count)) != 0)
3641feb639aSgwr 		return (error);
3651feb639aSgwr 	if ((error = copyin(cmap->green, green + start, count)) != 0)
3661feb639aSgwr 		return (error);
3671feb639aSgwr 	if ((error = copyin(cmap->blue, blue + start, count)) != 0)
3681feb639aSgwr 		return (error);
3691feb639aSgwr 
3701feb639aSgwr 	/* XXX - Wait for retrace? */
3711feb639aSgwr 
3721feb639aSgwr 	/* Copy from local arrays to hardware. */
3731feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3741feb639aSgwr 	for (i = start; i < ecount; i++)
3751feb639aSgwr 		*p++ = red[i];
3761feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3771feb639aSgwr 	for (i = start; i < ecount; i++)
3781feb639aSgwr 		*p++ = green[i];
3791feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3801feb639aSgwr 	for (i = start; i < ecount; i++)
3811feb639aSgwr 		*p++ = blue[i];
3821feb639aSgwr 
3831feb639aSgwr 	return (0);
3841feb639aSgwr 
3851feb639aSgwr }
3861feb639aSgwr 
3871feb639aSgwr static int
3881feb639aSgwr cg2intr(vsc)
3891feb639aSgwr 	void *vsc;
3901feb639aSgwr {
3911feb639aSgwr 	struct cg2_softc *sc = vsc;
3921feb639aSgwr 
3931feb639aSgwr 	/* XXX - Just disable interrupts for now. */
3941feb639aSgwr 	sc->sc_ctlreg->status.reg.inten = 0;
3951feb639aSgwr 
396a087bfebSchristos 	printf("cg2intr\n");
3971feb639aSgwr 	return (1);
3981feb639aSgwr }
399