[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

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