>From 6570e2859a43a1bc5178dc2130b1e91672fec6ae Mon Sep 17 00:00:00 2001 From: Izik Eidus Date: Mon, 19 Nov 2007 18:49:48 +0200 Subject: [PATCH] qemu: allow setting static devfn for pci devices from the command line Signed-off-by: Izik Eidus --- hw/pci.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- vl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 5 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 0b5e7bf..3914704 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -52,6 +52,9 @@ target_phys_addr_t pci_mem_base; static int pci_irq_index; static PCIBus *first_bus; +char static_devfns[PCI_DEVICES_MAX][64]; +int static_devfns_index = 0; + PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, qemu_irq *pic, int devfn_min, int nirq) { @@ -98,6 +101,67 @@ int pci_device_load(PCIDevice *s, QEMUFile *f) return 0; } +int pci_read_static_devfn(PCIBus *bus, const char *name) +{ + int i; + int y; + int count; + + for (i = 0; i < static_devfns_index; i++) { + count = 0; + for (y = 0; y < sizeof(static_devfns[0]) && name[y]; y++) { + if (tolower(static_devfns[i][y]) != tolower(name[y])) + continue; + count++; + } + /*if count is y we found devfn value for this device name */ + if (count == y && y < sizeof(static_devfns[0]) && + static_devfns[i][y] == '=') { + int devfn; + char *value_buffer; + + static_devfns[i][sizeof(static_devfns[0]) - 1] = '\0'; + value_buffer = strstr(static_devfns[i], "="); + if (!value_buffer) + return -1; + value_buffer++; + devfn = atoi(value_buffer); + if (devfn < 0) + return -1; + /* + * check if the devfn is already registered in case this pci device + * is registering now not for the first time. + * in this case we increase the value of the devfn by one untill + * we find a free devfn + * note: you should provide devices we big enougth spaces beteween + * them if you want to register the same devices more than once + */ + for (; devfn < 256; devfn++) + if (!bus->devices[devfn]) + return devfn; + return -1; + } + } + return -1; +} + +int pci_is_static_devfn(int devfn) +{ + int i; + char *value_buffer; + + for (i = 0; i < static_devfns_index; i++) { + static_devfns[i][sizeof(static_devfns[0]) - 1] = '\0'; + value_buffer = strstr(static_devfns[i], "="); + if (!value_buffer) + continue; + value_buffer++; + if (devfn == atoi(value_buffer)) + return 1; + } + return 0; +} + /* -1 for devfn means auto assign */ PCIDevice *pci_register_device(PCIBus *bus, const char *name, int instance_size, int devfn, @@ -110,13 +174,17 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, return NULL; if (devfn < 0) { - for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { - if (!bus->devices[devfn]) - goto found; + devfn = pci_read_static_devfn(bus, name); + if (devfn < 0) { + for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { + if (!bus->devices[devfn] && !pci_is_static_devfn(devfn)) + goto found; + } + return NULL; + found: ; } - return NULL; - found: ; } + pci_dev = qemu_mallocz(instance_size); if (!pci_dev) return NULL; diff --git a/vl.c b/vl.c index 8b2b5bd..7ae7275 100644 --- a/vl.c +++ b/vl.c @@ -29,6 +29,7 @@ #include "hw/fdc.h" #include "hw/audiodev.h" #include "hw/isa.h" +#include "hw/pci.h" #include "net.h" #include "console.h" #include "sysemu.h" @@ -871,6 +872,64 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); #endif /* _WIN32 */ +static void set_static_devfn(const char *optarg) +{ + int i; + + if (*optarg == '?') { + printf("usage: -static-devfn dev_name=static_devfn_num\n" + "list of device names:\n" + "rtl8139 - realteak8139 network device\n" + "ne2000 - ne2000 network device\n" + "openpic\n" + "pcnet\n" + "i440fx\n" + "piix\n" + "vga - vga video card device\n" + "qemuware_svga - vmware svga video card device\n" + "piix3\n" + "piix4\n" + "macio\n" + "pci_brgd - pci bridge\n" + "cmd646_ide - ide device\n" + "advanced_pci_bus - acpi device\n" + "piix3_ide - ide device\n" + "prep_host_bridge_-motorola_raven\n" + "uni-north_main\n" + "uni-north_bridge\n" + "uni-north_agp\n" + "uni-north_internal\n" + "ochi_usb\n" + "usb_uchi\n" + "piix4_ide - ide device\n" + "lsi53c895a_scsi_hba\n" + "realview_eb_pci_controller\n" + "versatile/pb_pci_controller\n" + "cirrus_vga - cirrus vga video card device\n" + "es1370\n" + "grackle_host_bridge\n" + "gt64120_pci_bus\n" + "std-vga - standart vga video card device\n"); + exit(0); + } else { + extern int static_devfns_index; + extern char static_devfns[PCI_DEVICES_MAX][64]; + + if (static_devfns_index >= PCI_DEVICES_MAX) { + fprintf(stderr, "Too many static-devfns registred\n"); + exit(1); + } + pstrcpy(static_devfns[static_devfns_index], + sizeof(static_devfns[static_devfns_index]), + optarg); + for (i = 0; static_devfns[static_devfns_index][i] && + i < sizeof(static_devfns[0]); i++) + if (static_devfns[static_devfns_index][i] == '_') + static_devfns[static_devfns_index][i] = ' '; + static_devfns_index++; + } +} + static struct qemu_alarm_timer alarm_timers[] = { #ifndef _WIN32 #ifdef __linux__ @@ -7076,6 +7135,8 @@ static void help(int exitcode) #endif "-usb enable the USB driver (will be the default soon)\n" "-usbdevice name add the host or guest USB device 'name'\n" + "-static-devfn set a static devfn for device\n" + " use -static-devfn ? to get help\n" #if defined(TARGET_PPC) || defined(TARGET_SPARC) "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n" #endif @@ -7243,6 +7304,7 @@ enum { QEMU_OPTION_win2k_hack, QEMU_OPTION_usb, QEMU_OPTION_usbdevice, + QEMU_OPTION_static_devfn, QEMU_OPTION_smp, QEMU_OPTION_vnc, QEMU_OPTION_no_acpi, @@ -7339,6 +7401,7 @@ const QEMUOption qemu_options[] = { { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, + { "static-devfn", HAS_ARG, QEMU_OPTION_static_devfn }, { "smp", HAS_ARG, QEMU_OPTION_smp }, { "vnc", HAS_ARG, QEMU_OPTION_vnc }, @@ -8111,6 +8174,9 @@ int main(int argc, char **argv) optarg); usb_devices_index++; break; + case QEMU_OPTION_static_devfn: + set_static_devfn(optarg); + break; case QEMU_OPTION_smp: smp_cpus = atoi(optarg); if (smp_cpus < 1 || smp_cpus > MAX_CPUS) { -- 1.5.3.4