Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/i386/stand Add VESA VBE/DDC EDID support for determ...



details:   https://anonhg.NetBSD.org/src/rev/fb57a5df04f7
branches:  trunk
changeset: 761841:fb57a5df04f7
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Wed Feb 09 04:37:54 2011 +0000

description:
Add VESA VBE/DDC EDID support for determining the monitor's preferred
video mode. "vesa on" will now select the preferred mode @ 8bpp if it can
be determined and is supported by the display adapter, otherwise it will
use 640x480 @ 8bpp.

diffstat:

 sys/arch/i386/stand/boot/version  |    3 +-
 sys/arch/i386/stand/lib/biosvbe.S |  100 +++++++++++++++++++++++++++++++++++++-
 sys/arch/i386/stand/lib/vbe.c     |   96 ++++++++++++++++++++++++++++++------
 sys/arch/i386/stand/lib/vbe.h     |    8 ++-
 4 files changed, 187 insertions(+), 20 deletions(-)

diffs (truncated from 345 to 300 lines):

diff -r 9d2a8304d569 -r fb57a5df04f7 sys/arch/i386/stand/boot/version
--- a/sys/arch/i386/stand/boot/version  Wed Feb 09 02:30:09 2011 +0000
+++ b/sys/arch/i386/stand/boot/version  Wed Feb 09 04:37:54 2011 +0000
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.14 2011/02/06 23:16:05 jmcneill Exp $
+$NetBSD: version,v 1.15 2011/02/09 04:37:54 jmcneill Exp $
 
 NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
 file is important - make sure the entries are appended on end, last item
@@ -46,3 +46,4 @@
 5.6:   GUID Partition Table support.
 5.7:   Recognize 64-bit LBA from bootxx.
 5.8:   Support for splash images.
+5.9:   VESA VBE/DDC EDID support.
diff -r 9d2a8304d569 -r fb57a5df04f7 sys/arch/i386/stand/lib/biosvbe.S
--- a/sys/arch/i386/stand/lib/biosvbe.S Wed Feb 09 02:30:09 2011 +0000
+++ b/sys/arch/i386/stand/lib/biosvbe.S Wed Feb 09 04:37:54 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: biosvbe.S,v 1.1 2009/02/16 22:39:30 jmcneill Exp $ */
+/* $NetBSD: biosvbe.S,v 1.2 2011/02/09 04:37:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2009 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -254,3 +254,101 @@
        popl    %ebx
        popl    %ebp
        ret
+
+/*
+ * Function 15h BL=00h - Report VBE/DDC Capabilities
+ *
+ * int biosvbe_ddc_caps(void)
+ * return: VBE/DDC capabilities
+ */
+ENTRY(biosvbe_ddc_caps)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movw    $0x4f15, %ax    /* display identification extensions */
+       mov     $0x00, %bx      /* report DDC capabilities */
+
+       movl    $0x0000, %esi   /* ES:DI == 0:0 */
+       movl    $0x0000, %edi
+       mov     $0x00, %cx      /* controller unit number (00h = primary) */
+       int     $0x10
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %eax,%ecx
+       movl    $0x0000,%eax
+       andl    $0xffff,%ecx
+       cmpl    $0x004f,%ecx
+       jne     1f
+       andl    $0xffff,%ebx
+       movl    %ebx,%eax
+1:
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 15h BL=01h - Read EDID
+ *
+ * int biosvbe_ddc_read_edid(int blockno, void *buf)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_ddc_read_edid)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %edx   /* EDID block number */
+       movl    12(%ebp), %edi  /* EDID block address */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %es
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di       /* EDID block address now in es:di */
+
+       movw    $0x4f15, %ax    /* display identification extensions */
+       mov     $0x01, %bx      /* read EDID */
+       mov     $0x00, %cx      /* controller unit number (00h = primary) */
+       int     $0x10
+
+       pop     %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
diff -r 9d2a8304d569 -r fb57a5df04f7 sys/arch/i386/stand/lib/vbe.c
--- a/sys/arch/i386/stand/lib/vbe.c     Wed Feb 09 02:30:09 2011 +0000
+++ b/sys/arch/i386/stand/lib/vbe.c     Wed Feb 09 04:37:54 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vbe.c,v 1.6 2010/06/25 15:35:08 tsutsui Exp $ */
+/* $NetBSD: vbe.c,v 1.7 2011/02/09 04:37:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2009 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -37,6 +37,8 @@
 #include "vbe.h"
 
 extern const uint8_t rasops_cmap[];
+static uint8_t *vbe_edid = NULL;
+static int vbe_edid_valid = 0;
 
 static struct _vbestate {
        int             available;
@@ -185,7 +187,7 @@
 }
 
 static int
-vbe_parse_mode_str(char *str, int *x, int *y, int *bpp)
+vbe_parse_mode_str(char *str, int *x, int *y, int *depth)
 {
        char *p;
 
@@ -202,11 +204,11 @@
                return 0;
        p = strchr(p, 'x');
        if (!p)
-               *bpp = 8;
+               *depth = 8;
        else {
                ++p;
-               *bpp = strtoul(p, NULL, 0);
-               if (*bpp == 0)
+               *depth = strtoul(p, NULL, 0);
+               if (*depth == 0)
                        return 0;
        }
 
@@ -214,18 +216,14 @@
 }
 
 static int
-vbe_find_mode(char *str)
+vbe_find_mode_xyd(int x, int y, int depth)
 {
        struct vbeinfoblock vbe;
        struct modeinfoblock mi;
        uint32_t farptr;
        uint16_t mode;
-       int x, y, bpp;
        int safety = 0;
 
-       if (!vbe_parse_mode_str(str, &x, &y, &bpp))
-               return 0;
-
        memset(&vbe, 0, sizeof(vbe));
        memcpy(vbe.VbeSignature, "VBE2", 4);
        if (biosvbe_info(&vbe) != 0x004f)
@@ -249,13 +247,24 @@
                safety = 0;
                if (mi.XResolution == x &&
                    mi.YResolution == y &&
-                   mi.BitsPerPixel == bpp)
+                   mi.BitsPerPixel == depth)
                        return mode;
        }
 
        return 0;
 }
 
+static int
+vbe_find_mode(char *str)
+{
+       int x, y, depth;
+
+       if (!vbe_parse_mode_str(str, &x, &y, &depth))
+               return 0;
+
+       return vbe_find_mode_xyd(x, y, depth);
+}
+
 static void
 vbe_dump_mode(int modenum, struct modeinfoblock *mi)
 {
@@ -263,6 +272,37 @@
            mi->XResolution, mi->YResolution, mi->BitsPerPixel);
 }
 
+static int
+vbe_get_edid(int *pwidth, int *pheight)
+{
+       const uint8_t magic[] = EDID_MAGIC;
+       int ddc_caps, ret;
+
+       ddc_caps = biosvbe_ddc_caps();
+       if (ddc_caps == 0) {
+               return 1;
+       }
+
+       if (vbe_edid == NULL) {
+               vbe_edid = alloc(128);
+       }
+       if (vbe_edid_valid == 0) {
+               ret = biosvbe_ddc_read_edid(0, vbe_edid);
+               if (ret != 0x004f)
+                       return 1;
+               if (memcmp(vbe_edid, magic, sizeof(magic)) != 0)
+                       return 1;
+               vbe_edid_valid = 1;
+       }
+
+       *pwidth = vbe_edid[EDID_DESC_BLOCK + 2] |
+           (((int)vbe_edid[EDID_DESC_BLOCK + 4] & 0xf0) << 4);
+       *pheight = vbe_edid[EDID_DESC_BLOCK + 5] |
+           (((int)vbe_edid[EDID_DESC_BLOCK + 7] & 0xf0) << 4);
+
+       return 0;
+}
+
 void
 vbe_modelist(void)
 {
@@ -271,10 +311,25 @@
        uint32_t farptr;
        uint16_t mode;
        int nmodes = 0, safety = 0;
+       int ddc_caps, edid_width, edid_height;
 
        if (!vbe_check())
                return;
 
+       ddc_caps = biosvbe_ddc_caps();
+       if (ddc_caps & 3) {
+               printf("DDC");
+               if (ddc_caps & 1)
+                       printf(" [DDC1]");
+               if (ddc_caps & 2)
+                       printf(" [DDC2]");
+
+               if (vbe_get_edid(&edid_width, &edid_height) != 0)
+                       printf(": no EDID information\n");
+               else
+                       printf(": EDID %dx%d\n", edid_width, edid_height);
+       }
+
        printf("Modes: ");
        memset(&vbe, 0, sizeof(vbe));
        memcpy(vbe.VbeSignature, "VBE2", 4);
@@ -317,7 +372,7 @@
 command_vesa(char *cmd)
 {
        char arg[20];
-       int modenum;
+       int modenum, edid_width, edid_height;
 
        if (!vbe_check())
                return;
@@ -334,18 +389,25 @@
                return;
        }
 
-       if (strcmp(arg, "enabled") == 0 || strcmp(arg, "on") == 0)
-               modenum = VBE_DEFAULT_MODE;
-       else if (strncmp(arg, "0x", 2) == 0)
+       if (strcmp(arg, "enabled") == 0 || strcmp(arg, "on") == 0) {
+               if (vbe_get_edid(&edid_width, &edid_height) != 0) {
+                       modenum = VBE_DEFAULT_MODE;
+               } else {
+                       modenum = vbe_find_mode_xyd(edid_width, edid_height, 8);
+                       if (modenum == 0)
+                               modenum = VBE_DEFAULT_MODE;



Home | Main Index | Thread Index | Old Index