diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | vbe.c | 87 |
2 files changed, 86 insertions, 3 deletions
@@ -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 @@ -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(®s, 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, ®s) == 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(); } |