diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-02-29 21:44:15 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-02-29 21:44:15 +0000 |
commit | 8960458919906c398d8776406f0bfd6cbedf9388 (patch) | |
tree | 0fcf547f728d6af563940655050b591be90b437e /sys/arch/sparc | |
parent | df46e8ff21dc5f3937081be70618ad6c0c6ff0f7 (diff) |
Enter rfx, driver for the SBus RasterFlex frame buffer family.
Currently 8-bit only for now.
This apparently completes the SBus frame buffer support list - yet if
you stumble upon an unsupported SBus frame buffer, I'd love to hear about it...
Diffstat (limited to 'sys/arch/sparc')
-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/rfx.c | 498 |
5 files changed, 518 insertions, 4 deletions
diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index ddf94487685..5afa4326c32 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.73 2004/02/20 00:12:15 deraadt Exp $ +# $OpenBSD: GENERIC,v 1.74 2004/02/29 21:44:12 miod Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -295,6 +295,10 @@ wsdisplay* at agten? mgx* at sbus? wsdisplay* at mgx? +# Vitec/Connectware/AP&D RasterFlex framebuffer series. +rfx* at sbus? +wsdisplay* at rfx? + # Microcontroller found on Tadpole SPARCbook tctrl0 at obio0 diff --git a/sys/arch/sparc/conf/SUN4C b/sys/arch/sparc/conf/SUN4C index 102b474f2f8..595c02f4bc7 100644 --- a/sys/arch/sparc/conf/SUN4C +++ b/sys/arch/sparc/conf/SUN4C @@ -1,4 +1,4 @@ -# $OpenBSD: SUN4C,v 1.47 2003/07/08 21:12:09 mickey Exp $ +# $OpenBSD: SUN4C,v 1.48 2004/02/29 21:44:12 miod Exp $ # $NetBSD: GENERIC,v 1.48 1997/08/23 19:19:01 mjacob Exp $ # Machine architecture; required by config(8) @@ -137,6 +137,10 @@ wsdisplay* at agten? mgx* at sbus? wsdisplay* at mgx? +# Vitec/Connectware/AP&D RasterFlex framebuffer series. +rfx* at sbus? +wsdisplay* at rfx? + # Sun PCMCIA bridge stp* at sbus? pcmcia* at stp? socket ? diff --git a/sys/arch/sparc/conf/SUN4M b/sys/arch/sparc/conf/SUN4M index 16b16d1850b..0307bebb799 100644 --- a/sys/arch/sparc/conf/SUN4M +++ b/sys/arch/sparc/conf/SUN4M @@ -1,4 +1,4 @@ -# $OpenBSD: SUN4M,v 1.59 2004/01/27 01:12:09 mickey Exp $ +# $OpenBSD: SUN4M,v 1.60 2004/02/29 21:44:12 miod Exp $ # $NetBSD: GENERIC,v 1.28.2.1 1996/07/02 23:55:22 jtc Exp $ # Machine architecture; required by config(8) @@ -184,6 +184,10 @@ wsdisplay* at agten? mgx* at sbus? wsdisplay* at mgx? +# Vitec/Connectware/AP&D RasterFlex framebuffer series. +rfx* at sbus? +wsdisplay* at rfx? + # Microcontroller found on Tadpole SPARCbook tctrl0 at obio0 diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index 2fac97b194c..8789795020e 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc,v 1.58 2003/06/28 18:12:31 jason Exp $ +# $OpenBSD: files.sparc,v 1.59 2004/02/29 21:44:12 miod Exp $ # $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 @@ -228,6 +228,10 @@ device mgx: wsemuldisplaydev, rasops8, wsemul_sun attach mgx at sbus file arch/sparc/dev/mgx.c mgx +device rfx: wsemuldisplaydev, rasops8, wsemul_sun +attach rfx at sbus +file arch/sparc/dev/rfx.c rfx + # 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/rfx.c b/sys/arch/sparc/dev/rfx.c new file mode 100644 index 00000000000..7701bf41629 --- /dev/null +++ b/sys/arch/sparc/dev/rfx.c @@ -0,0 +1,498 @@ +/* $OpenBSD: rfx.c,v 1.1 2004/02/29 21:44:14 miod Exp $ */ + +/* + * Copyright (c) 2004, 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 Vitec RasterFlex family of frame buffers. + * It should support RasterFlex-24, RasterFlex-32 and RasterFlex-HR. + */ + +#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> + +/* + * Configuration structure + */ +struct rfx_config { + u_int16_t unknown; + u_int16_t version; + u_int32_t scanline; + u_int32_t maxwidth; /* unsure */ + u_int32_t maxheight; /* unsure */ + u_int32_t width; + u_int32_t height; +}; + +/* + * In-memory offsets + */ + +#define RFX_RAMDAC_ADDR 0x00020000 +#define RFX_RAMDAC_SIZE 0x00000004 + +#define RFX_CONTROL_ADDR 0x00040000 +#define RFX_CONTROL_SIZE 0x000000e0 + +#define RFX_INIT_ADDR 0x00018000 +#define RFX_INIT_SIZE 0x00008000 + +#define RFX_VRAM_ADDR 0x00100000 + +/* + * Control registers + */ + +struct rfx_control { + u_int32_t unknown0[(0x40 - 0x00) / sizeof(u_int32_t)]; + u_int32_t cr40; +#define RFX_VIDEO_DISABLE 0x00000002 + u_int32_t unknown1[(RFX_CONTROL_SIZE - 0x44) / sizeof(u_int32_t)]; +}; + +/* + * Shadow colormap + */ +struct rfx_cmap { + u_int8_t red[256]; + u_int8_t green[256]; + u_int8_t blue[256]; +}; + +struct rfx_softc { + struct sunfb sc_sunfb; + struct sbusdev sc_sd; + struct rom_reg sc_phys; + struct intrhand sc_ih; + + struct rfx_cmap sc_cmap; + volatile u_int8_t *sc_ramdac; + volatile struct rfx_control *sc_ctrl; + + int sc_nscreens; +}; + +struct wsscreen_descr rfx_stdscreen = { + "std", +}; + +const struct wsscreen_descr *rfx_scrlist[] = { + &rfx_stdscreen, +}; + +struct wsscreen_list rfx_screenlist = { + sizeof(rfx_scrlist) / sizeof(struct wsscreen_descr *), + rfx_scrlist +}; + +int rfx_alloc_screen(void *, const struct wsscreen_descr *, void **, + int *, int *, long *); +void rfx_burner(void *, u_int, u_int); +void rfx_free_screen(void *, void *); +int rfx_ioctl(void *, u_long, caddr_t, int, struct proc *); +int rfx_show_screen(void *, void *, int, void (*cb)(void *, int, int), + void *); +paddr_t rfx_mmap(void *, off_t, int); + +int rfx_getcmap(struct rfx_cmap *, struct wsdisplay_cmap *); +int rfx_intr(void *); +void rfx_loadcmap(struct rfx_softc *, int, int); +int rfx_putcmap(struct rfx_cmap *, struct wsdisplay_cmap *); +void rfx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); + +struct wsdisplay_accessops rfx_accessops = { + rfx_ioctl, + rfx_mmap, + rfx_alloc_screen, + rfx_free_screen, + rfx_show_screen, + NULL, /* load_font */ + NULL, /* scrollback */ + NULL, /* getchar */ + rfx_burner, +}; + +int rfxmatch(struct device *, void *, void *); +void rfxattach(struct device *, struct device *, void *); + +#if defined(OpenBSD) + +struct cfattach rfx_ca = { + sizeof (struct rfx_softc), rfxmatch, rfxattach +}; + +struct cfdriver rfx_cd = { + NULL, "rfx", DV_DULL +}; + +#else + +CFATTACH_DECL(rfx, sizeof (struct rfx_softc), rfxmatch, rfxattach, NULL, NULL); + +#endif + +/* + * Match a supported RasterFlex card. + */ +int +rfxmatch(struct device *parent, void *vcf, void *aux) +{ + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + const char *device = ra->ra_name; + + /* skip vendor name (could be CWARE, VITec, ...) */ + while (*device != ',' && *device != '\0') + device++; + if (*device == '\0') + device = ra->ra_name; + else + device++; + + if (strncmp(device, "RasterFLEX", strlen("RasterFLEX")) != 0) + return (0); + + /* RasterVideo and RasterFlex-TV are frame grabbers */ + if (strcmp(device, "RasterFLEX-TV") == 0) + return (0); + + return (1); +} + +/* + * Attach and initialize a rfx display, as well as a child wsdisplay. + */ +void +rfxattach(struct device *parent, struct device *self, void *args) +{ + struct rfx_softc *sc = (struct rfx_softc *)self; + struct confargs *ca = args; + const char *device = ca->ca_ra.ra_name; + struct rfx_config cf; + struct wsemuldisplaydev_attach_args waa; + int node, cflen, isconsole = 0; + + /* skip vendor name (could be CWARE, VITec, ...) */ + while (*device != ',' && *device != '\0') + device++; + if (*device == '\0') + device = ca->ca_ra.ra_name; + else + device++; + + printf(": %s", device); + + if (ca->ca_ra.ra_nreg == 0) { + printf("\n%s: no SBus registers!\n", + self->dv_xname); + return; + } + + node = ca->ca_ra.ra_node; + isconsole = node == fbnode; + + /* + * Parse configuration structure + */ + cflen = getproplen(node, "configuration"); + if (cflen != sizeof cf) { + printf(", unknown %d bytes conf. structure", cflen); + /* fill in default values */ + cf.scanline = 2048; + cf.width = 1152; + cf.height = 900; + } else { + getprop(node, "configuration", &cf, cflen); + printf(", revision %d", cf.version); + } + + /* + * Map registers + */ + sc->sc_ramdac = (u_int8_t *) + mapiodev(ca->ca_ra.ra_reg, RFX_RAMDAC_ADDR, RFX_RAMDAC_SIZE); + sc->sc_ctrl = (struct rfx_control *) + mapiodev(ca->ca_ra.ra_reg, RFX_CONTROL_ADDR, RFX_CONTROL_SIZE); + sc->sc_phys = ca->ca_ra.ra_reg[0]; + +#if 0 /* not yet */ + sc->sc_ih.ih_fun = rfx_intr; + sc->sc_ih.ih_arg = sc; + intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB); +#endif + + /* + * The following is an equivalent for + * fb_setsize(&sc->sc_sunfb, 8, cf.width, cf.height, + * node, ca->ca_bustype); + * forcing the correct scan line value. Since the usual frame buffer + * properties are missing on this card, no need to go through + * fb_setsize()... + */ + sc->sc_sunfb.sf_depth = 8; + sc->sc_sunfb.sf_width = cf.width; + sc->sc_sunfb.sf_height = cf.height; + sc->sc_sunfb.sf_linebytes = cf.scanline; + sc->sc_sunfb.sf_fbsize = cf.height * cf.scanline; + + printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); + + sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, + RFX_VRAM_ADDR, round_page(sc->sc_sunfb.sf_fbsize)); + sc->sc_sunfb.sf_ro.ri_hw = sc; + + fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); + + bzero(&sc->sc_cmap, sizeof(sc->sc_cmap)); + fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor); + + rfx_stdscreen.capabilities = sc->sc_sunfb.sf_ro.ri_caps; + rfx_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows; + rfx_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols; + rfx_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops; + + if (isconsole) { + fbwscons_console_init(&sc->sc_sunfb, &rfx_stdscreen, -1, + rfx_burner); + } + + /* enable video */ + rfx_burner(sc, 1, 0); + + sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev); + + waa.console = isconsole; + waa.scrdata = &rfx_screenlist; + waa.accessops = &rfx_accessops; + waa.accesscookie = sc; + config_found(self, &waa, wsemuldisplaydevprint); +} + +/* + * Common wsdisplay operations + */ + +int +rfx_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct rfx_softc *sc = v; + struct wsdisplay_cmap *cm; + struct wsdisplay_fbinfo *wdf; + int error; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; + 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 = rfx_getcmap(&sc->sc_cmap, cm); + if (error != 0) + return (error); + break; + case WSDISPLAYIO_PUTCMAP: + cm = (struct wsdisplay_cmap *)data; + error = rfx_putcmap(&sc->sc_cmap, cm); + if (error != 0) + return (error); + rfx_loadcmap(sc, cm->index, cm->count); + break; + + default: + return (-1); + } + + return (0); +} + +paddr_t +rfx_mmap(void *v, off_t offset, int prot) +{ + struct rfx_softc *sc = v; + + if (offset & PGOFSET) + return (-1); + + if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { + return (REG2PHYS(&sc->sc_phys, RFX_VRAM_ADDR + offset) | + PMAP_NC); + } + + return (-1); +} + +int +rfx_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, + int *curxp, int *curyp, long *attrp) +{ + struct rfx_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, + WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp); + sc->sc_nscreens++; + return (0); +} + +void +rfx_free_screen(void *v, void *cookie) +{ + struct rfx_softc *sc = v; + + sc->sc_nscreens--; +} + +int +rfx_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + return (0); +} + +void +rfx_burner(void *v, u_int on, u_int flags) +{ + struct rfx_softc *sc = v; + + if (on) { + sc->sc_ctrl->cr40 &= ~RFX_VIDEO_DISABLE; + } else { + sc->sc_ctrl->cr40 |= RFX_VIDEO_DISABLE; + } +} + +/* + * Colormap helper functions + */ + +void +rfx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) +{ + struct rfx_softc *sc = v; + + sc->sc_cmap.red[index] = r; + sc->sc_cmap.green[index] = g; + sc->sc_cmap.blue[index] = b; + + rfx_loadcmap(sc, index, 1); +} + +int +rfx_getcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count; + int error; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + if ((error = copyout(cm->red + index, rcm->red, count)) != 0) + return (error); + if ((error = copyout(cm->green + index, rcm->green, count)) != 0) + return (error); + if ((error = copyout(cm->blue + index, rcm->blue, count)) != 0) + return (error); + + return (0); +} + +int +rfx_putcmap(struct rfx_cmap *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count; + u_int8_t red[256], green[256], blue[256]; + int error; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + if ((error = copyin(rcm->red, red, count)) != 0) + return (error); + if ((error = copyin(rcm->green, green, count)) != 0) + return (error); + if ((error = copyin(rcm->blue, blue, count)) != 0) + return (error); + + bcopy(red, cm->red + index, count); + bcopy(green, cm->green + index, count); + bcopy(blue, cm->blue + index, count); + + return (0); +} + +void +rfx_loadcmap(struct rfx_softc *sc, int start, int ncolors) +{ + + sc->sc_ramdac[0] = (start & 0xff); + sc->sc_ramdac[1] = 0; + + while (ncolors-- != 0) { + sc->sc_ramdac[3] = sc->sc_cmap.red[start]; + sc->sc_ramdac[3] = sc->sc_cmap.green[start]; + sc->sc_ramdac[3] = sc->sc_cmap.blue[start]; + start++; + } +} |