Add support for pci hardware detection (using pci id lookup), so we can create a unified rom with support for different pieces of hardware.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- vgasrc/Kconfig | 12 ++---- vgasrc/vgabios.c | 2 +- vgasrc/vgahw.c | 114 +++++++++++++++++++++++++++++++++++++++--------------- vgasrc/vgahw.h | 17 ++++++++ 4 files changed, 105 insertions(+), 40 deletions(-)
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig index 881e9ec..e011238 100644 --- a/vgasrc/Kconfig +++ b/vgasrc/Kconfig @@ -15,15 +15,11 @@ menu "VGA ROM" help Build basic VGA BIOS support.
- config VGA_CIRRUS - bool "QEMU Cirrus CLGD 54xx VGA BIOS" + config VGA_QEMU + bool "QEMU VGA BIOS" help - Build support for Cirrus VGA emulation. - - config VGA_BOCHS - bool "Bochs DISPI interface VGA BIOS" - help - Build support for Bochs DISPI interface. + Build VGA BIOS for QEMU. This builds a unified BIOS, + supporting both bochs vga interface and cirrus vga emulation.
config VGA_GEODEGX2 bool "GeodeGX2 interface VGA BIOS" diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 7b6c50a..a1cf11a 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -1001,7 +1001,7 @@ handle_1012XX(struct bregs *regs) static void handle_1012(struct bregs *regs) { - if (CONFIG_VGA_CIRRUS && regs->bl >= 0x80) { + if (HAVE_VGA_CIRRUS && regs->bl >= 0x80) { clext_1012(regs); return; } diff --git a/vgasrc/vgahw.c b/vgasrc/vgahw.c index 65afeb1..03d8757 100644 --- a/vgasrc/vgahw.c +++ b/vgasrc/vgahw.c @@ -1,28 +1,57 @@ #include "vgahw.h" +#include "config.h" // CONFIG_* +#include "util.h" // dprintf +#include "biosvar.h" // GET_GLOBAL +#include "pci.h" // pci_config_readw +#include "pci_regs.h" // PCI_VENDOR_ID +#include "vgabios.h" // VgaBDF + +enum qemu_vga_type qemu_vga_type VAR16; + +struct qemu_pci_table { + u16 vid; + u16 did; + char *name; + enum qemu_vga_type type; +}; + +static struct qemu_pci_table hwtab[] VAR16 = { + { + .vid = 0x1013, + .did = 0x00b8, + .name = "cirrus", + .type = VGA_TYPE_CIRRUS, + },{ + .vid = 0x1234, + .did = 0x1111, + .name = "std", + .type = VGA_TYPE_BOCHS, + } +};
struct vgamode_s *vgahw_find_mode(int mode) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_find_mode(mode); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_find_mode(mode); return stdvga_find_mode(mode); }
int vgahw_set_mode(struct vgamode_s *vmode_g, int flags) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_set_mode(vmode_g, flags); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_mode(vmode_g, flags); return stdvga_set_mode(vmode_g, flags); }
void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) clext_list_modes(seg, dest, last); - else if (CONFIG_VGA_BOCHS) + else if (HAVE_VGA_BOCHS) bochsvga_list_modes(seg, dest, last); else stdvga_list_modes(seg, dest, last); @@ -30,10 +59,34 @@ void vgahw_list_modes(u16 seg, u16 *dest, u16 *last)
int vgahw_init(void) { - if (CONFIG_VGA_CIRRUS) - return clext_init(); - if (CONFIG_VGA_BOCHS) - return bochsvga_init(); + if (CONFIG_VGA_QEMU) { + if (CONFIG_VGA_PCI) { + u16 bdf = GET_GLOBAL(VgaBDF); + u16 vid = pci_config_readw(bdf, PCI_VENDOR_ID); + u16 did = pci_config_readw(bdf, PCI_DEVICE_ID); + int i; + + for (i = 0; i < ARRAY_SIZE(hwtab); i++) { + if (GET_GLOBAL(hwtab[i].vid) == vid && + GET_GLOBAL(hwtab[i].did) == did) { + dprintf(1, "vgahw: detected qemu %s vga [pci %04x:%04x]\n", + GET_GLOBAL(hwtab[i].name), vid, did); + SET_VGA(qemu_vga_type, GET_GLOBAL(hwtab[i].type)); + break; + } + } + } + + if (GET_GLOBAL(qemu_vga_type) == VGA_TYPE_UNDEFINED) { + SET_VGA(qemu_vga_type, VGA_TYPE_STDVGA); + dprintf(1, "vgahw: no known hardware found, using stdvga\n"); + } + if (HAVE_VGA_CIRRUS) + return clext_init(); + if (HAVE_VGA_BOCHS) + return bochsvga_init(); + } + if (CONFIG_VGA_GEODEGX2 || CONFIG_VGA_GEODELX) return geodevga_init(); return stdvga_init(); @@ -41,96 +94,95 @@ int vgahw_init(void)
int vgahw_get_window(struct vgamode_s *vmode_g, int window) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_get_window(vmode_g, window); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_get_window(vmode_g, window); return stdvga_get_window(vmode_g, window); }
int vgahw_set_window(struct vgamode_s *vmode_g, int window, int val) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_set_window(vmode_g, window, val); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_window(vmode_g, window, val); return stdvga_set_window(vmode_g, window, val); }
int vgahw_get_linelength(struct vgamode_s *vmode_g) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_get_linelength(vmode_g); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_get_linelength(vmode_g); return stdvga_get_linelength(vmode_g); }
int vgahw_set_linelength(struct vgamode_s *vmode_g, int val) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_set_linelength(vmode_g, val); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_linelength(vmode_g, val); return stdvga_set_linelength(vmode_g, val); }
int vgahw_get_displaystart(struct vgamode_s *vmode_g) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_get_displaystart(vmode_g); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_get_displaystart(vmode_g); return stdvga_get_displaystart(vmode_g); }
int vgahw_set_displaystart(struct vgamode_s *vmode_g, int val) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_set_displaystart(vmode_g, val); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_displaystart(vmode_g, val); return stdvga_set_displaystart(vmode_g, val); }
int vgahw_get_dacformat(struct vgamode_s *vmode_g) { - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_get_dacformat(vmode_g); return stdvga_get_dacformat(vmode_g); }
int vgahw_set_dacformat(struct vgamode_s *vmode_g, int val) { - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_dacformat(vmode_g, val); return stdvga_set_dacformat(vmode_g, val); }
int vgahw_size_state(int states) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_size_state(states); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_size_state(states); return stdvga_size_state(states); }
int vgahw_save_state(u16 seg, void *data, int states) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_save_state(seg, data, states); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_save_state(seg, data, states); return stdvga_save_state(seg, data, states); }
int vgahw_restore_state(u16 seg, void *data, int states) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_restore_state(seg, data, states); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_restore_state(seg, data, states); return stdvga_restore_state(seg, data, states); } - diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 4643d38..186f7b5 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -9,6 +9,23 @@ #include "stdvga.h" // stdvga_set_mode #include "geodevga.h" // geodevga_init
+enum qemu_vga_type { + VGA_TYPE_UNDEFINED = 0, + VGA_TYPE_STDVGA, + VGA_TYPE_CIRRUS, + VGA_TYPE_BOCHS, +}; + +extern enum qemu_vga_type qemu_vga_type; + +#if CONFIG_VGA_QEMU +# define HAVE_VGA_CIRRUS (GET_GLOBAL(qemu_vga_type) == VGA_TYPE_CIRRUS) +# define HAVE_VGA_BOCHS (GET_GLOBAL(qemu_vga_type) == VGA_TYPE_BOCHS) +#else +# define HAVE_VGA_CIRRUS (0) +# define HAVE_VGA_BOCHS (0) +#endif + struct vgamode_s *vgahw_find_mode(int mode); int vgahw_set_mode(struct vgamode_s *vmode_g, int flags); void vgahw_list_modes(u16 seg, u16 *dest, u16 *last);