[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     ! 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