[BACK]Return to mgx.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / dev

Annotation of sys/arch/sparc/dev/mgx.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: mgx.c,v 1.12 2007/02/18 18:38:54 miod Exp $   */
        !             2: /*
        !             3:  * Copyright (c) 2003, Miodrag Vallat.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            18:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            19:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            20:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            23:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            24:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            25:  * POSSIBILITY OF SUCH DAMAGE.
        !            26:  *
        !            27:  */
        !            28:
        !            29: /*
        !            30:  * Driver for the Southland Media Systems (now Quantum 3D) MGX and MGXPlus
        !            31:  * frame buffers.
        !            32:  *
        !            33:  * Pretty crude, due to the lack of documentation. Works as a dumb frame
        !            34:  * buffer in 8 bit mode, although the hardware can run in an 32 bit
        !            35:  * accelerated mode. Also, interrupts are not handled.
        !            36:  */
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/buf.h>
        !            41: #include <sys/device.h>
        !            42: #include <sys/ioctl.h>
        !            43: #include <sys/malloc.h>
        !            44: #include <sys/mman.h>
        !            45: #include <sys/tty.h>
        !            46: #include <sys/conf.h>
        !            47:
        !            48: #include <uvm/uvm_extern.h>
        !            49:
        !            50: #include <machine/autoconf.h>
        !            51: #include <machine/pmap.h>
        !            52: #include <machine/cpu.h>
        !            53: #include <machine/conf.h>
        !            54:
        !            55: #include <dev/wscons/wsconsio.h>
        !            56: #include <dev/wscons/wsdisplayvar.h>
        !            57: #include <dev/rasops/rasops.h>
        !            58: #include <machine/fbvar.h>
        !            59:
        !            60: #include <sparc/dev/sbusvar.h>
        !            61:
        !            62: /*
        !            63:  * MGX PROM register layout
        !            64:  */
        !            65:
        !            66: #define        MGX_NREG        9
        !            67: #define        MGX_REG_CRTC    4       /* video control and ramdac */
        !            68: #define        MGX_REG_CTRL    5       /* control engine */
        !            69: #define        MGX_REG_VRAM8   8       /* 8-bit memory space */
        !            70:
        !            71: /*
        !            72:  * MGX CRTC empirical constants
        !            73:  */
        !            74: #if _BYTE_ORDER == _LITTLE_ENDIAN
        !            75: #define        IO_ADDRESS(x)   (x)
        !            76: #else
        !            77: #define        IO_ADDRESS(x)   ((x) ^ 0x03)
        !            78: #endif
        !            79: #define        CRTC_INDEX              IO_ADDRESS(0x03c4)
        !            80: #define        CRTC_DATA               IO_ADDRESS(0x03c5)
        !            81: #define        CD_DISABLEVIDEO 0x0020
        !            82: #define        CMAP_READ_INDEX         IO_ADDRESS(0x03c7)
        !            83: #define        CMAP_WRITE_INDEX        IO_ADDRESS(0x03c8)
        !            84: #define        CMAP_DATA               IO_ADDRESS(0x03c9)
        !            85:
        !            86: /* per-display variables */
        !            87: struct mgx_softc {
        !            88:        struct  sunfb   sc_sunfb;       /* common base device */
        !            89:        struct  rom_reg sc_phys;
        !            90:        u_int8_t        sc_cmap[256 * 3];       /* shadow colormap */
        !            91:        volatile u_int8_t *sc_vidc;     /* ramdac registers */
        !            92: };
        !            93:
        !            94: void   mgx_burner(void *, u_int ,u_int);
        !            95: int    mgx_getcmap(u_int8_t *, struct wsdisplay_cmap *);
        !            96: int    mgx_ioctl(void *, u_long, caddr_t, int, struct proc *);
        !            97: void   mgx_loadcmap(struct mgx_softc *, int, int);
        !            98: paddr_t        mgx_mmap(void *, off_t, int);
        !            99: int    mgx_putcmap(u_int8_t *, struct wsdisplay_cmap *);
        !           100: void   mgx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
        !           101:
        !           102: struct wsdisplay_accessops mgx_accessops = {
        !           103:        mgx_ioctl,
        !           104:        mgx_mmap,
        !           105:        NULL,   /* alloc_screen */
        !           106:        NULL,   /* free_screen */
        !           107:        NULL,   /* show_screen */
        !           108:        NULL,   /* load_font */
        !           109:        NULL,   /* scrollback */
        !           110:        NULL,   /* getchar */
        !           111:        mgx_burner,
        !           112:        NULL    /* pollc */
        !           113: };
        !           114:
        !           115: int    mgxmatch(struct device *, void *, void *);
        !           116: void   mgxattach(struct device *, struct device *, void *);
        !           117:
        !           118: struct cfattach mgx_ca = {
        !           119:        sizeof(struct mgx_softc), mgxmatch, mgxattach
        !           120: };
        !           121:
        !           122: struct cfdriver mgx_cd = {
        !           123:        NULL, "mgx", DV_DULL
        !           124: };
        !           125:
        !           126: /*
        !           127:  * Match an MGX or MGX+ card.
        !           128:  */
        !           129: int
        !           130: mgxmatch(struct device *parent, void *vcf, void *aux)
        !           131: {
        !           132:        struct confargs *ca = aux;
        !           133:        struct romaux *ra = &ca->ca_ra;
        !           134:
        !           135:        if (strcmp(ra->ra_name, "SMSI,mgx") != 0 &&
        !           136:            strcmp(ra->ra_name, "mgx") != 0)
        !           137:                return (0);
        !           138:
        !           139:        return (1);
        !           140: }
        !           141:
        !           142: /*
        !           143:  * Attach an MGX frame buffer.
        !           144:  * This will keep the frame buffer in the actual PROM mode, and attach
        !           145:  * a wsdisplay child device to itself.
        !           146:  */
        !           147: void
        !           148: mgxattach(struct device *parent, struct device *self, void *args)
        !           149: {
        !           150:        struct mgx_softc *sc = (struct mgx_softc *)self;
        !           151:        struct confargs *ca = args;
        !           152:        int node, fbsize;
        !           153:        int isconsole;
        !           154:
        !           155:        node = ca->ca_ra.ra_node;
        !           156:
        !           157:        printf(": %s", getpropstring(node, "model"));
        !           158:
        !           159:        isconsole = node == fbnode;
        !           160:
        !           161:        /* Check registers */
        !           162:        if (ca->ca_ra.ra_nreg < MGX_NREG) {
        !           163:                printf("\n%s: expected %d registers, got %d\n",
        !           164:                    self->dv_xname, MGX_NREG, ca->ca_ra.ra_nreg);
        !           165:                return;
        !           166:        }
        !           167:
        !           168:        sc->sc_vidc = (volatile u_int8_t *)mapiodev(
        !           169:            &ca->ca_ra.ra_reg[MGX_REG_CRTC], 0, PAGE_SIZE);
        !           170:
        !           171:        /* enable video */
        !           172:        mgx_burner(sc, 1, 0);
        !           173:
        !           174:        fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
        !           175:
        !           176:        /* Sanity check frame buffer memory */
        !           177:        fbsize = getpropint(node, "fb_size", 0);
        !           178:        if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
        !           179:                printf("\n%s: expected at least %d bytes of vram, but card "
        !           180:                    "only provides %d\n",
        !           181:                    self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
        !           182:                return;
        !           183:        }
        !           184:
        !           185:        /* Map the frame buffer memory area we're interested in */
        !           186:        sc->sc_phys = ca->ca_ra.ra_reg[MGX_REG_VRAM8];
        !           187:        sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&sc->sc_phys,
        !           188:            0, round_page(sc->sc_sunfb.sf_fbsize));
        !           189:        sc->sc_sunfb.sf_ro.ri_hw = sc;
        !           190:
        !           191:        fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
        !           192:
        !           193:        bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
        !           194:        fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);
        !           195:
        !           196:        printf(", %dx%d\n",
        !           197:            sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
        !           198:
        !           199:        if (isconsole) {
        !           200:                fbwscons_console_init(&sc->sc_sunfb, -1);
        !           201:        }
        !           202:
        !           203:        fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
        !           204: }
        !           205:
        !           206: /*
        !           207:  * wsdisplay operations
        !           208:  */
        !           209:
        !           210: int
        !           211: mgx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
        !           212: {
        !           213:        struct mgx_softc *sc = dev;
        !           214:        struct wsdisplay_cmap *cm;
        !           215:        struct wsdisplay_fbinfo *wdf;
        !           216:        int error;
        !           217:
        !           218:        switch (cmd) {
        !           219:        case WSDISPLAYIO_GTYPE:
        !           220:                *(u_int *)data = WSDISPLAY_TYPE_MGX;
        !           221:                break;
        !           222:        case WSDISPLAYIO_GINFO:
        !           223:                wdf = (struct wsdisplay_fbinfo *)data;
        !           224:                wdf->height = sc->sc_sunfb.sf_height;
        !           225:                wdf->width = sc->sc_sunfb.sf_width;
        !           226:                wdf->depth = sc->sc_sunfb.sf_depth;
        !           227:                wdf->cmsize = 256;
        !           228:                break;
        !           229:        case WSDISPLAYIO_LINEBYTES:
        !           230:                *(u_int *)data = sc->sc_sunfb.sf_linebytes;
        !           231:                break;
        !           232:
        !           233:        case WSDISPLAYIO_GETCMAP:
        !           234:                cm = (struct wsdisplay_cmap *)data;
        !           235:                error = mgx_getcmap(sc->sc_cmap, cm);
        !           236:                if (error != 0)
        !           237:                        return (error);
        !           238:                break;
        !           239:        case WSDISPLAYIO_PUTCMAP:
        !           240:                cm = (struct wsdisplay_cmap *)data;
        !           241:                error = mgx_putcmap(sc->sc_cmap, cm);
        !           242:                if (error != 0)
        !           243:                        return (error);
        !           244:                mgx_loadcmap(sc, cm->index, cm->count);
        !           245:                break;
        !           246:
        !           247:        case WSDISPLAYIO_SVIDEO:
        !           248:        case WSDISPLAYIO_GVIDEO:
        !           249:                break;
        !           250:
        !           251:        default:
        !           252:                return (-1);
        !           253:        }
        !           254:
        !           255:        return (0);
        !           256: }
        !           257:
        !           258: paddr_t
        !           259: mgx_mmap(void *v, off_t offset, int prot)
        !           260: {
        !           261:        struct mgx_softc *sc = v;
        !           262:
        !           263:        if (offset & PGOFSET)
        !           264:                return (-1);
        !           265:
        !           266:        /* Allow mapping as a dumb framebuffer from offset 0 */
        !           267:        if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
        !           268:                return (REG2PHYS(&sc->sc_phys, offset) | PMAP_NC);
        !           269:        }
        !           270:
        !           271:        return (-1);
        !           272: }
        !           273:
        !           274: void
        !           275: mgx_burner(void *v, u_int on, u_int flags)
        !           276: {
        !           277:        struct mgx_softc *sc = v;
        !           278:
        !           279:        sc->sc_vidc[CRTC_INDEX] = 1;    /* TS mode register */
        !           280:        if (on)
        !           281:                sc->sc_vidc[CRTC_DATA] &= ~CD_DISABLEVIDEO;
        !           282:        else
        !           283:                sc->sc_vidc[CRTC_DATA] |= CD_DISABLEVIDEO;
        !           284: }
        !           285:
        !           286: /*
        !           287:  * Colormap handling routines
        !           288:  */
        !           289:
        !           290: void
        !           291: mgx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
        !           292: {
        !           293:        struct mgx_softc *sc = v;
        !           294:
        !           295:        index *= 3;
        !           296:        sc->sc_cmap[index++] = r;
        !           297:        sc->sc_cmap[index++] = g;
        !           298:        sc->sc_cmap[index] = b;
        !           299:
        !           300:        mgx_loadcmap(sc, index, 1);
        !           301: }
        !           302:
        !           303: void
        !           304: mgx_loadcmap(struct mgx_softc *sc, int start, int ncolors)
        !           305: {
        !           306:        u_int8_t *color;
        !           307:        int i;
        !           308:
        !           309: #if 0
        !           310:        sc->sc_vidc[CMAP_WRITE_INDEX] = start;
        !           311:        color = sc->sc_cmap + start * 3;
        !           312: #else
        !           313:        /*
        !           314:         * Apparently there is no way to load an incomplete cmap to this
        !           315:         * DAC. What a waste.
        !           316:         */
        !           317:        ncolors = 256;
        !           318:        color = sc->sc_cmap;
        !           319: #endif
        !           320:        for (i = ncolors * 3; i != 0; i--)
        !           321:                sc->sc_vidc[CMAP_DATA] = *color++;
        !           322: }
        !           323:
        !           324: int
        !           325: mgx_getcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
        !           326: {
        !           327:        u_int index = rcm->index, count = rcm->count, i;
        !           328:        int error;
        !           329:
        !           330:        if (index >= 256 || count > 256 - index)
        !           331:                return (EINVAL);
        !           332:
        !           333:        for (i = 0; i < count; i++) {
        !           334:                if ((error =
        !           335:                    copyout(cm + (index + i) * 3 + 0, &rcm->red[i], 1)) != 0)
        !           336:                        return (error);
        !           337:                if ((error =
        !           338:                    copyout(cm + (index + i) * 3 + 1, &rcm->green[i], 1)) != 0)
        !           339:                        return (error);
        !           340:                if ((error =
        !           341:                    copyout(cm + (index + i) * 3 + 2, &rcm->blue[i], 1)) != 0)
        !           342:                        return (error);
        !           343:        }
        !           344:
        !           345:        return (0);
        !           346: }
        !           347:
        !           348: int
        !           349: mgx_putcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
        !           350: {
        !           351:        u_int index = rcm->index, count = rcm->count, i;
        !           352:        int error;
        !           353:
        !           354:        if (index >= 256 || count > 256 - index)
        !           355:                return (EINVAL);
        !           356:
        !           357:        for (i = 0; i < count; i++) {
        !           358:                if ((error =
        !           359:                    copyin(&rcm->red[i], cm + (index + i) * 3 + 0, 1)) != 0)
        !           360:                        return (error);
        !           361:                if ((error =
        !           362:                    copyin(&rcm->green[i], cm + (index + i) * 3 + 1, 1)) != 0)
        !           363:                        return (error);
        !           364:                if ((error =
        !           365:                    copyin(&rcm->blue[i], cm + (index + i) * 3 + 2, 1)) != 0)
        !           366:                        return (error);
        !           367:        }
        !           368:
        !           369:        return (0);
        !           370: }

CVSweb