summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev/bwtwo.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc/dev/bwtwo.c')
-rw-r--r--sys/arch/sparc/dev/bwtwo.c380
1 files changed, 240 insertions, 140 deletions
diff --git a/sys/arch/sparc/dev/bwtwo.c b/sys/arch/sparc/dev/bwtwo.c
index b024a82640a..78be5d0b885 100644
--- a/sys/arch/sparc/dev/bwtwo.c
+++ b/sys/arch/sparc/dev/bwtwo.c
@@ -1,35 +1,7 @@
-/* $NetBSD: bwtwo.c,v 1.15 1995/10/09 15:39:34 pk Exp $ */
+/* $NetBSD: bwtwo.c,v 1.26 1996/04/01 17:30:15 christos Exp $ */
/*
- * Copyright (c) 1995 Theo de Raadt
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed under OpenBSD by
- * Theo de Raadt.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
+ * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -77,14 +49,19 @@
* black&white display (bwtwo) driver.
*
* Does not handle interrupts, even though they can occur.
+ *
+ * P4 and overlay plane support by Jason R. Thorpe <thorpej@NetBSD.ORG>.
+ * Overlay plane handling hints and ideas provided by Brad Spencer.
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/tty.h>
+#include <sys/conf.h>
#include <vm/vm.h>
@@ -92,25 +69,36 @@
#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/fbvar.h>
-#if defined(SUN4)
#include <machine/eeprom.h>
#include <machine/ctlreg.h>
+#include <machine/conf.h>
#include <sparc/sparc/asm.h>
-#endif
+#include <sparc/dev/btreg.h>
#include <sparc/dev/bwtworeg.h>
-#include <sparc/dev/pfourreg.h>
#include <sparc/dev/sbusvar.h>
-#include "pfour.h"
+#if defined(SUN4)
+#include <sparc/dev/pfourreg.h>
+#endif
/* per-display variables */
struct bwtwo_softc {
struct device sc_dev; /* base device */
struct sbusdev sc_sd; /* sbus device */
struct fbdevice sc_fb; /* frame buffer device */
- volatile struct bwtworeg *sc_reg;/* control registers */
- struct rom_reg sc_phys; /* display RAM (phys addr) */
- int sc_bustype;
+ volatile struct fbcontrol *sc_reg;/* control registers */
+ struct rom_reg sc_phys; /* phys address description */
+ int sc_bustype; /* type of bus we live on */
+ int sc_pixeloffset; /* offset to framebuffer */
+#if defined(SUN4)
+ /*
+ * Additional overlay plane goo.
+ */
+ int sc_ovtype; /* what kind of color fb? */
+#define BWO_NONE 0x00
+#define BWO_CGFOUR 0x01
+#define BWO_CGEIGHT 0x02
+#endif
};
/* autoconfiguration driver */
@@ -121,20 +109,24 @@ int bwtwoclose __P((dev_t, int, int, struct proc *));
int bwtwoioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
int bwtwommap __P((dev_t, int, int));
static void bwtwounblank __P((struct device *));
+static void bwtwo_set_video __P((struct bwtwo_softc *, int));
+static int bwtwo_get_video __P((struct bwtwo_softc *));
+
+struct cfattach bwtwo_ca = {
+ sizeof(struct bwtwo_softc), bwtwomatch, bwtwoattach
+};
-struct cfdriver bwtwocd = {
- NULL, "bwtwo", bwtwomatch, bwtwoattach,
- DV_DULL, sizeof(struct bwtwo_softc)
+struct cfdriver bwtwo_cd = {
+ NULL, "bwtwo", DV_DULL
};
+/* XXX we do not handle frame buffer interrupts (do not know how) */
+
/* frame buffer generic driver */
static struct fbdriver bwtwofbdriver = {
bwtwounblank, bwtwoopen, bwtwoclose, bwtwoioctl, bwtwommap
};
-static void bwtwoenable __P((struct bwtwo_softc *, int));
-static int bwtwostatus __P((struct bwtwo_softc *));
-
extern int fbnode;
extern struct tty *fbconstty;
@@ -150,18 +142,48 @@ bwtwomatch(parent, vcf, aux)
struct confargs *ca = aux;
struct romaux *ra = &ca->ca_ra;
+ if (CPU_ISSUN4 && cf->cf_unit != 0)
+ return (0);
+
if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
return (0);
+
+ /*
+ * Mask out invalid flags from the user.
+ */
+ cf->cf_flags &= FB_USERMASK;
+
if (ca->ca_bustype == BUS_SBUS)
return(1);
-#if NPFOUR > 0
- if (ca->ca_bustype == BUS_PFOUR) {
- if (PFOUR_ID(ra->ra_pfour) == PFOUR_ID_BW)
- return (1);
+
+ /*
+ * Make sure there's hardware there.
+ */
+ if (probeget(ra->ra_vaddr, 4) == -1)
return (0);
+
+#if defined(SUN4)
+ if (CPU_ISSUN4 && (ca->ca_bustype == BUS_OBIO)) {
+ /*
+ * Check for a pfour framebuffer.
+ */
+ switch (fb_pfour_id(ra->ra_vaddr)) {
+ case PFOUR_ID_BW:
+ case PFOUR_ID_COLOR8P1: /* bwtwo in ... */
+ case PFOUR_ID_COLOR24: /* ...overlay plane */
+ cf->cf_flags |= FB_PFOUR;
+ /* FALLTHROUGH */
+
+ case PFOUR_NOTPFOUR:
+ return (1);
+
+ default:
+ return (0);
+ }
}
#endif
- return (probeget(ra->ra_vaddr, 4) != -1);
+
+ return (0);
}
/*
@@ -175,107 +197,180 @@ bwtwoattach(parent, self, args)
register struct bwtwo_softc *sc = (struct bwtwo_softc *)self;
register struct confargs *ca = args;
register int node = ca->ca_ra.ra_node, ramsize;
- int isconsole;
- char *nam;
+ struct fbdevice *fb = &sc->sc_fb;
+ int isconsole = 0;
+ int sbus = 1;
+ char *nam = NULL;
- sc->sc_fb.fb_driver = &bwtwofbdriver;
- sc->sc_fb.fb_device = &sc->sc_dev;
- sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2BW;
+ fb->fb_driver = &bwtwofbdriver;
+ fb->fb_device = &sc->sc_dev;
+ fb->fb_type.fb_type = FBTYPE_SUN2BW;
+ fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags;
+
+ /*
+ * Map the control register.
+ */
+ if (fb->fb_flags & FB_PFOUR) {
+ fb->fb_pfour =
+ (volatile u_int32_t *)mapiodev(ca->ca_ra.ra_reg, 0,
+ sizeof(u_int32_t), ca->ca_bustype);
+ sc->sc_reg = NULL;
+ } else {
+ sc->sc_reg =
+ (volatile struct fbcontrol *)mapiodev(ca->ca_ra.ra_reg,
+ BWREG_REG, sizeof(struct fbcontrol), ca->ca_bustype);
+ fb->fb_pfour = NULL;
+ }
+
+ /* Set up default pixel offset. May be changed below. */
+ sc->sc_pixeloffset = BWREG_MEM;
- sc->sc_bustype = ca->ca_bustype;
switch (ca->ca_bustype) {
-#if defined(SUN4)
-#if NPFOUR > 0
- case BUS_PFOUR:
- node = 0;
- pfour_reset();
- pfour_videosize(ca->ca_ra.ra_pfour,
- &sc->sc_fb.fb_type.fb_width,
- &sc->sc_fb.fb_type.fb_height);
- sc->sc_fb.fb_linebytes = sc->sc_fb.fb_type.fb_width / 8;
- nam = "bwtwo";
- break;
-#endif
-#endif
case BUS_OBIO:
-#if defined(SUN4M)
- if (cputyp == CPU_SUN4M) { /* 4m has framebuffer on obio */
- nam = getpropstring(node, "model");
- break;
- }
-#endif
+ if (CPU_ISSUN4M) /* 4m has framebuffer on obio */
+ goto obp_name;
+
+ sbus = node = 0;
#if defined(SUN4)
- node = 0;
+ if (fb->fb_flags & FB_PFOUR) {
+ nam = "bwtwo/p4";
+ /*
+ * Notice if this is an overlay plane on a color
+ * framebuffer. Note that PFOUR_COLOR_OFF_OVERLAY
+ * is the same as PFOUR_BW_OFF, but we use the
+ * different names anyway.
+ */
+ switch (PFOUR_ID(*fb->fb_pfour)) {
+ case PFOUR_ID_COLOR8P1:
+ sc->sc_ovtype = BWO_CGFOUR;
+ sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY;
+ break;
+
+ case PFOUR_ID_COLOR24:
+ sc->sc_ovtype = BWO_CGEIGHT;
+ sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY;
+ break;
+
+ default:
+ sc->sc_ovtype = BWO_NONE;
+ sc->sc_pixeloffset = PFOUR_BW_OFF;
+ break;
+ }
+ } else
+#endif
+ nam = "bwtwo";
+ break;
+
+ case BUS_VME32:
+ case BUS_VME16:
+ sbus = node = 0;
nam = "bwtwo";
break;
-#endif
+
case BUS_SBUS:
+ obp_name:
#if defined(SUN4C) || defined(SUN4M)
nam = getpropstring(node, "model");
- break;
#endif
+ break;
}
+
sc->sc_phys = ca->ca_ra.ra_reg[0];
sc->sc_bustype = ca->ca_bustype;
- sc->sc_fb.fb_type.fb_depth = 1;
- fb_setsize(&sc->sc_fb, sc->sc_fb.fb_type.fb_depth,
- 1152, 900, node, ca->ca_bustype);
+ fb->fb_type.fb_depth = 1;
+ fb_setsize(fb, fb->fb_type.fb_depth, 1152, 900, node, ca->ca_bustype);
- ramsize = sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes;
- sc->sc_fb.fb_type.fb_cmsize = 0;
- sc->sc_fb.fb_type.fb_size = ramsize;
+ ramsize = fb->fb_type.fb_height * fb->fb_linebytes;
+ fb->fb_type.fb_cmsize = 0;
+ fb->fb_type.fb_size = ramsize;
printf(": %s, %d x %d", nam,
- sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height);
+ fb->fb_type.fb_width, fb->fb_type.fb_height);
#if defined(SUN4)
- if (cputyp == CPU_SUN4) {
+ if (CPU_ISSUN4) {
struct eeprom *eep = (struct eeprom *)eeprom_va;
+ int constype = (fb->fb_flags & FB_PFOUR) ? EE_CONS_P4OPT :
+ EE_CONS_BW;
/*
* Assume this is the console if there's no eeprom info
* to be found.
*/
- if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_BW)
+ if (eep == NULL || eep->eeConsole == constype)
isconsole = (fbconstty != NULL);
else
isconsole = 0;
}
#endif
-#if defined(SUN4C) || defined(SUN4M)
- if (cputyp == CPU_SUN4C || cputyp == CPU_SUN4M)
+
+ if (CPU_ISSUN4COR4M)
isconsole = node == fbnode && fbconstty != NULL;
-#endif
+
/*
* When the ROM has mapped in a bwtwo display, the address
- * maps only the video RAM, so in any case we have to map the
+ * maps only the video RAM, hence we always map the control
* registers ourselves. We only need the video RAM if we are
* going to print characters via rconsole.
*/
- if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) {
+ if ((fb->fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) {
/* this probably cannot happen (on sun4c), but what the heck */
- sc->sc_fb.fb_pixels = mapiodev(ca->ca_ra.ra_reg, BWREG_MEM,
+ fb->fb_pixels =
+ mapiodev(ca->ca_ra.ra_reg, sc->sc_pixeloffset,
ramsize, ca->ca_bustype);
}
- sc->sc_reg = (volatile struct bwtworeg *)mapiodev(ca->ca_ra.ra_reg,
- BWREG_REG, sizeof(struct bwtworeg), ca->ca_bustype);
/* Insure video is enabled */
- bwtwoenable(sc, 1);
+ bwtwo_set_video(sc, 1);
if (isconsole) {
printf(" (console)\n");
#ifdef RASTERCONSOLE
- fbrcons_init(&sc->sc_fb);
+ fbrcons_init(fb);
#endif
} else
printf("\n");
+
#if defined(SUN4C) || defined(SUN4M)
- if (ca->ca_bustype == BUS_SBUS)
+ if (sbus)
sbus_establish(&sc->sc_sd, &sc->sc_dev);
#endif
- if ((node == fbnode && cputyp != CPU_SUN4) ||
- (isconsole && cputyp == CPU_SUN4))
- fb_attach(&sc->sc_fb);
+
+#if defined(SUN4)
+ if ((fb->fb_flags & FB_PFOUR) && (sc->sc_ovtype != BWO_NONE)) {
+ char *ovnam;
+
+ switch (sc->sc_ovtype) {
+ case BWO_CGFOUR:
+ ovnam = "cgfour";
+ break;
+
+ case BWO_CGEIGHT:
+ ovnam = "cgeight";
+ break;
+
+ default:
+ ovnam = "unknown";
+ break;
+ }
+ printf("%s: %s overlay plane\n", sc->sc_dev.dv_xname, ovnam);
+ }
+#endif
+
+ if (CPU_ISSUN4 || node == fbnode) {
+#if defined(SUN4)
+ /*
+ * If we're on an overlay plane of a color framebuffer,
+ * then we don't force the issue in fb_attach() because
+ * we'd like the color framebuffer to actually be the
+ * "console framebuffer". We're only around to speed
+ * up rconsole.
+ */
+ if ((fb->fb_flags & FB_PFOUR) && (sc->sc_ovtype != BWO_NONE ))
+ fb_attach(fb, 0);
+ else
+#endif
+ fb_attach(fb, isconsole);
+ }
}
int
@@ -286,8 +381,9 @@ bwtwoopen(dev, flags, mode, p)
{
int unit = minor(dev);
- if (unit >= bwtwocd.cd_ndevs || bwtwocd.cd_devs[unit] == NULL)
+ if (unit >= bwtwo_cd.cd_ndevs || bwtwo_cd.cd_devs[unit] == NULL)
return (ENXIO);
+
return (0);
}
@@ -309,7 +405,7 @@ bwtwoioctl(dev, cmd, data, flags, p)
int flags;
struct proc *p;
{
- struct bwtwo_softc *sc = bwtwocd.cd_devs[minor(dev)];
+ struct bwtwo_softc *sc = bwtwo_cd.cd_devs[minor(dev)];
switch (cmd) {
@@ -318,11 +414,11 @@ bwtwoioctl(dev, cmd, data, flags, p)
break;
case FBIOGVIDEO:
- bwtwostatus(sc);
+ *(int *)data = bwtwo_get_video(sc);
break;
case FBIOSVIDEO:
- bwtwoenable(sc, *(int *)data);
+ bwtwo_set_video(sc, (*(int *)data));
break;
default:
@@ -337,7 +433,7 @@ bwtwounblank(dev)
{
struct bwtwo_softc *sc = (struct bwtwo_softc *)dev;
- bwtwoenable(sc, 1);
+ bwtwo_set_video(sc, 1);
}
/*
@@ -349,7 +445,7 @@ bwtwommap(dev, off, prot)
dev_t dev;
int off, prot;
{
- register struct bwtwo_softc *sc = bwtwocd.cd_devs[minor(dev)];
+ register struct bwtwo_softc *sc = bwtwo_cd.cd_devs[minor(dev)];
if (off & PGOFSET)
panic("bwtwommap");
@@ -359,55 +455,59 @@ bwtwommap(dev, off, prot)
* I turned on PMAP_NC here to disable the cache as I was
* getting horribly broken behaviour with it on.
*/
- return (REG2PHYS(&sc->sc_phys, BWREG_MEM+off, sc->sc_bustype) | PMAP_NC);
+ return (REG2PHYS(&sc->sc_phys, sc->sc_pixeloffset + off,
+ sc->sc_bustype) | PMAP_NC);
}
-
-int
-bwtwostatus(sc)
+static int
+bwtwo_get_video(sc)
struct bwtwo_softc *sc;
{
-#ifdef SUN4
-#if NPFOUR > 0
- if (sc->sc_bustype == BUS_PFOUR)
- return pfourstatus();
-#endif
- if (sc->sc_bustype == BUS_OBIO)
- return (lduba(AC_SYSENABLE, ASI_CONTROL) & SYSEN_VIDEO);
-#endif
-#if defined(SUN4C) || defined(SUN4M)
- return (sc->sc_reg->bw_ctl & CTL_VE);
+
+#if defined(SUN4)
+ if (CPU_ISSUN4 && (sc->sc_bustype == BUS_OBIO)) {
+ if (sc->sc_fb.fb_flags & FB_PFOUR) {
+ /*
+ * This handles the overlay plane case, too.
+ */
+ return (fb_pfour_get_video(&sc->sc_fb));
+ } else
+ return ((lduba(AC_SYSENABLE,
+ ASI_CONTROL) & SYSEN_VIDEO) != 0);
+ }
#endif
+
+ return ((sc->sc_reg->fbc_ctrl & FBC_VENAB) != 0);
}
-void
-bwtwoenable(sc, on)
+static void
+bwtwo_set_video(sc, enable)
struct bwtwo_softc *sc;
- int on;
+ int enable;
{
-#if NPFOUR > 0
- if (sc->sc_bustype == BUS_PFOUR) {
- pfourenable(on);
+
+#if defined(SUN4)
+ if (CPU_ISSUN4 && (sc->sc_bustype == BUS_OBIO)) {
+ if (sc->sc_fb.fb_flags & FB_PFOUR) {
+ /*
+ * This handles the overlay plane case, too.
+ */
+ fb_pfour_set_video(&sc->sc_fb, enable);
return;
}
-#endif
- if (on) {
-#ifdef SUN4
- if (sc->sc_bustype == BUS_OBIO) {
+ if (enable)
stba(AC_SYSENABLE, ASI_CONTROL,
lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_VIDEO);
- return;
- }
-#endif
- sc->sc_reg->bw_ctl |= CTL_VE;
- } else {
-#ifdef SUN4
- if (sc->sc_bustype == BUS_OBIO) {
+ else
stba(AC_SYSENABLE, ASI_CONTROL,
lduba(AC_SYSENABLE, ASI_CONTROL) & ~SYSEN_VIDEO);
- return;
- }
-#endif
- sc->sc_reg->bw_ctl &= ~CTL_VE;
+
+ return;
}
+#endif
+
+ if (enable)
+ sc->sc_reg->fbc_ctrl |= FBC_VENAB;
+ else
+ sc->sc_reg->fbc_ctrl &= ~FBC_VENAB;
}