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 | 85 +++++++++++++++++++++++++++++++++++++++++++++++++------ vgasrc/vgahw.h | 20 +++++++++++++ 2 files changed, 95 insertions(+), 10 deletions(-)
diff --git a/vgasrc/vgahw.c b/vgasrc/vgahw.c index 0ef3af5..7620d59 100644 --- a/vgasrc/vgahw.c +++ b/vgasrc/vgahw.c @@ -1,37 +1,102 @@ #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 + +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(int mode, int flags) { - if (CONFIG_VGA_CIRRUS) + if (HAVE_VGA_CIRRUS) return clext_set_mode(mode, flags); - if (CONFIG_VGA_BOCHS) + if (HAVE_VGA_BOCHS) return bochsvga_set_mode(mode, flags); return stdvga_set_mode(mode, 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); }
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; + } + } + } else { + } + + 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(); } - diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 34de00d..82caaea 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(int mode, int flags); void vgahw_list_modes(u16 seg, u16 *dest, u16 *last);