#include "pci.h"
#include "monitor.h"
#include "net.h"
-#include "virtio-net.h"
#include "sysemu.h"
//#define DEBUG_PCI
struct PCIBus {
+ BusState qbus;
int bus_num;
int devfn_min;
pci_set_irq_fn set_irq;
return 0;
}
-PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+PCIBus *pci_register_bus(DeviceState *parent, const char *name,
+ pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
qemu_irq *pic, int devfn_min, int nirq)
{
PCIBus *bus;
static int nbus = 0;
- bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
+ bus = FROM_QBUS(PCIBus, qbus_create(BUS_TYPE_PCI,
+ sizeof(PCIBus) + (nirq * sizeof(int)),
+ parent, name));
bus->set_irq = set_irq;
bus->map_irq = map_irq;
bus->irq_opaque = pic;
}
/* -1 for devfn means auto assign */
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
- int instance_size, int devfn,
- PCIConfigReadFunc *config_read,
- PCIConfigWriteFunc *config_write)
+static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
+ const char *name, int devfn,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write)
{
- PCIDevice *pci_dev;
-
if (pci_irq_index >= PCI_DEVICES_MAX)
return NULL;
return NULL;
found: ;
}
- pci_dev = qemu_mallocz(instance_size);
pci_dev->bus = bus;
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
return pci_dev;
}
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+ int instance_size, int devfn,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write)
+{
+ PCIDevice *pci_dev;
+
+ pci_dev = qemu_mallocz(instance_size);
+ pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
+ config_read, config_write);
+ return pci_dev;
+}
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
{
return addr + pci_mem_base;
qemu_free_irqs(pci_dev->irq);
pci_irq_index--;
pci_dev->bus->devices[pci_dev->devfn] = NULL;
- qemu_free(pci_dev);
+ qdev_free(&pci_dev->qdev);
return 0;
}
NULL
};
-typedef PCIDevice *(*PCINICInitFn)(PCIBus *, NICInfo *, int);
-
-static PCINICInitFn pci_nic_init_fns[] = {
- pci_ne2000_init,
- pci_i82551_init,
- pci_i82557b_init,
- pci_i82559er_init,
- pci_rtl8139_init,
- pci_e1000_init,
- pci_pcnet_init,
- virtio_net_init,
+static const char * const pci_nic_names[] = {
+ "ne2k_pci",
+ "i82551",
+ "i82557b",
+ "i82559er",
+ "rtl8139",
+ "e1000",
+ "pcnet",
+ "virtio-net-pci",
NULL
};
PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
const char *default_model)
{
- PCIDevice *pci_dev;
+ DeviceState *dev;
int i;
qemu_check_nic_model_list(nd, pci_nic_models, default_model);
- for (i = 0; pci_nic_models[i]; i++)
+ for (i = 0; pci_nic_models[i]; i++) {
if (strcmp(nd->model, pci_nic_models[i]) == 0) {
- pci_dev = pci_nic_init_fns[i](bus, nd, devfn);
- if (pci_dev)
- nd->private = pci_dev;
- return pci_dev;
+ dev = qdev_create(&bus->qbus, pci_nic_names[i]);
+ qdev_set_prop_int(dev, "devfn", devfn);
+ qdev_set_netdev(dev, nd);
+ qdev_init(dev);
+ nd->private = dev;
+ return (PCIDevice *)dev;
}
+ }
return NULL;
}
s->bus = pci_register_secondary_bus(&s->dev, map_irq);
return s->bus;
}
+
+typedef struct {
+ DeviceInfo qdev;
+ pci_qdev_initfn init;
+} PCIDeviceInfo;
+
+static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+ PCIDevice *pci_dev = (PCIDevice *)qdev;
+ PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
+ PCIBus *bus;
+ int devfn;
+
+ bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
+ devfn = qdev_get_prop_int(qdev, "devfn", -1);
+ pci_dev = do_pci_register_device(pci_dev, bus, "FIXME", devfn,
+ NULL, NULL);//FIXME:config_read, config_write);
+ assert(pci_dev);
+ info->init(pci_dev);
+}
+
+void pci_qdev_register(const char *name, int size, pci_qdev_initfn init)
+{
+ PCIDeviceInfo *info;
+
+ info = qemu_mallocz(sizeof(*info));
+ info->init = init;
+ info->qdev.init = pci_qdev_init;
+ info->qdev.bus_type = BUS_TYPE_PCI;
+
+ qdev_register(name, size, &info->qdev);
+}
+
+PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(&bus->qbus, name);
+ qdev_set_prop_int(dev, "devfn", devfn);
+ qdev_init(dev);
+
+ return (PCIDevice *)dev;
+}