diff options
Diffstat (limited to 'sys/arch/sparc/dev/cgfour.c')
-rw-r--r-- | sys/arch/sparc/dev/cgfour.c | 346 |
1 files changed, 212 insertions, 134 deletions
diff --git a/sys/arch/sparc/dev/cgfour.c b/sys/arch/sparc/dev/cgfour.c index ebd6b1fecd7..d5dde467a9c 100644 --- a/sys/arch/sparc/dev/cgfour.c +++ b/sys/arch/sparc/dev/cgfour.c @@ -1,6 +1,7 @@ -/* $NetBSD: cgfour.c,v 1.12 1994/11/23 07:02:07 deraadt Exp $ */ +/* $NetBSD: cgfour.c,v 1.7 1996/04/01 17:29:58 christos Exp $ */ /* + * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. * Copyright (c) 1995 Theo de Raadt. All rights reserved. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -58,12 +59,14 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/buf.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> @@ -71,20 +74,20 @@ #include <machine/autoconf.h> #include <machine/pmap.h> #include <machine/fbvar.h> +#include <machine/eeprom.h> +#include <machine/conf.h> #include <sparc/dev/btreg.h> #include <sparc/dev/btvar.h> -#include <sparc/dev/cgfourreg.h> #include <sparc/dev/pfourreg.h> /* per-display variables */ struct cgfour_softc { struct device sc_dev; /* base device */ struct fbdevice sc_fb; /* frame buffer device */ - volatile struct bt_regs *sc_bt; /* Brooktree registers */ struct rom_reg sc_phys; /* display RAM (phys addr) */ + volatile struct fbcontrol *sc_fbc; /* Brooktree registers */ int sc_bustype; /* type of bus we live on */ - int sc_blanked; /* true if blanked */ union bt_cmap sc_cmap; /* Brooktree color map */ }; @@ -95,13 +98,19 @@ int cgfouropen __P((dev_t, int, int, struct proc *)); int cgfourclose __P((dev_t, int, int, struct proc *)); int cgfourioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); int cgfourmmap __P((dev_t, int, int)); +#if defined(SUN4) static void cgfourunblank __P((struct device *)); +#endif + +struct cfattach cgfour_ca = { + sizeof(struct cgfour_softc), cgfourmatch, cgfourattach +}; -struct cfdriver cgfourcd = { - NULL, "cgfour", cgfourmatch, cgfourattach, - DV_DULL, sizeof(struct cgfour_softc) +struct cfdriver cgfour_cd = { + NULL, "cgfour", DV_DULL }; +#if defined(SUN4) /* frame buffer generic driver */ static struct fbdriver cgfourfbdriver = { cgfourunblank, cgfouropen, cgfourclose, cgfourioctl, cgfourmmap @@ -111,6 +120,9 @@ extern int fbnode; extern struct tty *fbconstty; static void cgfourloadcmap __P((struct cgfour_softc *, int, int)); +static int cgfour_get_video __P((struct cgfour_softc *)); +static void cgfour_set_video __P((struct cgfour_softc *, int)); +#endif /* * Match a cgfour. @@ -126,8 +138,40 @@ cgfourmatch(parent, vcf, aux) if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) return (0); - if (PFOUR_ID(ra->ra_pfour) == PFOUR_ID_COLOR8P1) + + /* + * Mask out invalid flags from the user. + */ + cf->cf_flags &= FB_USERMASK; + + /* + * Only exists on a sun4. + */ + if (!CPU_ISSUN4) + return (0); + + /* + * Only exists on obio. + */ + if (ca->ca_bustype != BUS_OBIO) + return (0); + + /* + * Make sure there's hardware there. + */ + if (probeget(ra->ra_vaddr, 4) == -1) + return (0); + +#if defined(SUN4) + /* + * Check the pfour register. + */ + if (fb_pfour_id(ra->ra_vaddr) == PFOUR_ID_COLOR8P1) { + cf->cf_flags |= FB_PFOUR; return (1); + } +#endif + return (0); } @@ -139,74 +183,109 @@ cgfourattach(parent, self, args) struct device *parent, *self; void *args; { +#if defined(SUN4) register struct cgfour_softc *sc = (struct cgfour_softc *)self; register struct confargs *ca = args; register int node = 0, ramsize, i; register volatile struct bt_regs *bt; + struct fbdevice *fb = &sc->sc_fb; int isconsole; - sc->sc_fb.fb_driver = &cgfourfbdriver; - sc->sc_fb.fb_device = &sc->sc_dev; - sc->sc_fb.fb_type.fb_type = FBTYPE_SUN4COLOR; + fb->fb_driver = &cgfourfbdriver; + fb->fb_device = &sc->sc_dev; + fb->fb_type.fb_type = FBTYPE_SUN4COLOR; + fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags; + + /* + * Only pfour cgfours, thank you... + */ + if ((ca->ca_bustype != BUS_OBIO) || + ((fb->fb_flags & FB_PFOUR) == 0)) { + printf("%s: ignoring; not a pfour\n", sc->sc_dev.dv_xname); + return; + } + + /* Map the pfour register. */ + fb->fb_pfour = (volatile u_int32_t *)mapiodev(ca->ca_ra.ra_reg, 0, + sizeof(u_int32_t), ca->ca_bustype); + + ramsize = PFOUR_COLOR_OFF_END - PFOUR_COLOR_OFF_OVERLAY; + + fb->fb_type.fb_depth = 8; + fb_setsize(fb, fb->fb_type.fb_depth, 1152, 900, node, ca->ca_bustype); + + fb->fb_type.fb_cmsize = 256; + fb->fb_type.fb_size = ramsize; + printf(": cgfour/p4, %d x %d", fb->fb_type.fb_width, + fb->fb_type.fb_height); + + isconsole = 0; - pfour_reset(); - pfour_videosize(ca->ca_ra.ra_pfour, &sc->sc_fb.fb_type.fb_width, - &sc->sc_fb.fb_type.fb_height); + if (CPU_ISSUN4) { + struct eeprom *eep = (struct eeprom *)eeprom_va; - sc->sc_fb.fb_linebytes = sc->sc_fb.fb_type.fb_width; + /* + * Assume this is the console if there's no eeprom info + * to be found. + */ + if (eep == NULL || eep->eeConsole == EE_CONS_P4OPT) + isconsole = (fbconstty != NULL); + } - ramsize = CG4REG_END - CG4REG_OVERLAY; - sc->sc_fb.fb_type.fb_depth = 8; - sc->sc_fb.fb_type.fb_cmsize = 256; - sc->sc_fb.fb_type.fb_size = ramsize; - printf(": %d x %d", sc->sc_fb.fb_type.fb_width, - sc->sc_fb.fb_type.fb_height); +#if 0 + /* + * We don't do any of the console handling here. Instead, + * we let the bwtwo driver pick up the overlay plane and + * use it instead. Rconsole should have better performance + * with the 1-bit depth. + * -- Jason R. Thorpe <thorpej@NetBSD.ORG> + */ /* * When the ROM has mapped in a cgfour display, the address * maps only the video RAM, so in any case we have to map the * registers ourselves. We only need the video RAM if we are * going to print characters via rconsole. - * - * XXX: it is insane to map the full 0x800000 space, when - * the mmap code down below doesn't use it all. Ridiculous! */ - isconsole = node == fbnode && fbconstty != NULL; - if (ca->ca_ra.ra_vaddr == NULL) { - /* this probably cannot happen, but what the heck */ - ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, - ramsize, ca->ca_bustype); + + if (isconsole) { + /* XXX this is kind of a waste */ + fb->fb_pixels = mapiodev(ca->ca_ra.ra_reg, + PFOUR_COLOR_OFF_OVERLAY, ramsize, ca->ca_bustype); } - sc->sc_fb.fb_pixels = (char *)((int)ca->ca_ra.ra_vaddr + - CG4REG_COLOUR - CG4REG_OVERLAY); +#endif + + /* Map the Brooktree. */ + sc->sc_fbc = (volatile struct fbcontrol *)mapiodev(ca->ca_ra.ra_reg, + PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol), ca->ca_bustype); -#define O(memb) ((u_int)(&((struct cgfour_all *)0)->memb)) - sc->sc_bt = bt = (volatile struct bt_regs *)mapiodev(ca->ca_ra.ra_reg, - O(ba_btreg), sizeof(struct bt_regs), ca->ca_bustype); sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; /* grab initial (current) color map */ + bt = &sc->sc_fbc->fbc_dac; bt->bt_addr = 0; for (i = 0; i < 256 * 3 / 4; i++) ((char *)&sc->sc_cmap)[i] = bt->bt_cmap >> 24; - /* make sure we are not blanked (see cgfourunblank) */ - bt->bt_addr = 0x06 << 24; /* command reg */ - bt->bt_ctrl = 0x73 << 24; /* overlay plane */ - bt->bt_addr = 0x04 << 24; /* read mask */ - bt->bt_ctrl = 0xff << 24; /* color planes */ + BT_INIT(bt, 24); +#if 0 /* See above. */ if (isconsole) { printf(" (console)\n"); -#ifdef RASTERCONSOLE - fbrcons_init(&sc->sc_fb); +#if defined(RASTERCONSOLE) && 0 /* XXX been told it doesn't work well. */ + fbrcons_init(fb); #endif } else +#endif /* 0 */ printf("\n"); - if ((node == fbnode && cputyp != CPU_SUN4) || - (isconsole && cputyp == CPU_SUN4)) - fb_attach(&sc->sc_fb); + + /* + * Even though we're not using rconsole, we'd still like + * to notice if we're the console framebuffer. + */ + fb_attach(fb, isconsole); +#endif } int @@ -217,7 +296,7 @@ cgfouropen(dev, flags, mode, p) { int unit = minor(dev); - if (unit >= cgfourcd.cd_ndevs || cgfourcd.cd_devs[unit] == NULL) + if (unit >= cgfour_cd.cd_ndevs || cgfour_cd.cd_devs[unit] == NULL) return (ENXIO); return (0); } @@ -240,7 +319,8 @@ cgfourioctl(dev, cmd, data, flags, p) int flags; struct proc *p; { - register struct cgfour_softc *sc = cgfourcd.cd_devs[minor(dev)]; +#if defined(SUN4) + register struct cgfour_softc *sc = cgfour_cd.cd_devs[minor(dev)]; register struct fbgattr *fba; int error; @@ -278,62 +358,109 @@ cgfourioctl(dev, cmd, data, flags, p) break; case FBIOGVIDEO: - *(int *)data = sc->sc_blanked; + *(int *)data = cgfour_get_video(sc); break; case FBIOSVIDEO: - if (*(int *)data) - cgfourunblank(&sc->sc_dev); - else if (!sc->sc_blanked) { - register volatile struct bt_regs *bt; - - bt = sc->sc_bt; - bt->bt_addr = 0x06 << 24; /* command reg */ - bt->bt_ctrl = 0x70 << 24; /* overlay plane */ - bt->bt_addr = 0x04 << 24; /* read mask */ - bt->bt_ctrl = 0x00 << 24; /* color planes */ - /* - * Set color 0 to black -- note that this overwrites - * R of color 1. - */ - bt->bt_addr = 0 << 24; - bt->bt_cmap = 0 << 24; - - sc->sc_blanked = 1; - } + cgfour_set_video(sc, *(int *)data); break; default: return (ENOTTY); } +#endif return (0); } /* + * Return the address that would map the given device at the given + * offset, allowing for the given protection, or return -1 for error. + * + * the cg4 maps it's overlay plane for 128K, followed by the enable + * plane for 128K, followed by the colour plane (for as much colour + * as their is.) + * + * As well, mapping at an offset of 0x04000000 causes the cg4 to map + * only it's colour plane, at 0. + */ +int +cgfourmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + register struct cgfour_softc *sc = cgfour_cd.cd_devs[minor(dev)]; + int poff; + +#define START_ENABLE (128*1024) +#define START_COLOR ((128*1024) + (128*1024)) +#define COLOR_SIZE (sc->sc_fb.fb_type.fb_width * \ + sc->sc_fb.fb_type.fb_height) +#define END_COLOR (START_COLOR + COLOR_SIZE) +#define NOOVERLAY (0x04000000) + + if (off & PGOFSET) + panic("cgfourmap"); + + if ((u_int)off >= NOOVERLAY) { + off =- NOOVERLAY; + + /* + * X11 maps a huge chunk of the frame buffer; far more than + * there really is. We compensate by double-mapping the + * first page for as many other pages as it wants + */ + while (off >= COLOR_SIZE) + off -= COLOR_SIZE; /* XXX thorpej ??? */ + + poff = off + PFOUR_COLOR_OFF_COLOR; + } else if ((u_int)off < START_ENABLE) { + /* + * in overlay plane + */ + poff = PFOUR_COLOR_OFF_OVERLAY + off; + } else if ((u_int)off < START_COLOR) { + /* + * in enable plane + */ + poff = (off - START_ENABLE) + PFOUR_COLOR_OFF_ENABLE; + } else if ((u_int)off < END_COLOR) { + /* + * in colour plane + */ + poff = (off - START_COLOR) + PFOUR_COLOR_OFF_COLOR; + } else + return (-1); + + return (REG2PHYS(&sc->sc_phys, poff, sc->sc_bustype) | PMAP_NC); +} + +#if defined(SUN4) +/* * Undo the effect of an FBIOSVIDEO that turns the video off. */ static void cgfourunblank(dev) struct device *dev; { - struct cgfour_softc *sc = (struct cgfour_softc *)dev; - register volatile struct bt_regs *bt; - if (sc->sc_blanked) { - sc->sc_blanked = 0; - bt = sc->sc_bt; - /* restore color 0 (and R of color 1) */ - bt->bt_addr = 0 << 24; - bt->bt_cmap = sc->sc_cmap.cm_chip[0]; - bt->bt_cmap = sc->sc_cmap.cm_chip[0] << 8; - bt->bt_cmap = sc->sc_cmap.cm_chip[0] << 16; - - /* restore read mask */ - bt->bt_addr = 0x06 << 24; /* command reg */ - bt->bt_ctrl = 0x73 << 24; /* overlay plane */ - bt->bt_addr = 0x04 << 24; /* read mask */ - bt->bt_ctrl = 0xff << 24; /* color planes */ - } + cgfour_set_video((struct cgfour_softc *)dev, 1); +} + +static int +cgfour_get_video(sc) + struct cgfour_softc *sc; +{ + + return (fb_pfour_get_video(&sc->sc_fb)); +} + +static void +cgfour_set_video(sc, enable) + struct cgfour_softc *sc; + int enable; +{ + + fb_pfour_set_video(&sc->sc_fb, enable); } /* @@ -350,7 +477,7 @@ cgfourloadcmap(sc, start, ncolors) ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; - bt = sc->sc_bt; + bt = &sc->sc_fbc->fbc_dac; bt->bt_addr = BT_D4M4(start) << 24; while (--count >= 0) { i = *ip++; @@ -361,53 +488,4 @@ cgfourloadcmap(sc, start, ncolors) bt->bt_cmap = i << 24; } } - -/* - * Return the address that would map the given device at the given - * offset, allowing for the given protection, or return -1 for error. - * - * the cg4 maps it's overlay plane for 128K, followed by the enable - * plane for 128K, followed by the colour plane (for as much colour - * as their is.) - * - * As well, mapping at an offset of 0x04000000 causes the cg4 to map - * only it's colour plane, at 0. - */ -int -cgfourmmap(dev, off, prot) - dev_t dev; - int off, prot; -{ - register struct cgfour_softc *sc = cgfourcd.cd_devs[minor(dev)]; - int poff; - -#define START_ENABLE (128*1024) -#define START_COLOUR (128*1024 + 128*1024) -#define COLOUR_SIZE (sc->sc_fb.fb_type.fb_width * sc->sc_fb.fb_type.fb_height) -#define END_COLOUR (START_COLOUR + COLOUR_SIZE) -#define NOOVERLAY (0x04000000) - - if (off & PGOFSET) - panic("cgfourmap"); - - if ((u_int)off >= NOOVERLAY) { - off = off - NOOVERLAY; - - /* - * X11 maps a huge chunk of the frame buffer; far more than - * there really is. We compensate by double-mapping the - * first page for as many other pages as it wants - */ - while (off >= COLOUR_SIZE) - off = 0; - poff = off + (CG4REG_COLOUR - CG4REG_OVERLAY); - } else if ((u_int)off < START_ENABLE) /* in overlay plane */ - poff = off; - else if ((u_int)off < START_COLOUR) /* in enable plane */ - poff = off + (CG4REG_ENABLE - CG4REG_OVERLAY) - START_ENABLE; - else if ((u_int)off < (CG4REG_END - CG4REG_OVERLAY)) /* in colour plane */ - poff = off + (CG4REG_COLOUR - CG4REG_OVERLAY) - START_COLOUR; - else - return (-1); - return (REG2PHYS(&sc->sc_phys, off, sc->sc_bustype) | PMAP_NC); -} +#endif |