aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--vbe.c87
2 files changed, 86 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 26590ab..d8f7a09 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
- monitor-get-edid-using-vbe:
o update x86emu from xserver git (fixes issues at least with newish
NVIDIA cards)
+ o check if the port supports DDC before trying to read EDID data (this
+ should prevent problems when probing nonexistent ports on old cards)
Version 2.2 - 16 August 2009
diff --git a/vbe.c b/vbe.c
index 7791751..ff02e03 100644
--- a/vbe.c
+++ b/vbe.c
@@ -135,6 +135,42 @@ static int vbe_check_vbe_info(hd_data_t *hd_data)
return 1;
}
+static void parse_ddc_info(int port, int info)
+{
+ log_err("Port %d:\n", port);
+ log_err(" DDC1 %ssupported\n", info & 1 ? "" : "not ");
+ log_err(" DDC2 %ssupported\n", info & 2 ? "" : "not ");
+ log_err(" Screen %sblanked during data transfer\n", info & 4 ? "" : "not ");
+ log_err(" Time to transfer one EDID block: %d sec (rounded up)\n", (info & 0xff00) >> 8);
+}
+
+static int vbe_check_ddc_capabilities(hd_data_t *hd_data, int port)
+{
+ int i;
+ int ax, bx, cx;
+
+ /* Setup registers for the interrupt call */
+ ax = 0x4f15;
+ bx = 0; /* Report DDC Capabilities */
+ cx = port;
+
+ /* Get capabilities */
+ i = CallInt10(&ax, &bx, &cx, NULL, 0, hd_data->flags.cpuemu) & 0xffff;
+ if (i != 0x4f) {
+ log_err("DDC: Error (0x4f15:00): 0x%04x\n", i);
+ return 0;
+ }
+
+ parse_ddc_info(port, bx);
+
+ if (!(bx & 3)) {
+ log_err("DDC (0x4f15:00): DDC not supported, not continuing\n", i);
+ return 0;
+ }
+
+ return 1;
+}
+
/* Get EDID info. */
int vbe_get_edid_info(hd_data_t *hd_data, char *edid, int port)
{
@@ -149,7 +185,7 @@ int vbe_get_edid_info(hd_data_t *hd_data, char *edid, int port)
/* Get EDID block */
i = CallInt10(&ax, &bx, &cx, edid, 256, hd_data->flags.cpuemu) & 0xffff;
if (i != 0x4f) {
- log_err("EDID: Error (0x4f15): 0x%04x\n", i);
+ log_err("EDID: Error (0x4f15:01): 0x%04x\n", i);
return 0;
}
@@ -211,6 +247,49 @@ static int vbe_check_vbe_info__old(void)
return 1;
}
+static int vbe_check_ddc_capabilities__old(int port)
+{
+ int i;
+ struct LRMI_regs regs;
+
+ /* initialize LRMI */
+ if (LRMI_init() == 0) {
+ log_err("EDID: could not initialize LRMI\n");
+ return 0;
+ }
+
+ /* set up registers for the interrupt call. */
+ memset(&regs, 0, sizeof(regs));
+ regs.eax = 0x4f15;
+ regs.ebx = 0x0000;
+ regs.ecx = port;
+ regs.es = 0;
+ regs.edi = 0;
+
+ /* do it. */
+ iopl(3);
+ ioperm(0, 0x400, 1);
+ if (LRMI_int(0x10, &regs) == 0) {
+ return 0;
+ }
+
+ /* check for successful return code */
+ i = regs.eax & 0xffff;
+ if (i != 0x4f) {
+ log_err("DDC: Error (0x4f15:00): 0x%04x\n", i);
+ return 0;
+ }
+
+ parse_ddc_info(port, regs.ebx);
+
+ if (!(regs.ebx & 3)) {
+ log_err("DDC (0x4f15:00): DDC not supported, not continuing\n", i);
+ return 0;
+ }
+
+ return 1;
+}
+
static int vbe_get_edid_info__old(char *edid, int port)
{
int i;
@@ -252,7 +331,7 @@ static int vbe_get_edid_info__old(char *edid, int port)
i = regs.eax & 0xffff;
if (i != 0x4f) {
LRMI_free_real(mem);
- log_err("EDID: Error (0x4f15): 0x%04x\n", i);
+ log_err("EDID: Error (0x4f15:01): 0x%04x\n", i);
return 0;
}
@@ -269,7 +348,8 @@ int get_edid__old(char *edid, int port)
one is also bogus for the other */
log_err("Retrying with old LRMI interface\n");
ok =
- (box_is_xbox() || vbe_check_vbe_info__old()) &&
+ (box_is_xbox() || (vbe_check_vbe_info__old() &&
+ vbe_check_ddc_capabilities__old(port))) &&
vbe_get_edid_info__old(edid, port);
return ok;
}
@@ -287,6 +367,7 @@ int get_edid(hd_data_t *hd_data, char *edid, int port)
if (!box_is_xbox()) {
if (InitInt10(hd_data) == 0) {
ok = vbe_check_vbe_info(hd_data)
+ && vbe_check_ddc_capabilities(hd_data, port)
&& vbe_get_edid_info(hd_data, edid, port);
FreeInt10();
}