[BACK]Return to vesafb.c CVS log [TXT][DIR] Up to [local] / sys / dev / vesa

Annotation of sys/dev/vesa/vesafb.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: vesafb.c,v 1.4 2007/02/18 19:19:02 gwk Exp $ */
                      2:
                      3: /*-
                      4:  * Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *        This product includes software developed by the NetBSD
                     18:  *        Foundation, Inc. and its contributors.
                     19:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     20:  *    contributors may be used to endorse or promote products derived
                     21:  *    from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     24:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     25:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     26:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     27:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     28:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     29:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     30:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     31:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     32:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: /*
                     36:  * Copyright (c) 2006 Matthieu Herrb
                     37:  *
                     38:  * Permission to use, copy, modify, and distribute this software for any
                     39:  * purpose with or without fee is hereby granted, provided that the above
                     40:  * copyright notice and this permission notice appear in all copies.
                     41:  *
                     42:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     43:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     44:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     45:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     46:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     47:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     48:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     49:  */
                     50:
                     51: #include <sys/param.h>
                     52: #include <sys/systm.h>
                     53: #include <sys/kernel.h>
                     54: #include <sys/device.h>
                     55:
                     56: #include <machine/bus.h>
                     57:
                     58: #include <dev/pci/pcireg.h>
                     59: #include <dev/pci/pcivar.h>
                     60: #include <dev/pci/pcidevs.h>
                     61:
                     62: #include <dev/ic/mc6845reg.h>
                     63: #include <dev/ic/pcdisplayvar.h>
                     64: #include <dev/ic/vgareg.h>
                     65: #include <dev/ic/vgavar.h>
                     66: #include <dev/pci/vga_pcivar.h>
                     67:
                     68: #include <dev/vesa/vesabiosreg.h>
                     69: #include <dev/vesa/vesabiosvar.h>
                     70: #include <dev/vesa/vbe.h>
                     71:
                     72: #include <machine/frame.h>
                     73: #include <machine/kvm86.h>
                     74:
                     75: #include <dev/wscons/wsconsio.h>
                     76: #include <dev/wscons/wsdisplayvar.h>
                     77:
                     78: #include <uvm/uvm_extern.h>
                     79:
                     80:
                     81: void vesafb_set_mode(struct vga_pci_softc *, int);
                     82: int vesafb_get_mode(struct vga_pci_softc *);
                     83: void vesafb_get_mode_info(struct vga_pci_softc *, int, struct modeinfoblock *);
                     84: void vesafb_set_palette(struct vga_pci_softc *, int, struct paletteentry);
                     85: int vesafb_putcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
                     86: int vesafb_getcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
                     87: int vesafb_get_ddc_version(struct vga_pci_softc *);
                     88: int vesafb_get_ddc_info(struct vga_pci_softc *, struct edid *);
                     89:
                     90: int
                     91: vesafb_get_ddc_version(struct vga_pci_softc *sc)
                     92: {
                     93:        struct trapframe tf;
                     94:        int res;
                     95:
                     96:        bzero(&tf, sizeof(struct trapframe));
                     97:        tf.tf_eax = VBE_FUNC_DDC;
                     98:
                     99:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    100:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED)
                    101:                return 0;
                    102:
                    103:        return VBECALL_SUCESS(tf.tf_eax);
                    104: }
                    105:
                    106:
                    107: int
                    108: vesafb_get_ddc_info(struct vga_pci_softc *sc, struct edid *info)
                    109: {
                    110:        struct trapframe tf;
                    111:        unsigned char *buf;
                    112:        int res;
                    113:
                    114:        if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) {
                    115:                printf("%s: kvm86_bios_addpage failed.\n",
                    116:                    sc->sc_dev.dv_xname);
                    117:                return 1;
                    118:        }
                    119:
                    120:        bzero(&tf, sizeof(struct trapframe));
                    121:        tf.tf_eax = VBE_FUNC_DDC;
                    122:        tf.tf_ebx = VBE_DDC_GET;
                    123:        tf.tf_vm86_es = 0;
                    124:        tf.tf_edi = KVM86_CALL_TASKVA;
                    125:
                    126:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    127:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
                    128:                kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
                    129:                return 1;
                    130:        }
                    131:
                    132:        memcpy(info, buf, sizeof(struct edid));
                    133:        kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
                    134:        return VBECALL_SUCESS(tf.tf_eax);
                    135: }
                    136:
                    137: int
                    138: vesafb_get_mode(struct vga_pci_softc *sc)
                    139: {
                    140:        struct trapframe tf;
                    141:        int res;
                    142:
                    143:        bzero(&tf, sizeof(struct trapframe));
                    144:        tf.tf_eax = VBE_FUNC_GETMODE;
                    145:
                    146:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    147:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
                    148:                printf("%s: vbecall: res=%d, ax=%x\n",
                    149:                    sc->sc_dev.dv_xname, res, tf.tf_eax);
                    150:        }
                    151:        return tf.tf_ebx & 0xffff;
                    152: }
                    153:
                    154: void
                    155: vesafb_get_mode_info(struct vga_pci_softc *sc, int mode,
                    156:     struct modeinfoblock *mi)
                    157: {
                    158:        struct trapframe tf;
                    159:        unsigned char *buf;
                    160:        int res;
                    161:
                    162:        if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) {
                    163:                printf("%s: kvm86_bios_addpage failed.\n",
                    164:                    sc->sc_dev.dv_xname);
                    165:                return;
                    166:        }
                    167:        memset(&tf, 0, sizeof(struct trapframe));
                    168:        tf.tf_eax = VBE_FUNC_MODEINFO;
                    169:        tf.tf_ecx = mode;
                    170:        tf.tf_vm86_es = 0;
                    171:        tf.tf_edi = KVM86_CALL_TASKVA;
                    172:
                    173:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    174:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
                    175:                printf("%s: vbecall: res=%d, ax=%x\n",
                    176:                    sc->sc_dev.dv_xname, res, tf.tf_eax);
                    177:                printf("%s: error getting info for mode %05x\n",
                    178:                    sc->sc_dev.dv_xname, mode);
                    179:                kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
                    180:                return;
                    181:        }
                    182:        memcpy(mi, buf, sizeof(struct modeinfoblock));
                    183:        kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
                    184: }
                    185:
                    186: void
                    187: vesafb_set_palette(struct vga_pci_softc *sc, int reg, struct paletteentry pe)
                    188: {
                    189:        struct trapframe tf;
                    190:        int res;
                    191:        char *buf;
                    192:
                    193:        if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) {
                    194:                printf("%s: kvm86_bios_addpage failed.\n",
                    195:                       sc->sc_dev.dv_xname);
                    196:                return;
                    197:        }
                    198:        /*
                    199:         * this function takes 8 bit per palette as input, but we're
                    200:         * working in 6 bit mode here
                    201:         */
                    202:        pe.Red >>= 2;
                    203:        pe.Green >>= 2;
                    204:        pe.Blue >>= 2;
                    205:
                    206:        memcpy(buf, &pe, sizeof(struct paletteentry));
                    207:
                    208:        /* set palette */
                    209:        memset(&tf, 0, sizeof(struct trapframe));
                    210:        tf.tf_eax = VBE_FUNC_PALETTE;
                    211:        tf.tf_ebx = 0x0600; /* 6 bit per primary, set format */
                    212:        tf.tf_ecx = 1;
                    213:        tf.tf_edx = reg;
                    214:        tf.tf_vm86_es = 0;
                    215:        tf.tf_edi = KVM86_CALL_TASKVA;
                    216:
                    217:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    218:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED)
                    219:                printf("%s: vbecall: res=%d, ax=%x\n",
                    220:                    sc->sc_dev.dv_xname, res, tf.tf_eax);
                    221:
                    222:        kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
                    223:        return;
                    224: }
                    225:
                    226: void
                    227: vesafb_set_mode(struct vga_pci_softc *sc, int mode)
                    228: {
                    229:        struct trapframe tf;
                    230:        int res;
                    231:
                    232:        bzero(&tf, sizeof(struct trapframe));
                    233:        tf.tf_eax = VBE_FUNC_SETMODE;
                    234:        tf.tf_ebx = mode | 0x4000; /* flat */
                    235:
                    236:        res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
                    237:        if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
                    238:                printf("%s: vbecall: res=%d, ax=%x\n",
                    239:                    sc->sc_dev.dv_xname, res, tf.tf_eax);
                    240:                return;
                    241:        }
                    242: }
                    243:
                    244: int
                    245: vesafb_find_mode(struct vga_pci_softc *sc, int width, int height, int bpp)
                    246: {
                    247:        struct modeinfoblock mi;
                    248:        int i;
                    249:
                    250:        if (vesabios_softc == NULL || vesabios_softc->sc_nmodes == 0)
                    251:                return -1;
                    252: #ifdef VESABIOSVERBOSE
                    253:        printf("vesafb_find_mode %d %d %d\n", width, height, bpp);
                    254: #endif
                    255:        /* Choose a graphics mode */
                    256:        for (i = 0; i < vesabios_softc->sc_nmodes; i++) {
                    257:                vesafb_get_mode_info(sc, vesabios_softc->sc_modes[i], &mi);
                    258:                if (mi.XResolution == width &&
                    259:                    mi.YResolution == height &&
                    260:                    mi.BitsPerPixel == bpp) {
                    261:                        sc->sc_width = mi.XResolution;
                    262:                        sc->sc_height = mi.YResolution;
                    263:                        sc->sc_depth = mi.BitsPerPixel;
                    264:                        sc->sc_linebytes = mi.BytesPerScanLine;
                    265:                        sc->sc_base = mi.PhysBasePtr;
                    266:                        break;
                    267:                }
                    268:        }
                    269:        if (i == vesabios_softc->sc_nmodes)
                    270:                return -1;
                    271:        else
                    272:                return vesabios_softc->sc_modes[i];
                    273: }
                    274:
                    275: int
                    276: vesafb_putcmap(struct vga_pci_softc *sc, struct wsdisplay_cmap *cm)
                    277: {
                    278:        struct paletteentry pe;
                    279:        u_int idx, cnt;
                    280:        u_char r[256], g[256], b[256];
                    281:        u_char *rp, *gp, *bp;
                    282:        int rv, i;
                    283:
                    284:        idx = cm->index;
                    285:        cnt = cm->count;
                    286:
                    287:        if (idx >= 256 || cnt > 256 - idx)
                    288:                return EINVAL;
                    289:
                    290:        rv = copyin(cm->red, &r[idx], cnt);
                    291:        if (rv)
                    292:                return rv;
                    293:        rv = copyin(cm->green, &g[idx], cnt);
                    294:        if (rv)
                    295:                return rv;
                    296:        rv = copyin(cm->blue, &b[idx], cnt);
                    297:        if (rv)
                    298:                return rv;
                    299:
                    300:        memcpy(&sc->sc_cmap_red[idx], &r[idx], cnt);
                    301:        memcpy(&sc->sc_cmap_green[idx], &g[idx], cnt);
                    302:        memcpy(&sc->sc_cmap_blue[idx], &b[idx], cnt);
                    303:
                    304:        rp = &sc->sc_cmap_red[idx];
                    305:        gp = &sc->sc_cmap_green[idx];
                    306:        bp = &sc->sc_cmap_blue[idx];
                    307:
                    308:        for (i = 0; i < cnt; i++) {
                    309:                pe.Blue = *bp;
                    310:                pe.Green = *gp;
                    311:                pe.Red = *rp;
                    312:                pe.Alignment = 0;
                    313:                vesafb_set_palette(sc, idx, pe);
                    314:                idx++;
                    315:                rp++, gp++, bp++;
                    316:        }
                    317:
                    318:        return 0;
                    319: }
                    320:
                    321: int
                    322: vesafb_getcmap(struct vga_pci_softc *sc, struct wsdisplay_cmap *cm)
                    323: {
                    324:        u_int idx, cnt;
                    325:        int rv;
                    326:
                    327:        idx = cm->index;
                    328:        cnt = cm->count;
                    329:
                    330:        if (idx >= 256 || cnt > 256 - idx)
                    331:                return EINVAL;
                    332:
                    333:        rv = copyout(&sc->sc_cmap_red[idx], cm->red, cnt);
                    334:        if (rv)
                    335:                return rv;
                    336:        rv = copyout(&sc->sc_cmap_green[idx], cm->green, cnt);
                    337:        if (rv)
                    338:                return rv;
                    339:        rv = copyout(&sc->sc_cmap_blue[idx], cm->blue, cnt);
                    340:        if (rv)
                    341:                return rv;
                    342:
                    343:        return 0;
                    344: }
                    345:
                    346: static int
                    347: vesafb_getdepthflag(struct modeinfoblock *mi)
                    348: {
                    349:        int bpp, depth;
                    350:
                    351:        depth = mi->RedMaskSize + mi->GreenMaskSize + mi->BlueMaskSize;
                    352:        bpp = mi->BitsPerPixel;
                    353:        switch (depth) {
                    354:        case 1:
                    355:                return WSDISPLAYIO_DEPTH_1;
                    356:        case 4:
                    357:                return WSDISPLAYIO_DEPTH_4;
                    358:        case 8:
                    359:                return WSDISPLAYIO_DEPTH_8;
                    360:        case 15:
                    361:                return WSDISPLAYIO_DEPTH_15;
                    362:        case 16:
                    363:                return WSDISPLAYIO_DEPTH_16;
                    364:        case 24:
                    365:                switch (bpp) {
                    366:                case 24:
                    367:                        return WSDISPLAYIO_DEPTH_24_24;
                    368:                case 32:
                    369:                        return WSDISPLAYIO_DEPTH_24_32;
                    370:                }
                    371:        }
                    372:        return 0;
                    373: }
                    374:
                    375:
                    376: int
                    377: vesafb_get_supported_depth(struct vga_pci_softc *sc)
                    378: {
                    379:        int i, depths;
                    380:        struct modeinfoblock mi;
                    381:
                    382:        depths = 0;
                    383:
                    384:        if (vesabios_softc == NULL || vesabios_softc->sc_nmodes == 0)
                    385:                return 0;
                    386:
                    387:        for (i = 0; i < vesabios_softc->sc_nmodes; i++) {
                    388:                vesafb_get_mode_info(sc, vesabios_softc->sc_modes[i], &mi);
                    389:                depths |= vesafb_getdepthflag(&mi);
                    390:        }
                    391:        return depths;
                    392: }

CVSweb