Module Name: src
Committed By: jmcneill
Date: Wed Feb 9 04:37:54 UTC 2011
Modified Files:
src/sys/arch/i386/stand/boot: version
src/sys/arch/i386/stand/lib: biosvbe.S vbe.c vbe.h
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/i386/stand/boot/version
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/i386/stand/lib/biosvbe.S
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/i386/stand/lib/vbe.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/i386/stand/lib/vbe.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/i386/stand/boot/version
diff -u src/sys/arch/i386/stand/boot/version:1.14 src/sys/arch/i386/stand/boot/version:1.15
--- src/sys/arch/i386/stand/boot/version:1.14 Sun Feb 6 23:16:05 2011
+++ src/sys/arch/i386/stand/boot/version Wed Feb 9 04:37:54 2011
@@ -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.
Index: src/sys/arch/i386/stand/lib/biosvbe.S
diff -u src/sys/arch/i386/stand/lib/biosvbe.S:1.1 src/sys/arch/i386/stand/lib/biosvbe.S:1.2
--- src/sys/arch/i386/stand/lib/biosvbe.S:1.1 Mon Feb 16 22:39:30 2009
+++ src/sys/arch/i386/stand/lib/biosvbe.S Wed Feb 9 04:37:54 2011
@@ -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 <[email protected]>
@@ -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
+
Index: src/sys/arch/i386/stand/lib/vbe.c
diff -u src/sys/arch/i386/stand/lib/vbe.c:1.6 src/sys/arch/i386/stand/lib/vbe.c:1.7
--- src/sys/arch/i386/stand/lib/vbe.c:1.6 Fri Jun 25 15:35:08 2010
+++ src/sys/arch/i386/stand/lib/vbe.c Wed Feb 9 04:37:54 2011
@@ -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 <[email protected]>
@@ -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;
+ }
+ } else if (strncmp(arg, "0x", 2) == 0) {
modenum = strtoul(arg, NULL, 0);
- else if (strchr(arg, 'x') != NULL) {
+ } else if (strchr(arg, 'x') != NULL) {
modenum = vbe_find_mode(arg);
if (modenum == 0) {
printf("mode %s not supported by firmware\n", arg);
return;
}
- } else
+ } else {
modenum = 0;
+ }
if (modenum >= 0x100) {
vbestate.modenum = modenum;
Index: src/sys/arch/i386/stand/lib/vbe.h
diff -u src/sys/arch/i386/stand/lib/vbe.h:1.2 src/sys/arch/i386/stand/lib/vbe.h:1.3
--- src/sys/arch/i386/stand/lib/vbe.h:1.2 Mon Sep 14 11:56:27 2009
+++ src/sys/arch/i386/stand/lib/vbe.h Wed Feb 9 04:37:54 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: vbe.h,v 1.2 2009/09/14 11:56:27 jmcneill Exp $ */
+/* $NetBSD: vbe.h,v 1.3 2011/02/09 04:37:54 jmcneill Exp $ */
/*-
* Copyright (c) 2009 Jared D. McNeill <[email protected]>
@@ -85,12 +85,18 @@
uint8_t Alignment;
} __packed;
+/* EDID */
+#define EDID_MAGIC { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }
+#define EDID_DESC_BLOCK 0x36
+
/* low-level VBE calls, from biosvbe.S */
int biosvbe_info(struct vbeinfoblock *);
int biosvbe_set_mode(int);
int biosvbe_get_mode_info(int, struct modeinfoblock *);
int biosvbe_palette_format(int);
int biosvbe_palette_data(int, int, struct paletteentry *);
+int biosvbe_ddc_caps(void);
+int biosvbe_ddc_read_edid(int, void *);
/* high-level VBE helpers, from vbe.c */
void vbe_init(void);