xref: /netbsd/sys/arch/sun3/dev/cg2.c (revision 8dd04cdc)
1*8dd04cdcSitojun /*	$NetBSD: cg2.c,v 1.17 2002/08/03 00:13:01 itojun 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 
740c5e3e49Sgwr cdev_decl(cg2);
750c5e3e49Sgwr 
761feb639aSgwr #define	CMSIZE 256
771feb639aSgwr 
781feb639aSgwr /* offset to and size of mapped part of frame buffer */
791feb639aSgwr #define PLANEMAP_SIZE		0x100000
801feb639aSgwr #define PIXELMAP_SIZE		0x100000
811feb639aSgwr #define ROWOPMAP_SIZE		0x100000
821feb639aSgwr 
831feb639aSgwr #define	CTLREGS_OFF 		0x300000
841feb639aSgwr #define	CTLREGS_SIZE		 0x10600
851feb639aSgwr 
861feb639aSgwr #define	CG2_MAPPED_OFFSET	(PLANEMAP_SIZE + PIXELMAP_SIZE)
87a1cc6d49Sgwr #define	CG2_MAPPED_SIZE 	(CTLREGS_OFF + CTLREGS_SIZE)
881feb639aSgwr 
891feb639aSgwr /* per-display variables */
901feb639aSgwr struct cg2_softc {
911feb639aSgwr 	struct	device sc_dev;		/* base device */
921feb639aSgwr 	struct	fbdevice sc_fb;		/* frame buffer device */
931feb639aSgwr 	int 	sc_phys;		/* display RAM (phys addr) */
941feb639aSgwr 	int 	sc_pmtype;		/* pmap type bits */
951feb639aSgwr 	struct	cg2fb *sc_ctlreg;	/* control registers */
961feb639aSgwr };
971feb639aSgwr 
981feb639aSgwr /* autoconfiguration driver */
991feb639aSgwr static void	cg2attach __P((struct device *, struct device *, void *));
1000c5e3e49Sgwr static int	cg2match __P((struct device *, struct cfdata *, void *));
1011feb639aSgwr 
1023cd14f75Sthorpej struct cfattach cgtwo_ca = {
1033cd14f75Sthorpej 	sizeof(struct cg2_softc), cg2match, cg2attach
1043cd14f75Sthorpej };
1053cd14f75Sthorpej 
106119b962aSgwr extern struct cfdriver cgtwo_cd;
107119b962aSgwr 
1080c5e3e49Sgwr static int  cg2gattr __P((struct fbdevice *,  void *));
1090c5e3e49Sgwr static int  cg2gvideo __P((struct fbdevice *, void *));
1100c5e3e49Sgwr static int	cg2svideo __P((struct fbdevice *, void *));
1110c5e3e49Sgwr static int	cg2getcmap __P((struct fbdevice *, void *));
1120c5e3e49Sgwr static int	cg2putcmap __P((struct fbdevice *, void *));
1131feb639aSgwr 
1141feb639aSgwr static struct fbdriver cg2fbdriver = {
115795010b5Smycroft 	cg2open, cg2close, cg2mmap, cg2gattr,
1161feb639aSgwr 	cg2gvideo, cg2svideo,
1171feb639aSgwr 	cg2getcmap, cg2putcmap };
1181feb639aSgwr 
1191feb639aSgwr static int cg2intr __P((void*));
1201feb639aSgwr 
1211feb639aSgwr /*
1221feb639aSgwr  * Match a cg2.
1231feb639aSgwr  */
1241feb639aSgwr static int
125703ed32eSgwr cg2match(parent, cf, aux)
1261feb639aSgwr 	struct device *parent;
1270c5e3e49Sgwr 	struct cfdata *cf;
128703ed32eSgwr 	void *aux;
1291feb639aSgwr {
130703ed32eSgwr 	struct confargs *ca = aux;
131703ed32eSgwr 	int probe_addr;
1321feb639aSgwr 
133703ed32eSgwr 	/* No default VME address. */
1341feb639aSgwr 	if (ca->ca_paddr == -1)
1351feb639aSgwr 		return (0);
1361feb639aSgwr 
137703ed32eSgwr 	/* Make sure something is there... */
138703ed32eSgwr 	probe_addr = ca->ca_paddr + CTLREGS_OFF;
139703ed32eSgwr 	if (bus_peek(ca->ca_bustype, probe_addr, 1) == -1)
1401feb639aSgwr 		return (0);
1411feb639aSgwr 
142703ed32eSgwr 	/* XXX: look at the ID reg? */
143a087bfebSchristos 	/* printf("cg2: id=0x%x\n", x); */
1441feb639aSgwr 
145703ed32eSgwr 	/* Default interrupt priority. */
146703ed32eSgwr 	if (ca->ca_intpri == -1)
147703ed32eSgwr 		ca->ca_intpri = 4;
148703ed32eSgwr 
1491feb639aSgwr 	return (1);
1501feb639aSgwr }
1511feb639aSgwr 
1521feb639aSgwr /*
1531feb639aSgwr  * Attach a display.  We need to notice if it is the console, too.
1541feb639aSgwr  */
1551feb639aSgwr static void
1561feb639aSgwr cg2attach(parent, self, args)
1571feb639aSgwr 	struct device *parent, *self;
1581feb639aSgwr 	void *args;
1591feb639aSgwr {
1601feb639aSgwr 	struct cg2_softc *sc = (struct cg2_softc *)self;
1611feb639aSgwr 	struct fbdevice *fb = &sc->sc_fb;
1621feb639aSgwr 	struct confargs *ca = args;
1631feb639aSgwr 	struct fbtype *fbt;
1641feb639aSgwr 
1651feb639aSgwr 	sc->sc_phys = ca->ca_paddr;
1661feb639aSgwr 	sc->sc_pmtype = PMAP_NC | PMAP_VME16;
1671feb639aSgwr 
1681feb639aSgwr 	sc->sc_ctlreg = (struct cg2fb *) bus_mapin(ca->ca_bustype,
1691feb639aSgwr 			ca->ca_paddr + CTLREGS_OFF, CTLREGS_SIZE);
1701feb639aSgwr 
1711feb639aSgwr 	isr_add_vectored(cg2intr, (void*)sc,
1721feb639aSgwr 					 ca->ca_intpri, ca->ca_intvec);
1731feb639aSgwr 
1741feb639aSgwr 	/*
1751feb639aSgwr 	 * XXX - Initialize?  Determine type?
1761feb639aSgwr 	 */
1771feb639aSgwr 	sc->sc_ctlreg->intrptvec.reg = ca->ca_intvec;
1781feb639aSgwr 	sc->sc_ctlreg->status.word = 1;
1791feb639aSgwr 
1801feb639aSgwr 	fb->fb_driver = &cg2fbdriver;
1811feb639aSgwr 	fb->fb_private = sc;
1821feb639aSgwr 	fb->fb_name = sc->sc_dev.dv_xname;
1831feb639aSgwr 
1841feb639aSgwr 	fbt = &fb->fb_fbtype;
1851feb639aSgwr 	fbt->fb_type = FBTYPE_SUN2COLOR;
1861feb639aSgwr 	fbt->fb_depth = 8;
1871feb639aSgwr 	fbt->fb_cmsize = CMSIZE;
1881feb639aSgwr 
1891feb639aSgwr 	fbt->fb_width = 1152;
1901feb639aSgwr 	fbt->fb_height = 900;
1911feb639aSgwr 	fbt->fb_size = CG2_MAPPED_SIZE;
1921feb639aSgwr 
193a087bfebSchristos 	printf(" (%dx%d)\n", fbt->fb_width, fbt->fb_height);
1941feb639aSgwr 	fb_attach(fb, 2);
1951feb639aSgwr }
1961feb639aSgwr 
1971feb639aSgwr int
1981feb639aSgwr cg2open(dev, flags, mode, p)
1991feb639aSgwr 	dev_t dev;
2001feb639aSgwr 	int flags, mode;
2011feb639aSgwr 	struct proc *p;
2021feb639aSgwr {
2031feb639aSgwr 	int unit = minor(dev);
2041feb639aSgwr 
2053cd14f75Sthorpej 	if (unit >= cgtwo_cd.cd_ndevs || cgtwo_cd.cd_devs[unit] == NULL)
2061feb639aSgwr 		return (ENXIO);
2071feb639aSgwr 	return (0);
2081feb639aSgwr }
2091feb639aSgwr 
2101feb639aSgwr int
2111feb639aSgwr cg2close(dev, flags, mode, p)
2121feb639aSgwr 	dev_t dev;
2131feb639aSgwr 	int flags, mode;
2141feb639aSgwr 	struct proc *p;
2151feb639aSgwr {
2161feb639aSgwr 
2171feb639aSgwr 	return (0);
2181feb639aSgwr }
2191feb639aSgwr 
2201feb639aSgwr int
2211feb639aSgwr cg2ioctl(dev, cmd, data, flags, p)
2221feb639aSgwr 	dev_t dev;
2231feb639aSgwr 	u_long cmd;
2241feb639aSgwr 	caddr_t data;
2251feb639aSgwr 	int flags;
2261feb639aSgwr 	struct proc *p;
2271feb639aSgwr {
2283cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2291feb639aSgwr 
2301feb639aSgwr 	return (fbioctlfb(&sc->sc_fb, cmd, data));
2311feb639aSgwr }
2321feb639aSgwr 
2331feb639aSgwr /*
2341feb639aSgwr  * Return the address that would map the given device at the given
2351feb639aSgwr  * offset, allowing for the given protection, or return -1 for error.
2361feb639aSgwr  */
237889c658bSsimonb paddr_t
238ca5caf00Smycroft cg2mmap(dev, off, prot)
2391feb639aSgwr 	dev_t dev;
240889c658bSsimonb 	off_t off;
241889c658bSsimonb 	int prot;
2421feb639aSgwr {
2433cd14f75Sthorpej 	struct cg2_softc *sc = cgtwo_cd.cd_devs[minor(dev)];
2441feb639aSgwr 
2451feb639aSgwr 	if (off & PGOFSET)
246795010b5Smycroft 		panic("cg2mmap");
2471feb639aSgwr 
248889c658bSsimonb 	if (off >= CG2_MAPPED_SIZE)
2491feb639aSgwr 		return (-1);
2501feb639aSgwr 
2511feb639aSgwr 	/*
2521feb639aSgwr 	 * I turned on PMAP_NC here to disable the cache as I was
2531feb639aSgwr 	 * getting horribly broken behaviour with it on.
2541feb639aSgwr 	 */
2551feb639aSgwr 	return ((sc->sc_phys + off) | sc->sc_pmtype);
2561feb639aSgwr }
2571feb639aSgwr 
2581feb639aSgwr /*
2591feb639aSgwr  * Internal ioctl functions.
2601feb639aSgwr  */
2611feb639aSgwr 
2621feb639aSgwr /* FBIOGATTR: */
2630c5e3e49Sgwr static int  cg2gattr(fb, data)
2641feb639aSgwr 	struct fbdevice *fb;
2650c5e3e49Sgwr 	void *data;
2661feb639aSgwr {
2670c5e3e49Sgwr 	struct fbgattr *fba = data;
2681feb639aSgwr 
2691feb639aSgwr 	fba->real_type = fb->fb_fbtype.fb_type;
2701feb639aSgwr 	fba->owner = 0;		/* XXX - TIOCCONS stuff? */
2711feb639aSgwr 	fba->fbtype = fb->fb_fbtype;
2721feb639aSgwr 	fba->sattr.flags = 0;
2731feb639aSgwr 	fba->sattr.emu_type = fb->fb_fbtype.fb_type;
2741feb639aSgwr 	fba->sattr.dev_specific[0] = -1;
2751feb639aSgwr 	fba->emu_types[0] = fb->fb_fbtype.fb_type;
2761feb639aSgwr 	fba->emu_types[1] = -1;
2771feb639aSgwr 	return (0);
2781feb639aSgwr }
2791feb639aSgwr 
2801feb639aSgwr /* FBIOGVIDEO: */
2810c5e3e49Sgwr static int  cg2gvideo(fb, data)
2821feb639aSgwr 	struct fbdevice *fb;
2830c5e3e49Sgwr 	void *data;
2841feb639aSgwr {
2850c5e3e49Sgwr 	int *on = data;
2861feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
2871feb639aSgwr 
2881feb639aSgwr 	*on = sc->sc_ctlreg->status.reg.video_enab;
2891feb639aSgwr 	return (0);
2901feb639aSgwr }
2911feb639aSgwr 
2921feb639aSgwr /* FBIOSVIDEO: */
2930c5e3e49Sgwr static int cg2svideo(fb, data)
2941feb639aSgwr 	struct fbdevice *fb;
2950c5e3e49Sgwr 	void *data;
2961feb639aSgwr {
2970c5e3e49Sgwr 	int *on = data;
2981feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
2991feb639aSgwr 
3001feb639aSgwr 	sc->sc_ctlreg->status.reg.video_enab = (*on) & 1;
3011feb639aSgwr 
3021feb639aSgwr 	return (0);
3031feb639aSgwr }
3041feb639aSgwr 
3051feb639aSgwr /* FBIOGETCMAP: */
3060c5e3e49Sgwr static int cg2getcmap(fb, data)
3071feb639aSgwr 	struct fbdevice *fb;
3080c5e3e49Sgwr 	void *data;
3091feb639aSgwr {
3100c5e3e49Sgwr 	struct fbcmap *cmap = data;
3111feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3121feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
3131feb639aSgwr 	int error, start, count, ecount;
314eabd6921Stsutsui 	u_int i;
315eabd6921Stsutsui 	u_short *p;
3161feb639aSgwr 
3171feb639aSgwr 	start = cmap->index;
3181feb639aSgwr 	count = cmap->count;
3191feb639aSgwr 	ecount = start + count;
320*8dd04cdcSitojun 	if (start >= CMSIZE || count > CMSIZE - start)
3211feb639aSgwr 		return (EINVAL);
3221feb639aSgwr 
3231feb639aSgwr 	/* XXX - Wait for retrace? */
3241feb639aSgwr 
3251feb639aSgwr 	/* Copy hardware to local arrays. */
3261feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3271feb639aSgwr 	for (i = start; i < ecount; i++)
3281feb639aSgwr 		red[i] = *p++;
3291feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3301feb639aSgwr 	for (i = start; i < ecount; i++)
3311feb639aSgwr 		green[i] = *p++;
3321feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3331feb639aSgwr 	for (i = start; i < ecount; i++)
3341feb639aSgwr 		blue[i] = *p++;
3351feb639aSgwr 
3361feb639aSgwr 	/* Copy local arrays to user space. */
3371feb639aSgwr 	if ((error = copyout(red + start, cmap->red, count)) != 0)
3381feb639aSgwr 		return (error);
3391feb639aSgwr 	if ((error = copyout(green + start, cmap->green, count)) != 0)
3401feb639aSgwr 		return (error);
3411feb639aSgwr 	if ((error = copyout(blue + start, cmap->blue, count)) != 0)
3421feb639aSgwr 		return (error);
3431feb639aSgwr 
3441feb639aSgwr 	return (0);
3451feb639aSgwr }
3461feb639aSgwr 
3471feb639aSgwr /* FBIOPUTCMAP: */
3480c5e3e49Sgwr static int cg2putcmap(fb, data)
3491feb639aSgwr 	struct fbdevice *fb;
3500c5e3e49Sgwr 	void *data;
3511feb639aSgwr {
3520c5e3e49Sgwr 	struct fbcmap *cmap = data;
3531feb639aSgwr 	struct cg2_softc *sc = fb->fb_private;
3541feb639aSgwr 	u_char red[CMSIZE], green[CMSIZE], blue[CMSIZE];
35574954dadSjdolecek 	int error;
35674954dadSjdolecek 	u_int start, count, ecount;
357eabd6921Stsutsui 	u_int i;
358eabd6921Stsutsui 	u_short *p;
3591feb639aSgwr 
3601feb639aSgwr 	start = cmap->index;
3611feb639aSgwr 	count = cmap->count;
3621feb639aSgwr 	ecount = start + count;
363*8dd04cdcSitojun 	if (start >= CMSIZE || count > CMSIZE - start)
3641feb639aSgwr 		return (EINVAL);
3651feb639aSgwr 
3661feb639aSgwr 	/* Copy from user space to local arrays. */
3671feb639aSgwr 	if ((error = copyin(cmap->red, red + start, count)) != 0)
3681feb639aSgwr 		return (error);
3691feb639aSgwr 	if ((error = copyin(cmap->green, green + start, count)) != 0)
3701feb639aSgwr 		return (error);
3711feb639aSgwr 	if ((error = copyin(cmap->blue, blue + start, count)) != 0)
3721feb639aSgwr 		return (error);
3731feb639aSgwr 
3741feb639aSgwr 	/* XXX - Wait for retrace? */
3751feb639aSgwr 
3761feb639aSgwr 	/* Copy from local arrays to hardware. */
3771feb639aSgwr 	p = &sc->sc_ctlreg->redmap[start];
3781feb639aSgwr 	for (i = start; i < ecount; i++)
3791feb639aSgwr 		*p++ = red[i];
3801feb639aSgwr 	p = &sc->sc_ctlreg->greenmap[start];
3811feb639aSgwr 	for (i = start; i < ecount; i++)
3821feb639aSgwr 		*p++ = green[i];
3831feb639aSgwr 	p = &sc->sc_ctlreg->bluemap[start];
3841feb639aSgwr 	for (i = start; i < ecount; i++)
3851feb639aSgwr 		*p++ = blue[i];
3861feb639aSgwr 
3871feb639aSgwr 	return (0);
3881feb639aSgwr 
3891feb639aSgwr }
3901feb639aSgwr 
3911feb639aSgwr static int
3921feb639aSgwr cg2intr(vsc)
3931feb639aSgwr 	void *vsc;
3941feb639aSgwr {
3951feb639aSgwr 	struct cg2_softc *sc = vsc;
3961feb639aSgwr 
3971feb639aSgwr 	/* XXX - Just disable interrupts for now. */
3981feb639aSgwr 	sc->sc_ctlreg->status.reg.inten = 0;
3991feb639aSgwr 
400a087bfebSchristos 	printf("cg2intr\n");
4011feb639aSgwr 	return (1);
4021feb639aSgwr }
403