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