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/vgahw.c | 109 ++++++++++++++++++++++++++++++++++++++++++++----------- vgasrc/vgahw.h | 20 ++++++++++ 2 files changed, 107 insertions(+), 22 deletions(-)
diff --git a/vgasrc/vgahw.c b/vgasrc/vgahw.c index be5945e..77b8e77 100644 --- a/vgasrc/vgahw.c +++ b/vgasrc/vgahw.c @@ -1,28 +1,72 @@ #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 + +struct vga_pci_table { + u16 vid; + u16 did; + char *name; + enum vga_type type; + int supported; +}; + +static struct vga_pci_table hwtab[] VAR16 = { + { + .vid = 0x1013, + .did = 0x00b8, + .name = "QEMU Cirrus VGA (CLGD 54xx)", + .type = VGA_TYPE_CIRRUS, + .supported = CONFIG_VGA_CIRRUS, + },{ + .vid = 0x1234, + .did = 0x1111, + .name = "QEMU Standard VGA", + .type = VGA_TYPE_BOCHS, + .supported = CONFIG_VGA_BOCHS, + },{ + .vid = 0x100b, + .did = 0x0030, + .name = "Geode GX2", + .type = VGA_TYPE_GEODEGX2, + .supported = CONFIG_VGA_GEODEGX2, + },{ + .vid = 0x1022, + .did = 0x2081, + .name = "Geode LX", + .type = VGA_TYPE_GEODELX, + .supported = CONFIG_VGA_GEODELX, + } +}; + +enum vga_type vga_type VAR16;
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,66 +74,87 @@ void vgahw_list_modes(u16 seg, u16 *dest, u16 *last)
int vgahw_init(void) { - if (CONFIG_VGA_CIRRUS) + 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 %s [pci %04x:%04x]\n", + GET_GLOBAL(hwtab[i].name), vid, did); + if (GET_GLOBAL(hwtab[i].supported)) { + SET_VGA(vga_type, GET_GLOBAL(hwtab[i].type)); + } else { + SET_VGA(vga_type, VGA_TYPE_STDVGA); + dprintf(1, "vgahw: support not compiled, using stdvga\n"); + } + break; + } + } + } + + if (HAVE_VGA_CIRRUS) return clext_init(); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_init(); - if (CONFIG_VGA_GEODEGX2 || CONFIG_VGA_GEODELX) + if (HAVE_VGA_GEODEGX2 || HAVE_VGA_GEODELX) return geodevga_init(); return stdvga_init(); }
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); } - diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 751d4fd..2f51ee8 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -9,6 +9,26 @@ #include "stdvga.h" // stdvga_set_mode #include "geodevga.h" // geodevga_init
+enum vga_type { + VGA_TYPE_UNDEFINED = 0, + VGA_TYPE_STDVGA, + VGA_TYPE_CIRRUS, + VGA_TYPE_BOCHS, + VGA_TYPE_GEODEGX2, + VGA_TYPE_GEODELX, +}; + +extern enum vga_type vga_type; + +#define HAVE_VGA_CIRRUS (CONFIG_VGA_CIRRUS && \ + (GET_GLOBAL(vga_type) == VGA_TYPE_CIRRUS)) +#define HAVE_VGA_BOCHS (CONFIG_VGA_BOCHS && \ + (GET_GLOBAL(vga_type) == VGA_TYPE_BOCHS)) +#define HAVE_VGA_GEODEGX2 (CONFIG_VGA_GEODEGX2 && \ + (GET_GLOBAL(vga_type) == VGA_TYPE_GEODEGX2)) +#define HAVE_VGA_GEODELX (CONFIG_VGA_GEODELX && \ + (GET_GLOBAL(vga_type) == VGA_TYPE_GEODELX)) + 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);