root/dev/vesa/vesabios.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vesabios_match
  2. vbegetinfo
  3. vbefreeinfo
  4. vbeprobe
  5. mm2txt
  6. vesabios_attach
  7. vesabios_print

    1 /* $OpenBSD: vesabios.c,v 1.4 2007/02/18 19:19:02 gwk Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002, 2004
    5  *      Matthias Drochner.  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  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/device.h>
   34 #include <sys/malloc.h>
   35 #include <machine/frame.h>
   36 #include <machine/kvm86.h>
   37 
   38 #include <dev/vesa/vesabiosvar.h>
   39 #include <dev/vesa/vesabiosreg.h>
   40 #include <dev/vesa/vbe.h>
   41 
   42 struct vbeinfoblock
   43 {
   44         char VbeSignature[4];
   45         uint16_t VbeVersion;
   46         uint32_t OemStringPtr;
   47         uint32_t Capabilities;
   48         uint32_t VideoModePtr;
   49         uint16_t TotalMemory;
   50         uint16_t OemSoftwareRev;
   51         uint32_t OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
   52         /* data area, in total max 512 bytes for VBE 2.0 */
   53 } __packed;
   54 
   55 #define FAR2FLATPTR(p) ((p & 0xffff) + ((p >> 12) & 0xffff0))
   56 
   57 int vesabios_match(struct device *, void *, void *);
   58 void vesabios_attach(struct device *, struct device *, void *);
   59 int vesabios_print(void *, const char *);
   60 
   61 int vbegetinfo(struct vbeinfoblock **);
   62 void vbefreeinfo(struct vbeinfoblock *);
   63 #ifdef VESABIOSVERBOSE
   64 const char *mm2txt(unsigned int);
   65 #endif
   66 
   67 struct vesabios_softc *vesabios_softc;
   68 
   69 struct cfattach vesabios_ca = {
   70         sizeof(struct vesabios_softc), vesabios_match, vesabios_attach
   71 };
   72 
   73 struct cfdriver vesabios_cd = {
   74         NULL, "vesabios", DV_DULL
   75 };
   76 
   77 int
   78 vesabios_match(struct device *parent, void *match, void *aux)
   79 {
   80 
   81         return (1);
   82 }
   83 
   84 int
   85 vbegetinfo(struct vbeinfoblock **vip)
   86 {
   87         unsigned char *buf;
   88         struct trapframe tf;
   89         int res, error;
   90 
   91         if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) {
   92                 printf("vbegetinfo: kvm86_bios_addpage failed\n");
   93                 return (ENOMEM);
   94         }
   95 
   96         memcpy(buf, "VBE2", 4);
   97 
   98         memset(&tf, 0, sizeof(struct trapframe));
   99         tf.tf_eax = VBE_FUNC_CTRLINFO;
  100         tf.tf_vm86_es = 0;
  101         tf.tf_edi = KVM86_CALL_TASKVA;
  102 
  103         res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
  104         if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
  105                 printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax);
  106                 error = ENXIO;
  107                 goto out;
  108         }
  109 
  110         if (memcmp(((struct vbeinfoblock *)buf)->VbeSignature, "VESA", 4)) {
  111                 error = EIO;
  112                 goto out;
  113         }
  114 
  115         if (vip)
  116                 *vip = (struct vbeinfoblock *)buf;
  117         return (0);
  118 
  119 out:
  120         kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
  121         return (error);
  122 }
  123 
  124 void
  125 vbefreeinfo(struct vbeinfoblock *vip)
  126 {
  127 
  128         kvm86_bios_delpage(KVM86_CALL_TASKVA, vip);
  129 }
  130 
  131 int
  132 vbeprobe(void)
  133 {
  134         struct vbeinfoblock *vi;
  135         int found = 0;
  136 
  137         if (vbegetinfo(&vi))
  138                 return (0);
  139         if (VBE_CTRLINFO_VERSION(vi->VbeVersion) > 1) {
  140                 /* VESA bios is at least version 2.0 */
  141                 found = 1;
  142         }
  143         vbefreeinfo(vi);
  144         return (found);
  145 }
  146 
  147 #ifdef VESABIOSVERBOSE
  148 const char *
  149 mm2txt(unsigned int mm)
  150 {
  151         static char buf[30];
  152         static const char *names[] = {
  153                 "Text mode",
  154                 "CGA graphics",
  155                 "Hercules graphics",
  156                 "Planar",
  157                 "Packed pixel",
  158                 "Non-chain 4, 256 color",
  159                 "Direct Color",
  160                 "YUV"
  161         };
  162 
  163         if (mm < sizeof(names)/sizeof(names[0]))
  164                 return (names[mm]);
  165         snprintf(buf, sizeof(buf), "unknown memory model %d", mm);
  166         return (buf);
  167 }
  168 #endif
  169 
  170 void
  171 vesabios_attach(struct device *parent, struct device *self, void *aux)
  172 {
  173         struct vesabios_softc *sc = (struct vesabios_softc *)self;
  174         struct vbeinfoblock *vi;
  175         unsigned char *buf;
  176         struct trapframe tf;
  177         int res;
  178         char name[256];
  179 #define MAXMODES 60
  180         uint16_t modes[MAXMODES];
  181         int rastermodes[MAXMODES];
  182         int textmodes[MAXMODES];
  183         int nmodes, nrastermodes, ntextmodes, i;
  184         uint32_t modeptr;
  185         struct modeinfoblock *mi;
  186 
  187         if (vbegetinfo(&vi)) {
  188                 printf("\n");
  189                 panic("vesabios_attach: disappeared");
  190         }
  191 
  192         printf(": version %d.%d",
  193             VBE_CTRLINFO_VERSION(vi->VbeVersion),
  194             VBE_CTRLINFO_REVISION(vi->VbeVersion));
  195 
  196 
  197         res = kvm86_bios_read(FAR2FLATPTR(vi->OemVendorNamePtr),
  198             name, sizeof(name));
  199 
  200         sc->sc_size = vi->TotalMemory * 65536;
  201         if (res > 0) {
  202                 name[res - 1] = 0;
  203                 printf(", %s", name);
  204                 res = kvm86_bios_read(FAR2FLATPTR(vi->OemProductNamePtr),
  205                                       name, sizeof(name));
  206                 if (res > 0) {
  207                         name[res - 1] = 0;
  208                         printf(" %s", name);
  209                 }
  210         }
  211         printf("\n");
  212 
  213         nmodes = 0;
  214         modeptr = FAR2FLATPTR(vi->VideoModePtr);
  215         while (nmodes < MAXMODES) {
  216                 res = kvm86_bios_read(modeptr, (char *)&modes[nmodes], 2);
  217                 if (res != 2 || modes[nmodes] == 0xffff)
  218                         break;
  219                 nmodes++;
  220                 modeptr += 2;
  221         }
  222 
  223         vbefreeinfo(vi);
  224         if (nmodes == 0)
  225                 return;
  226 
  227         nrastermodes = ntextmodes = 0;
  228 
  229         buf = kvm86_bios_addpage(KVM86_CALL_TASKVA);
  230         if (!buf) {
  231                 printf("%s: kvm86_bios_addpage failed\n",
  232                     self->dv_xname);
  233                 return;
  234         }
  235         for (i = 0; i < nmodes; i++) {
  236 
  237                 memset(&tf, 0, sizeof(struct trapframe));
  238                 tf.tf_eax = VBE_FUNC_MODEINFO;
  239                 tf.tf_ecx = modes[i];
  240                 tf.tf_vm86_es = 0;
  241                 tf.tf_edi = KVM86_CALL_TASKVA;
  242 
  243                 res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf);
  244                 if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) {
  245                         printf("%s: vbecall: res=%d, ax=%x\n",
  246                             self->dv_xname, res, tf.tf_eax);
  247                         printf("%s: error getting info for mode %04x\n",
  248                             self->dv_xname, modes[i]);
  249                         continue;
  250                 }
  251                 mi = (struct modeinfoblock *)buf;
  252 #ifdef VESABIOSVERBOSE
  253                 printf("%s: VESA mode %04x: attributes %04x",
  254                        self->dv_xname, modes[i], mi->ModeAttributes);
  255 #endif
  256                 if (!(mi->ModeAttributes & 1)) {
  257 #ifdef VESABIOSVERBOSE
  258                         printf("\n");
  259 #endif
  260                         continue;
  261                 }
  262                 if (mi->ModeAttributes & 0x10) {
  263                         /* graphics */
  264 #ifdef VESABIOSVERBOSE
  265                         printf(", %dx%d %dbbp %s\n",
  266                                mi->XResolution, mi->YResolution,
  267                                mi->BitsPerPixel, mm2txt(mi->MemoryModel));
  268 #endif
  269                         if (mi->ModeAttributes & 0x80) {
  270                                 /* flat buffer */
  271                                 rastermodes[nrastermodes++] = modes[i];
  272                         }
  273                 } else {
  274                         /* text */
  275 #ifdef VESABIOSVERBOSE
  276                         printf(", text %dx%d\n",
  277                                mi->XResolution, mi->YResolution);
  278 #endif
  279                         if (!(mi->ModeAttributes & 0x20)) /* VGA compatible */
  280                                 textmodes[ntextmodes++] = modes[i];
  281                 }
  282         }
  283         kvm86_bios_delpage(KVM86_CALL_TASKVA, buf);
  284         if (nrastermodes > 0) {
  285                 sc->sc_modes =
  286                     (uint16_t *)malloc(sizeof(uint16_t)*nrastermodes,
  287                         M_DEVBUF, M_NOWAIT);
  288                 if (sc->sc_modes == NULL) {
  289                         sc->sc_nmodes = 0;
  290                         return;
  291                 }
  292                 sc->sc_nmodes = nrastermodes;
  293                 for (i = 0; i < nrastermodes; i++)
  294                         sc->sc_modes[i] = rastermodes[i];
  295         }
  296         vesabios_softc = sc;
  297 }
  298 
  299 int
  300 vesabios_print(aux, pnp)
  301         void *aux;
  302         const char *pnp;
  303 {
  304         char *busname = aux;
  305 
  306         if (pnp)
  307                 printf("%s at %s", busname, pnp);
  308         return (UNCONF);
  309 }

/* [<][>][^][v][top][bottom][index][help] */