diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-05-14 06:39:50 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-05-14 06:39:50 +0000 |
commit | 0f25815910e892fe948612375db775b2ca95fbf5 (patch) | |
tree | 5b8a4b7eeab3fdae7ac7d31b1ad0e16271086aa9 /sys | |
parent | 4e6f2b8c17bcd7e33b6f672fdd97badefaf2370e (diff) |
The ramdac's hater club is proud to present new yet another SBus frame
bufer driver, this time for the Southland Media Systems (now Quantum 3D)
MGX and MGXPlus cards.
Not complete, but a good start.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/conf/GENERIC | 6 | ||||
-rw-r--r-- | sys/arch/sparc/conf/SUN4C | 6 | ||||
-rw-r--r-- | sys/arch/sparc/conf/SUN4M | 6 | ||||
-rw-r--r-- | sys/arch/sparc/conf/files.sparc | 6 | ||||
-rw-r--r-- | sys/arch/sparc/dev/mgx.c | 418 | ||||
-rw-r--r-- | sys/dev/wscons/wsconsio.h | 3 |
6 files changed, 440 insertions, 5 deletions
diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index af6c784c54c..c2fcda80f64 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.66 2003/05/14 01:13:48 miod Exp $ +# $OpenBSD: GENERIC,v 1.67 2003/05/14 06:39:49 miod Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -289,6 +289,10 @@ wsdisplay* at tvtwo? agten* at sbus? wsdisplay* at agten? +# Southland Media Systems MGX/MGXPlus framebuffer. +mgx* at sbus? +wsdisplay* at mgx? + # Microcontroller found on Tadpole tctrl0 at obio0 diff --git a/sys/arch/sparc/conf/SUN4C b/sys/arch/sparc/conf/SUN4C index 737640991a8..bfc6052ae36 100644 --- a/sys/arch/sparc/conf/SUN4C +++ b/sys/arch/sparc/conf/SUN4C @@ -1,4 +1,4 @@ -# $OpenBSD: SUN4C,v 1.43 2003/05/14 01:13:48 miod Exp $ +# $OpenBSD: SUN4C,v 1.44 2003/05/14 06:39:49 miod Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -133,6 +133,10 @@ wsdisplay* at tvtwo? agten* at sbus? wsdisplay* at agten? +# Southland Media Systems MGX/MGXPlus framebuffer. +mgx* at sbus? +wsdisplay* at mgx? + # SCSI bus layer. SCSI devices attach to the SCSI bus, which attaches # to the underlying hardware controller. scsibus* at esp? diff --git a/sys/arch/sparc/conf/SUN4M b/sys/arch/sparc/conf/SUN4M index 70f06a96d14..d61de374eb5 100644 --- a/sys/arch/sparc/conf/SUN4M +++ b/sys/arch/sparc/conf/SUN4M @@ -1,4 +1,4 @@ -# $OpenBSD: SUN4M,v 1.51 2003/05/14 01:53:02 fgsch Exp $ +# $OpenBSD: SUN4M,v 1.52 2003/05/14 06:39:49 miod Exp $ # $NetBSD: GENERIC,v 1.28.2.1 1996/07/02 23:55:22 jtc Exp $ # Machine architecture; required by config(8) @@ -172,6 +172,10 @@ wsdisplay* at tvtwo? agten* at sbus? wsdisplay* at agten? +# Southland Media Systems MGX/MGXPlus framebuffer. +mgx* at sbus? +wsdisplay* at mgx? + # Microcontroller found on Tadpole tctrl0 at obio0 diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index 19fddb6c766..86b6297a7f1 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc,v 1.52 2003/05/13 17:24:10 miod Exp $ +# $OpenBSD: files.sparc,v 1.53 2003/05/14 06:39:49 miod Exp $ # $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 @@ -215,6 +215,10 @@ device zx: wsemuldisplaydev, rasops32, wsemul_sun attach zx at sbus file arch/sparc/dev/zx.c zx +device mgx: wsemuldisplaydev, rasops8, wsemul_sun +attach mgx at sbus +file arch/sparc/dev/mgx.c mgx + # device definition in sys/conf/files attach le at sbus, ledma, lebuffer, obio file arch/sparc/dev/if_le.c le diff --git a/sys/arch/sparc/dev/mgx.c b/sys/arch/sparc/dev/mgx.c new file mode 100644 index 00000000000..a8ae5b4f2e3 --- /dev/null +++ b/sys/arch/sparc/dev/mgx.c @@ -0,0 +1,418 @@ +/* $OpenBSD: mgx.c,v 1.1 2003/05/14 06:39:49 miod Exp $ */ +/* + * Copyright (c) 2003, Miodrag Vallat. + * All rights reserved. + * + * 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. + * + * 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. + * + */ + +/* + * Driver for the Southlan Media Systems (now Quantum 3D) MGX and MGXPlus + * frame buffers. + * + * Pretty crude, due to the lack of documentation. Works as a dumb frame + * buffer in 8 bit mode, although the hardware can run in an 32 bit + * accelerated mode. Also, interrupts are not handled. + */ + +#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 <uvm/uvm_extern.h> + +#include <machine/autoconf.h> +#include <machine/pmap.h> +#include <machine/cpu.h> +#include <machine/conf.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/wscons/wscons_raster.h> +#include <dev/rasops/rasops.h> +#include <machine/fbvar.h> + +#include <sparc/dev/sbusvar.h> + +/* + * MGX PROM register layout + */ + +#define MGX_NREG 9 +#define MGX_REG_VIDC 4 /* video control and ramdac */ +#define MGX_REG_CTRL 5 /* control engine */ +#define MGX_REG_VRAM8 8 /* 8-bit memory space */ + +/* + * MGX VIDC empirical constants + */ +#define VIDC_DATA 0x03c6 +#define VIDC_COMMAND 0x03c7 +#define VIDC_CMAP 0x03ca +#define VD_DISABLEVIDEO 0x0020 + +/* per-display variables */ +struct mgx_softc { + struct sunfb sc_sunfb; /* common base device */ + struct sbusdev sc_sd; /* sbus device */ + struct rom_reg sc_phys; + u_int8_t sc_cmap[256 * 3]; /* shadow colormap */ + volatile u_int8_t *sc_vidc; /* ramdac registers */ + + int sc_nscreens; +}; + +struct wsscreen_descr mgx_stdscreen = { + "std", +}; + +const struct wsscreen_descr *mgx_scrlist[] = { + &mgx_stdscreen, +}; + +struct wsscreen_list mgx_screenlist = { + sizeof(mgx_scrlist) / sizeof(struct wsscreen_descr *), + mgx_scrlist +}; + +int mgx_ioctl(void *, u_long, caddr_t, int, struct proc *); +int mgx_alloc_screen(void *, const struct wsscreen_descr *, void **, + int *, int *, long *); +void mgx_free_screen(void *, void *); +int mgx_show_screen(void *, void *, int, void (*cb)(void *, int, int), + void *); +paddr_t mgx_mmap(void *, off_t, int); +void mgx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); +int mgx_getcmap(u_int8_t *, struct wsdisplay_cmap *); +int mgx_putcmap(u_int8_t *, struct wsdisplay_cmap *); +void mgx_loadcmap(struct mgx_softc *, int, int); +void mgx_burner(void *, u_int ,u_int); + +struct wsdisplay_accessops mgx_accessops = { + mgx_ioctl, + mgx_mmap, + mgx_alloc_screen, + mgx_free_screen, + mgx_show_screen, + NULL, /* load_font */ + NULL, /* scrollback */ + NULL, /* getchar */ + mgx_burner +}; + +int mgxmatch(struct device *, void *, void *); +void mgxattach(struct device *, struct device *, void *); + +struct cfattach mgx_ca = { + sizeof(struct mgx_softc), mgxmatch, mgxattach +}; + +struct cfdriver mgx_cd = { + NULL, "mgx", DV_DULL +}; + +/* + * Match an MGX or MGX+ card. + */ +int +mgxmatch(struct device *parent, void *vcf, void *aux) +{ + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + + if (strcmp(ra->ra_name, "SMSI,mgx") != 0 && + strcmp(ra->ra_name, "mgx") != 0) + return (0); + + return (1); +} + +/* + * Attach an MGX frame buffer. + * This will keep the frame buffer in the actual PROM mode, and attach + * a wsdisplay child device to itself. + */ +void +mgxattach(struct device *parent, struct device *self, void *args) +{ + struct mgx_softc *sc = (struct mgx_softc *)self; + struct confargs *ca = args; + struct wsemuldisplaydev_attach_args waa; + int node, fbsize; + int isconsole; + + sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags & FB_USERMASK; + node = ca->ca_ra.ra_node; + + printf(": %s", getpropstring(node, "model")); + + isconsole = node == fbnode; + + /* Check registers */ + if (ca->ca_ra.ra_nreg < MGX_NREG) { + printf("\n%s: expected %d registers, got %d\n", + self->dv_xname, MGX_NREG, ca->ca_ra.ra_nreg); + return; + } + + sc->sc_vidc = (volatile u_int8_t *)mapiodev( + &ca->ca_ra.ra_reg[MGX_REG_VIDC], 0, PAGE_SIZE); + + fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); + + /* Sanity check frame buffer memory */ + fbsize = getpropint(node, "fb_size", 0); + if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) { + printf("\n%s: expected at least %d bytes of vram, but card " + "only provides %d\n", + self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize); + return; + } + + /* Map the frame buffer memory area we're interested in */ + sc->sc_phys = ca->ca_ra.ra_reg[MGX_REG_VRAM8]; + sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&sc->sc_phys, + 0, round_page(sc->sc_sunfb.sf_fbsize)); + sc->sc_sunfb.sf_ro.ri_hw = sc; + + fbwscons_init(&sc->sc_sunfb, isconsole); + + bzero(sc->sc_cmap, sizeof(sc->sc_cmap)); + fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor); + + mgx_stdscreen.capabilities = sc->sc_sunfb.sf_ro.ri_caps; + mgx_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows; + mgx_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols; + mgx_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops; + + printf(", %dx%d\n", + sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); + + if (isconsole) { + fbwscons_console_init(&sc->sc_sunfb, + &mgx_stdscreen, -1, mgx_burner); + } + + sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev); + + waa.console = isconsole; + waa.scrdata = &mgx_screenlist; + waa.accessops = &mgx_accessops; + waa.accesscookie = sc; + config_found(self, &waa, wsemuldisplaydevprint); +} + +/* + * wsdisplay operations + */ + +int +mgx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct mgx_softc *sc = dev; + struct wsdisplay_cmap *cm; + struct wsdisplay_fbinfo *wdf; + int error; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_MGX; + break; + case WSDISPLAYIO_GINFO: + wdf = (struct wsdisplay_fbinfo *)data; + wdf->height = sc->sc_sunfb.sf_height; + wdf->width = sc->sc_sunfb.sf_width; + wdf->depth = sc->sc_sunfb.sf_depth; + wdf->cmsize = 256; + break; + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = sc->sc_sunfb.sf_linebytes; + break; + + case WSDISPLAYIO_GETCMAP: + cm = (struct wsdisplay_cmap *)data; + error = mgx_getcmap(sc->sc_cmap, cm); + if (error != 0) + return (error); + break; + case WSDISPLAYIO_PUTCMAP: + cm = (struct wsdisplay_cmap *)data; + error = mgx_putcmap(sc->sc_cmap, cm); + if (error != 0) + return (error); + mgx_loadcmap(sc, cm->index, cm->count); + break; + + default: + return (-1); + } + + return (0); +} + +paddr_t +mgx_mmap(void *v, off_t offset, int prot) +{ + struct mgx_softc *sc = v; + + if (offset & PGOFSET) + return (-1); + + /* Allow mapping as a dumb framebuffer from offset 0 */ + if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { + return (REG2PHYS(&sc->sc_phys, offset) | PMAP_NC); + } + + return (-1); +} + +int +mgx_alloc_screen(void *v, const struct wsscreen_descr *type, + void **cookiep, int *curxp, int *curyp, long *attrp) +{ + struct mgx_softc *sc = v; + + if (sc->sc_nscreens > 0) + return (ENOMEM); + + *cookiep = &sc->sc_sunfb.sf_ro; + *curyp = 0; + *curxp = 0; + sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro, + 0, 0, 0, attrp); + sc->sc_nscreens++; + return (0); +} + +void +mgx_free_screen(void *v, void *cookie) +{ + struct mgx_softc *sc = v; + + sc->sc_nscreens--; +} + +int +mgx_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + return (0); +} + +void +mgx_burner(void *v, u_int on, u_int flags) +{ + struct mgx_softc *sc = v; + + /* A few magic constants here. Don't ask. */ + sc->sc_vidc[VIDC_COMMAND] = 1; + if (on) + sc->sc_vidc[VIDC_DATA] = 0x01; + else + sc->sc_vidc[VIDC_DATA] = 0x01 | VD_DISABLEVIDEO; +} + +/* + * Colormap handling routines + */ + +void +mgx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) +{ + struct mgx_softc *sc = v; + + index *= 3; + sc->sc_cmap[index++] = r; + sc->sc_cmap[index++] = g; + sc->sc_cmap[index] = b; + + mgx_loadcmap(sc, index, 1); +} + +void +mgx_loadcmap(struct mgx_softc *sc, int start, int ncolors) +{ + u_int8_t *color; + int i; + + /* + * Apparently there is no way to load an incomplete cmap to this + * DAC. What a waste. + */ + for (color = sc->sc_cmap, i = 0; i < 256 * 3; i++) + sc->sc_vidc[VIDC_CMAP] = *color++; +} + +int +mgx_getcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count, i; + int error; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + for (i = 0; i < count; i++) { + if ((error = + copyout(cm + (index + i) * 3 + 0, &rcm->red[i], 1)) != 0) + return (error); + if ((error = + copyout(cm + (index + i) * 3 + 1, &rcm->green[i], 1)) != 0) + return (error); + if ((error = + copyout(cm + (index + i) * 3 + 2, &rcm->blue[i], 1)) != 0) + return (error); + } + + return (0); +} + +int +mgx_putcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count, i; + int error; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + for (i = 0; i < count; i++) { + if ((error = + copyin(&rcm->red[i], cm + (index + i) * 3 + 0, 1)) != 0) + return (error); + if ((error = + copyin(&rcm->green[i], cm + (index + i) * 3 + 1, 1)) != 0) + return (error); + if ((error = + copyin(&rcm->blue[i], cm + (index + i) * 3 + 2, 1)) != 0) + return (error); + } + + return (0); +} diff --git a/sys/dev/wscons/wsconsio.h b/sys/dev/wscons/wsconsio.h index cce41a8551d..c3e3221df2c 100644 --- a/sys/dev/wscons/wsconsio.h +++ b/sys/dev/wscons/wsconsio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsio.h,v 1.27 2003/03/28 02:59:31 jason Exp $ */ +/* $OpenBSD: wsconsio.h,v 1.28 2003/05/14 06:39:49 miod Exp $ */ /* $NetBSD: wsconsio.h,v 1.31.2.1 2000/07/07 09:49:17 hannken Exp $ */ /* @@ -269,6 +269,7 @@ struct wsmouse_calibcoords { #define WSDISPLAY_TYPE_AGTEN 36 /* AG10E */ #define WSDISPLAY_TYPE_XVIDEO 37 /* Xvideo */ #define WSDISPLAY_TYPE_SUNCG12 38 /* Sun cgtwelve */ +#define WSDISPLAY_TYPE_MGX 39 /* SMS MGX */ /* Basic display information. Not applicable to all display types. */ struct wsdisplay_fbinfo { |