This patch adds the ability for the Bochs VGA ROM to return information about a HD wide monitor.
It is constructed from defitions at run time.
Inspired by this patch I digged out from the vgabios mailing list: http://old.nabble.com/VBE-BIOS-support-for-monitor-information-(EDID)-td2295...
Signed-off-by: Hiroshi Miura miurahr@linux.com --- Makefile | 3 +- vgasrc/bochsedid.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/bochsedid.h | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/vgahw.h | 5 ++ 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 vgasrc/bochsedid.c create mode 100644 vgasrc/bochsedid.h
diff --git a/Makefile b/Makefile index 45ea48a..d3e22b9 100644 --- a/Makefile +++ b/Makefile @@ -189,7 +189,8 @@ $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py SRCVGA=src/output.c src/util.c src/pci.c \ vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgafonts.c vgasrc/vbe.c \ vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \ - vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c + vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c \ + vgasrc/bochsedid.c
CFLAGS16VGA = $(CFLAGS16INC) -Isrc
diff --git a/vgasrc/bochsedid.c b/vgasrc/bochsedid.c new file mode 100644 index 0000000..5a40593 --- /dev/null +++ b/vgasrc/bochsedid.c @@ -0,0 +1,147 @@ +// VESA VBE EDID capability for virtual display +// +// Copyright (C) 2012 Hiroshi Miura miurahr@linux.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // dprintf +#include "config.h" // CONFIG_* +#include "bochsedid.h" + +int bochs_get_ddc_capabilities(u16 unit) +{ + if (unit != 0) + return -1; + + return (1 << 8) | VBE_DDC1_PROTOCOL_SUPPORTED; +} + +u8 most_chromaticity[8] VAR16 = {0xA6,0x55,0x48,0x9B,0x26,0x12,0x50,0x54}; +unsigned char vgabios_name[] VAR16 = "Sea VGABIOS"; +struct edid_detailed_timing edid_dtd_1280x1024 VAR16 = { + 0x2a30, 0x00, 0x98, 0x51, 0x00, 0x2A, + 0x40, 0x30, 0x70, 0x13, 0x00, 0x2C, 0xE1, 0x10, + 0x00, 0x00, 0x1E}; +struct edid_detailed_timing edid_dtd_1152x864 VAR16 = { + 0x2a30, 0x80, 0xC0, 0x41, 0x60, 0x24, + 0x30, 0x40, 0x80, 0x13, 0x00, 0x2C, 0xE1, 0x10, + 0x00, 0x00, 0x1E}; +struct edid_detailed_timing edid_dtd_1600x1200 VAR16 = { + 0x3c8c, 0x40, 0x30, 0x62, 0xB0, 0x32, + 0x40, 0x40, 0xC0, 0x13, 0x00, 0x2C, 0xE1, 0x10, + 0x00, 0x00, 0x1E}; +struct edid_detailed_timing edid_dtd_1920x1200 VAR16 = { + 0x4B7D, 0xB0, 0xA0, 0x72, 0xB0, 0x2D, + 0x40, 0x88, 0xC8, 0x55, 0x75, 0x21, + 0x00, 0x00, 0x1C}; +struct edid_monitor_range_limit edid_range_limit VAR16 = { + {0x00,0x00,0x00,0xfD,0x00}, + 50,150, /* Vertical 50Hz - 150Hz */ + 31,135, /* Horiz 31kHz - 135kHz */ + 20, /* clock 200MHz */ + 0, /* no ext */ + 0x0A,0x20,0x20, + 0x2020, + 0x20,0x20 /* padding */ + }; + +int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next) +{ + struct edid_info *info = data; + int i; + + memset_far(seg, info, 0, sizeof(*info)); + /* header */ + SET_FARVAR(seg, info->header[0], 0); + for (i = 1; i < 7; i++) { + SET_FARVAR(seg, info->header[i], 0xFF); + } + SET_FARVAR(seg, info->header[7], 0); + /* Vendor/Product/Serial/Date */ + SET_FARVAR(seg, info->vendor, 0x2104); + SET_FARVAR(seg, info->product,0xCDAB); + SET_FARVAR(seg, info->serial, 0x00000000); + /* date/version */ + SET_FARVAR(seg, info->week,36); + SET_FARVAR(seg, info->year,22); /* 2012 */ + SET_FARVAR(seg, info->major_version,1); + SET_FARVAR(seg, info->minor_version,3); /* 1.3 */ + /* video prameters */ + SET_FARVAR(seg, info->video_setup,0x0F); + /* Video signal interface (analogue, 0.700 : 0.300 : 1.000 V p-p, + Video Setup: Blank Level = Black Level, Separate Sync H & V Signals are + supported, Composite Sync Signal on Horizontal is supported, Composite + Sync Signal on Green Video is supported, Serration on the Vertical Sync + is supported) */ + SET_FARVAR(seg, info->screen_width,0x21); + SET_FARVAR(seg, info->screen_height,0x19); /* 330 mm * 250 mm */ + SET_FARVAR(seg, info->gamma,0x78); /* 2.2 */ + SET_FARVAR(seg, info->feature_flag,0x0F); /* no DMPS states, RGB, display is continuous frequency, prefered mode */ + SET_FARVAR(seg, info->least_chromaticity[0],0x78); + SET_FARVAR(seg, info->least_chromaticity[1],0xF5); + memcpy_far(seg, info->most_chromaticity, get_global_seg(), most_chromaticity, + sizeof (most_chromaticity)); + + SET_FARVAR(seg, info->established_timing[0], 0xFF); + SET_FARVAR(seg, info->established_timing[1], 0xEF); + SET_FARVAR(seg, info->established_timing[2], 0x80); + /* 720x400@70Hz, 720x400@88Hz, 640x480@60Hz, 640x480@67Hz, 640x480@72Hz, 640x480@75Hz, + 800x600@56Hz, 800x600@60Hz, 800x600@72Hz, 800x600@75Hz, 832x624@75Hz, 1152x870@75Hz, + not 1024x768@87Hz(I), 1024x768@60Hz, 1024x768@70Hz, 1024x768@75Hz, 1280x1024@75Hz */ + /* standard timings */ + SET_FARVAR(seg, info->standard_timing[0], EDID_STD_640x480_85Hz); + SET_FARVAR(seg, info->standard_timing[1], EDID_STD_800x600_85Hz); + SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1024x768_85Hz); + SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1280x720_70Hz); + SET_FARVAR(seg, info->standard_timing[4], EDID_STD_1280x960_60Hz); + SET_FARVAR(seg, info->standard_timing[5], EDID_STD_1440x900_60Hz); + SET_FARVAR(seg, info->standard_timing[6], EDID_STD_1600x1200_60Hz); + SET_FARVAR(seg, info->standard_timing[7], EDID_STD_NOP); + /* detailed timing blocks */ + memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1600x1200, + sizeof (edid_dtd_1600x1200)); + /* monitor range */ + memcpy_far(seg, &(info->desc[1].mrld), get_global_seg(), &edid_range_limit, + sizeof(edid_range_limit)); + /* serial */ + for (i = 0; i < 5; i++) { + SET_FARVAR(seg, info->desc[2].mtxtd.header[i], 0); + } + SET_FARVAR(seg, info->desc[2].mtxtd.header[3], 0xFF); + for (i = 0; i < 10; i++) { + SET_FARVAR(seg, info->desc[2].mtxtd.text[i], i+0x30); + } + SET_FARVAR(seg, info->desc[2].mtxtd.text[10], 0x0A); + SET_FARVAR(seg, info->desc[2].mtxtd.text[11], 0x20); + SET_FARVAR(seg, info->desc[2].mtxtd.text[12], 0x20); + /* monitor name */ + for (i = 0; i < 5; i++) { + SET_FARVAR(seg, info->desc[3].mtxtd.header[i], 0); + } + SET_FARVAR(seg, info->desc[3].mtxtd.header[3], 0xFC); + memcpy_far(seg, info->desc[3].mtxtd.text, get_global_seg(), vgabios_name, 12); + SET_FARVAR(seg, info->desc[3].mtxtd.text[12], 0x0A); + /* ext */ + SET_FARVAR(seg, info->extensions, next); + + /* checksum */ + u8 sum = -checksum_far(get_global_seg(), info, sizeof(info)); + SET_FARVAR(seg, info->checksum, sum); + + return 0; +} + +int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data) +{ + if (unit != 0) + return -1; + + switch (block) { + case 0: + return bochs_read_edid_block0(unit, block, seg, data, 0); + default: + return -1; + } +} diff --git a/vgasrc/bochsedid.h b/vgasrc/bochsedid.h new file mode 100644 index 0000000..0f925df --- /dev/null +++ b/vgasrc/bochsedid.h @@ -0,0 +1,136 @@ +#ifndef __BOCHEDID_H +#define __BOCHEDID_H + +/* EDID infomation definitions */ +/* Detailed Timing Descriptor */ +struct edid_detailed_timing { + u16 pixel_clock; + u8 horizontal_addressable_low; + u8 horizontal_blanking_low; + u8 horizontal_high; + u8 vertical_addressable_low; + u8 vertical_blanking_low; + u8 vertical_high; + u8 horizontal_front_porch_low; + u8 horizontal_sync_pulse_low; + u8 vertical_low4; + u8 horizontal_vertical_sync_hi; + u8 horizontal_video_image_low; + u8 vertical_video_image_low; + u8 video_image_high; + u8 horizontal_border; + u8 vertical_border; + u8 features; +} PACKED; + +/* Other Monitor Descriptors */ +/* + 0xFF: Monitor serial number (text) + 0xFE: Unspecified text (text) + 0xFC: Monitor name (text) + */ +struct edid_monitor_text { + u8 header[5]; + u8 text[13]; +} PACKED; + +/* Monitor Range Limits Descriptor */ +/* + 0xFD: Monitor range limits. 6- or 13-byte binary descriptor. + */ +struct edid_monitor_range_limit { + u8 header[5]; + u8 vertical_rate_min; + u8 vertical_rate_max; + u8 horizontal_rate_min; + u8 horizontal_rate_max; + u8 pixel_clock_max; + u8 extended_timing_type; + u8 reserved; + u8 start_frequency; + u8 gtf_c_val; + u16 gtf_m_val; + u8 gtf_k_val; + u8 gtf_j_val; +} PACKED; + +/* White point Descriptor */ +/* + 0xFB: Additional white point data. 2Ã 5-byte descriptors, padded with 0A 20 20. + 0xFA: Additional standard timing identifiers. 6Ã 2-byte descriptors, padded with 0A + */ +struct edid_wp_desc { + u8 index; + u8 least; + u8 x; + u8 y; + u8 gamma; +} PACKED; + +struct edid_white_point { + u8 header[5]; + struct edid_wp_desc desc[2]; + u8 padding[3]; +} PACKED; + +struct edid_additional_timing { + u8 header[5]; + u16 standard_timing[6]; + u8 padding; +} PACKED; + +union edid_descriptors { + struct edid_detailed_timing dtd; + struct edid_monitor_range_limit mrld; + struct edid_monitor_text mtxtd; + struct edid_white_point wpd; + struct edid_additional_timing astd; +} PACKED; + +struct edid_info { + u8 header[8]; + u16 vendor; + u16 product; + u32 serial; + u8 week; + u8 year; + u8 major_version; + u8 minor_version; + u8 video_setup; + u8 screen_width; + u8 screen_height; + u8 gamma; + u8 feature_flag; + u8 least_chromaticity[2]; + u8 most_chromaticity[8]; + u8 established_timing[3]; + u16 standard_timing[8]; + union edid_descriptors desc[4]; + u8 extensions; + u8 checksum; +} PACKED; + +/* EDID Standard Timing Description */ + +/* First byte: X resolution, divided by 8, less 31 (256â2288 pixels) */ +/* bit 7-6, X:Y pixel ratio: 00=16:10; 01=4:3; 10=5:4; 11=16:9 */ +/* bit 5-0, Vertical frequency, less 60 (60â123 Hz), nop 01 01 in Big Endian*/ +#define EDID_STD_640x480_85Hz 0x5931 +#define EDID_STD_800x600_85Hz 0x5945 +#define EDID_STD_1024x768_85Hz 0x5961 +#define EDID_STD_1152x864_70Hz 0x4A71 +#define EDID_STD_1280x720_70Hz 0xCA81 +#define EDID_STD_1280x800_70Hz 0x0A81 +#define EDID_STD_1280x960_60Hz 0x4081 +#define EDID_STD_1280x1024_60Hz 0x8081 +#define EDID_STD_1440x900_60Hz 0x0095 +#define EDID_STD_1600x1200_60Hz 0x40A9 +#define EDID_STD_1600x900_60Hz 0xC0A9 +#define EDID_STD_1680x1050_60Hz 0x00B3 +#define EDID_STD_1920x1080_60Hz 0xC0D1 +#define EDID_STD_1920x1200_60Hz 0x00D1 +#define EDID_STD_NOP 0x0101 + +int bochs_get_ddc_capabilities(u16 unit); +int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data); +#endif /* bochedid.h */ diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 01d2609..130462c 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -8,6 +8,7 @@ #include "bochsvga.h" // bochsvga_set_mode #include "stdvga.h" // stdvga_set_mode #include "geodevga.h" // geodevga_init +#include "bochsedid.h"
static inline struct vgamode_s *vgahw_find_mode(int mode) { if (CONFIG_VGA_CIRRUS) @@ -130,10 +131,14 @@ static inline int vgahw_restore_state(u16 seg, void *data, int states) { }
static inline int vgahw_get_ddc_capabilities(u16 unit) { + if (CONFIG_VGA_BOCHS) + return bochs_get_ddc_capabilities(unit); return stdvga_get_ddc_capabilities(unit); }
static inline int vgahw_read_edid(u16 unit, u16 block, u16 seg, void *data) { + if (CONFIG_VGA_BOCHS) + return bochs_read_edid(unit, block, seg, data); return stdvga_read_edid(unit, block, seg, data); }
On Sun, Sep 16, 2012 at 01:03:18PM +0900, Hiroshi Miura wrote:
This patch adds the ability for the Bochs VGA ROM to return information about a HD wide monitor.
It is constructed from defitions at run time.
[...]
--- /dev/null +++ b/vgasrc/bochsedid.c @@ -0,0 +1,147 @@ +// VESA VBE EDID capability for virtual display +// +// Copyright (C) 2012 Hiroshi Miura miurahr@linux.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // dprintf +#include "config.h" // CONFIG_* +#include "bochsedid.h"
+int bochs_get_ddc_capabilities(u16 unit) +{
- if (unit != 0)
return -1;
- return (1 << 8) | VBE_DDC1_PROTOCOL_SUPPORTED;
+}
+u8 most_chromaticity[8] VAR16 = {0xA6,0x55,0x48,0x9B,0x26,0x12,0x50,0x54}; +unsigned char vgabios_name[] VAR16 = "Sea VGABIOS"; +struct edid_detailed_timing edid_dtd_1280x1024 VAR16 = {
0x2a30, 0x00, 0x98, 0x51, 0x00, 0x2A,
0x40, 0x30, 0x70, 0x13, 0x00, 0x2C, 0xE1, 0x10,
0x00, 0x00, 0x1E};
+struct edid_detailed_timing edid_dtd_1152x864 VAR16 = {
0x2a30, 0x80, 0xC0, 0x41, 0x60, 0x24,
0x30, 0x40, 0x80, 0x13, 0x00, 0x2C, 0xE1, 0x10,
0x00, 0x00, 0x1E};
+struct edid_detailed_timing edid_dtd_1600x1200 VAR16 = {
0x3c8c, 0x40, 0x30, 0x62, 0xB0, 0x32,
0x40, 0x40, 0xC0, 0x13, 0x00, 0x2C, 0xE1, 0x10,
0x00, 0x00, 0x1E};
+struct edid_detailed_timing edid_dtd_1920x1200 VAR16 = {
0x4B7D, 0xB0, 0xA0, 0x72, 0xB0, 0x2D,
0x40, 0x88, 0xC8, 0x55, 0x75, 0x21,
0x00, 0x00, 0x1C};
+struct edid_monitor_range_limit edid_range_limit VAR16 = {
- {0x00,0x00,0x00,0xfD,0x00},
- 50,150, /* Vertical 50Hz - 150Hz */
- 31,135, /* Horiz 31kHz - 135kHz */
- 20, /* clock 200MHz */
- 0, /* no ext */
- 0x0A,0x20,0x20,
- 0x2020,
- 0x20,0x20 /* padding */
- };
+int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next) +{
- struct edid_info *info = data;
- int i;
- memset_far(seg, info, 0, sizeof(*info));
- /* header */
- SET_FARVAR(seg, info->header[0], 0);
- for (i = 1; i < 7; i++) {
SET_FARVAR(seg, info->header[i], 0xFF);
- }
- SET_FARVAR(seg, info->header[7], 0);
- /* Vendor/Product/Serial/Date */
- SET_FARVAR(seg, info->vendor, 0x2104);
- SET_FARVAR(seg, info->product,0xCDAB);
- SET_FARVAR(seg, info->serial, 0x00000000);
- /* date/version */
- SET_FARVAR(seg, info->week,36);
- SET_FARVAR(seg, info->year,22); /* 2012 */
- SET_FARVAR(seg, info->major_version,1);
- SET_FARVAR(seg, info->minor_version,3); /* 1.3 */
- /* video prameters */
- SET_FARVAR(seg, info->video_setup,0x0F);
- /* Video signal interface (analogue, 0.700 : 0.300 : 1.000 V p-p,
Video Setup: Blank Level = Black Level, Separate Sync H & V Signals are
supported, Composite Sync Signal on Horizontal is supported, Composite
Sync Signal on Green Video is supported, Serration on the Vertical Sync
is supported) */
- SET_FARVAR(seg, info->screen_width,0x21);
- SET_FARVAR(seg, info->screen_height,0x19); /* 330 mm * 250 mm */
- SET_FARVAR(seg, info->gamma,0x78); /* 2.2 */
- SET_FARVAR(seg, info->feature_flag,0x0F); /* no DMPS states, RGB, display is continuous frequency, prefered mode */
- SET_FARVAR(seg, info->least_chromaticity[0],0x78);
- SET_FARVAR(seg, info->least_chromaticity[1],0xF5);
- memcpy_far(seg, info->most_chromaticity, get_global_seg(), most_chromaticity,
sizeof (most_chromaticity));
- SET_FARVAR(seg, info->established_timing[0], 0xFF);
- SET_FARVAR(seg, info->established_timing[1], 0xEF);
- SET_FARVAR(seg, info->established_timing[2], 0x80);
- /* 720x400@70Hz, 720x400@88Hz, 640x480@60Hz, 640x480@67Hz, 640x480@72Hz, 640x480@75Hz,
800x600@56Hz, 800x600@60Hz, 800x600@72Hz, 800x600@75Hz, 832x624@75Hz, 1152x870@75Hz,
not 1024x768@87Hz(I), 1024x768@60Hz, 1024x768@70Hz, 1024x768@75Hz, 1280x1024@75Hz */
- /* standard timings */
- SET_FARVAR(seg, info->standard_timing[0], EDID_STD_640x480_85Hz);
- SET_FARVAR(seg, info->standard_timing[1], EDID_STD_800x600_85Hz);
- SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1024x768_85Hz);
- SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1280x720_70Hz);
- SET_FARVAR(seg, info->standard_timing[4], EDID_STD_1280x960_60Hz);
- SET_FARVAR(seg, info->standard_timing[5], EDID_STD_1440x900_60Hz);
- SET_FARVAR(seg, info->standard_timing[6], EDID_STD_1600x1200_60Hz);
- SET_FARVAR(seg, info->standard_timing[7], EDID_STD_NOP);
- /* detailed timing blocks */
- memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1600x1200,
sizeof (edid_dtd_1600x1200));
- /* monitor range */
- memcpy_far(seg, &(info->desc[1].mrld), get_global_seg(), &edid_range_limit,
sizeof(edid_range_limit));
- /* serial */
- for (i = 0; i < 5; i++) {
SET_FARVAR(seg, info->desc[2].mtxtd.header[i], 0);
- }
- SET_FARVAR(seg, info->desc[2].mtxtd.header[3], 0xFF);
- for (i = 0; i < 10; i++) {
SET_FARVAR(seg, info->desc[2].mtxtd.text[i], i+0x30);
- }
- SET_FARVAR(seg, info->desc[2].mtxtd.text[10], 0x0A);
- SET_FARVAR(seg, info->desc[2].mtxtd.text[11], 0x20);
- SET_FARVAR(seg, info->desc[2].mtxtd.text[12], 0x20);
- /* monitor name */
- for (i = 0; i < 5; i++) {
SET_FARVAR(seg, info->desc[3].mtxtd.header[i], 0);
- }
- SET_FARVAR(seg, info->desc[3].mtxtd.header[3], 0xFC);
- memcpy_far(seg, info->desc[3].mtxtd.text, get_global_seg(), vgabios_name, 12);
- SET_FARVAR(seg, info->desc[3].mtxtd.text[12], 0x0A);
- /* ext */
- SET_FARVAR(seg, info->extensions, next);
- /* checksum */
- u8 sum = -checksum_far(get_global_seg(), info, sizeof(info));
- SET_FARVAR(seg, info->checksum, sum);
- return 0;
+}
+int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data) +{
- if (unit != 0)
return -1;
- switch (block) {
- case 0:
return bochs_read_edid_block0(unit, block, seg, data, 0);
- default:
return -1;
- }
+}
The patch looks okay to me.
Out of curiousity, though, why not populate the edid block at init? Something like:
struct edid_info BochsEDID VAR16;
void bochs_setup_edid(void) { ... }
int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data) { if (unit != 0 || block != 0) return -1;
memcpy_far(seg, data, get_global_seg(), &BochsEDID, sizeof(BochsEDID)); return 0; }
-Kevin
On 2012.09.16 17:46, Kevin O'Connor wrote:
On Sun, Sep 16, 2012 at 01:03:18PM +0900, Hiroshi Miura wrote:
This patch adds the ability for the Bochs VGA ROM to return information about a HD wide monitor.
It is constructed from defitions at run time.
[...]
--- /dev/null +++ b/vgasrc/bochsedid.c @@ -0,0 +1,147 @@ +// VESA VBE EDID capability for virtual display +// +// Copyright (C) 2012 Hiroshi Miura miurahr@linux.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // dprintf +#include "config.h" // CONFIG_* +#include "bochsedid.h"
+int bochs_get_ddc_capabilities(u16 unit) +{
- if (unit != 0)
return -1;
- return (1 << 8) | VBE_DDC1_PROTOCOL_SUPPORTED;
+}
[snip]
+int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next) +{
- struct edid_info *info = data;
- int i;
- memset_far(seg, info, 0, sizeof(*info));
[snip]
- /* ext */
- SET_FARVAR(seg, info->extensions, next);
- /* checksum */
- u8 sum = -checksum_far(get_global_seg(), info, sizeof(info));
- SET_FARVAR(seg, info->checksum, sum);
- return 0;
+}
+int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data) +{
- if (unit != 0)
return -1;
- switch (block) {
- case 0:
return bochs_read_edid_block0(unit, block, seg, data, 0);
- default:
return -1;
- }
+}
The patch looks okay to me.
Out of curiousity, though, why not populate the edid block at init? Something like:
struct edid_info BochsEDID VAR16;
void bochs_setup_edid(void) { ... }
int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data) { if (unit != 0 || block != 0) return -1;
memcpy_far(seg, data, get_global_seg(), &BochsEDID, sizeof(BochsEDID)); return 0;
}
I think we need runtime generation of EDID when supporting following cases;
(a) terminal service -Assume that we use qemu-kvm and seabios/vgabios for Terminal service, (as same as Windows Server). -Thin client that run VNC client connect. -qemu may want to ask guest that new (virtual) display is connected and update its resolution. --qemu may trigger guest OS as if your note-PC triggered when connecting projector. --Guest OS request EDID of new (virtual) display -- seabios/vgabios ask qemu about preferable resolution. -- seabios/vgabios return EDID that offer resolution that is good for client.
(b) vnc client resolution change - vnc client change its resolution. - qemu may ask guest OS refresh its resolution. - Seabios/vgabios report a preferred resolution as EDID.
If we don't need such feature (in future), populating the edid block at init is ok.
As Gred suggest me, we can add bochs api that offer preferable resolution, and use it for above scenario, that may be great.
I'm sorry I don't know how trigger guest os from host when VNC client connect or change its resolution.
Hiroshi
Hi,
Out of curiousity, though, why not populate the edid block at init? Something like:
I think we need runtime generation of EDID when supporting following cases;
(a) terminal service -Assume that we use qemu-kvm and seabios/vgabios for Terminal service, (as same as Windows Server). -Thin client that run VNC client connect. -qemu may want to ask guest that new (virtual) display is connected and update its resolution. --qemu may trigger guest OS as if your note-PC triggered when connecting projector. --Guest OS request EDID of new (virtual) display -- seabios/vgabios ask qemu about preferable resolution. -- seabios/vgabios return EDID that offer resolution that is good for client.
(b) vnc client resolution change
- vnc client change its resolution.
- qemu may ask guest OS refresh its resolution.
- Seabios/vgabios report a preferred resolution as EDID.
If we don't need such feature (in future), populating the edid block at init is ok.
I think we should populate at init time.
BTW: a CONFIG_EDID would be nice.
As Gred suggest me, we can add bochs api that offer preferable resolution, and use it for above scenario, that may be great.
Indeed ...
I'm sorry I don't know how trigger guest os from host when VNC client connect or change its resolution.
... but seabios doesn't need to worry about this.
The usual way the (virtual) hardware signals such changes to the os is to raise an interrupt, and the os gfx card driver handles it. No seabios involved here. Even if seabios would handle the interrupt and update the edid there would still be the problem that there simply is no bios interface which seabios could use to inform the guest os.
sea(vga)bios should just use what it finds at boot time and not worry about any changes while the guest is running. If something changes seabios will pick it up on the next reboot.
cheers, Gerd
On 2012年09月18日 14:56, Gerd Hoffmann wrote:
Hi,
Out of curiousity, though, why not populate the edid block at init? Something like:
I think we need runtime generation of EDID when supporting following cases;
(a) terminal service -Assume that we use qemu-kvm and seabios/vgabios for Terminal service, (as same as Windows Server). -Thin client that run VNC client connect. -qemu may want to ask guest that new (virtual) display is connected and update its resolution. --qemu may trigger guest OS as if your note-PC triggered when connecting projector. --Guest OS request EDID of new (virtual) display -- seabios/vgabios ask qemu about preferable resolution. -- seabios/vgabios return EDID that offer resolution that is good for client.
(b) vnc client resolution change
- vnc client change its resolution.
- qemu may ask guest OS refresh its resolution.
- Seabios/vgabios report a preferred resolution as EDID.
If we don't need such feature (in future), populating the edid block at init is ok.
I think we should populate at init time.
BTW: a CONFIG_EDID would be nice.
I'd like to rework it (now doing...) to pupulation at init time.
As Gred suggest me, we can add bochs api that offer preferable resolution, and use it for above scenario, that may be great.
Indeed ...
I'm sorry I don't know how trigger guest os from host when VNC client connect or change its resolution.
... but seabios doesn't need to worry about this.
The usual way the (virtual) hardware signals such changes to the os is to raise an interrupt, and the os gfx card driver handles it. No seabios involved here. Even if seabios would handle the interrupt and update the edid there would still be the problem that there simply is no bios interface which seabios could use to inform the guest os.
sea(vga)bios should just use what it finds at boot time and not worry about any changes while the guest is running. If something changes seabios will pick it up on the next reboot.
Thanks for clarification. Best,
Hiroshi