All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more.
@ 2009-07-10 11:26 Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann
                   ` (12 more replies)
  0 siblings, 13 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

This patch is a repost of the patch series posted last friday.

What is in there?

First the qdev property rework.  Quite big one, but as it puts the way
properties work upside down it can hardly be split into smaller pieces.
Support for property default values added since I posted it last time.
The patch description is much better too.  Otherwise it is unchanged.

The other patches are building on top of the properties.  They are a
bunch of little, self-contained and friendly patches.  They bring:

 * A new, generic -device switch to add devices to your VM.
 * Support for attaching user-specified ids to devices.
 * A few more devices being switched to qdev.

v2 brings some minor changes:

  * rebased, resolved some conflicts.
  * picked up the *_dev name convention for bus_info methods.
  * folded in the two incremental fixes posted earlier this week.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 17:13   ` Paul Brook
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 02/13] qdev: factor out driver search to qdev_find_info() Gerd Hoffmann
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch is a major overhaul of the device properties.  The properties
are saved directly in the device state struct now, the linked list of
property values is gone.

Advantages:
  * We don't have to maintain the list with the property values.
  * The value in the property list and the value actually used by
    the device can't go out of sync any more (used to happen for
    the pci.devfn == -1 case) because there is only one place where
    the value is stored.
  * A record describing the property is required now, you can't set
    random properties any more.

There are bus-specific and device-specific properties.  The former
should be used for properties common to all bus drivers.  Typical
use case is bus addressing, i.e. pci.devfn and i2c.address.

Properties have a PropertyInfo struct attached with name, size and
function pointers to parse and print properties.  A few common property
types have PropertyInfos defined in qdev-properties.c.  Drivers are free
to implement their own very special property parsers if needed.

Properties can have default values.  If unset they are zero-filled.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile              |    2 +-
 hw/arm_sysctl.c       |   20 ++++-
 hw/armv7m.c           |   22 ++++-
 hw/axis_dev88.c       |    2 +-
 hw/esp.c              |   14 ++--
 hw/etraxfs.c          |    2 +-
 hw/etraxfs_pic.c      |   18 ++++-
 hw/i2c.c              |   11 ++-
 hw/i2c.h              |    2 +-
 hw/integratorcp.c     |   30 +++++--
 hw/mips_malta.c       |    4 +-
 hw/musicpal.c         |    2 +-
 hw/pc.c               |    4 +-
 hw/pci.c              |   17 +++-
 hw/pcnet.c            |   19 ++++-
 hw/qdev-properties.c  |  207 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c             |  141 +++++----------------------------
 hw/qdev.h             |   60 ++++++++------
 hw/smbus_eeprom.c     |   10 ++-
 hw/smc91c111.c        |    2 +-
 hw/stellaris.c        |    2 +-
 hw/sun4m.c            |    3 +-
 hw/syborg.c           |    4 +-
 hw/syborg_fb.c        |   45 +++++++----
 hw/syborg_interrupt.c |   21 ++++-
 hw/syborg_keyboard.c  |   21 ++++-
 hw/syborg_pointer.c   |   29 ++++++--
 hw/syborg_serial.c    |   21 ++++-
 hw/syborg_timer.c     |   11 ++-
 hw/xilinx.h           |   12 ++--
 hw/xilinx_ethlite.c   |   29 ++++++--
 hw/xilinx_intc.c      |   18 ++++-
 hw/xilinx_timer.c     |   32 ++++++--
 33 files changed, 574 insertions(+), 263 deletions(-)
 create mode 100644 hw/qdev-properties.c

diff --git a/Makefile b/Makefile
index caf8530..a3ae99f 100644
--- a/Makefile
+++ b/Makefile
@@ -108,7 +108,7 @@ obj-y += bt-hci-csr.o
 obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
 obj-y += qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
 obj-y += msmouse.o ps2.o
-obj-y += qdev.o ssi.o
+obj-y += qdev.o qdev-properties.o ssi.o
 
 obj-$(CONFIG_BRLAPI) += baum.o
 
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index c9d1e3f..bb005c8 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -194,7 +194,6 @@ static void arm_sysctl_init1(SysBusDevice *dev)
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
     int iomemtype;
 
-    s->sys_id = qdev_get_prop_int(&dev->qdev, "sys_id", 0);
     /* The MPcore bootloader uses these flags to start secondary CPUs.
        We don't use a bootloader, so do this here.  */
     s->flags = 3;
@@ -210,15 +209,28 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "realview_sysctl");
-    qdev_set_prop_int(dev, "sys_id", sys_id);
+    qdev_prop_set_uint32(dev, "sys_id", sys_id);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 }
 
+static SysBusDeviceInfo arm_sysctl_info = {
+    .init = arm_sysctl_init1,
+    .qdev.name  = "realview_sysctl",
+    .qdev.size  = sizeof(arm_sysctl_state),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "sys_id",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(arm_sysctl_state, sys_id),
+        },
+        {/* end of list */}
+    }
+};
+
 static void arm_sysctl_register_devices(void)
 {
-    sysbus_register_dev("realview_sysctl", sizeof(arm_sysctl_state),
-                        arm_sysctl_init1);
+    sysbus_register_withprop(&arm_sysctl_info);
 }
 
 device_init(arm_sysctl_register_devices)
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 297a3e1..2e66d7e 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -127,7 +127,6 @@ static void bitband_init(SysBusDevice *dev)
     BitBandState *s = FROM_SYSBUS(BitBandState, dev);
     int iomemtype;
 
-    s->base = qdev_get_prop_int(&dev->qdev, "base", 0);
     iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
                                        &s->base);
     sysbus_init_mmio(dev, 0x02000000, iomemtype);
@@ -138,12 +137,12 @@ static void armv7m_bitband_init(void)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_set_prop_int(dev, "base", 0x20000000);
+    qdev_prop_set_uint32(dev, "base", 0x20000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
 
     dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_set_prop_int(dev, "base", 0x40000000);
+    qdev_prop_set_uint32(dev, "base", 0x40000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
 }
@@ -238,10 +237,23 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
     return pic;
 }
 
+static SysBusDeviceInfo bitband_info = {
+    .init = bitband_init,
+    .qdev.name  = "ARM,bitband-memory",
+    .qdev.size  = sizeof(BitBandState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "base",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(BitBandState, base),
+        },
+        {/* end of list */}
+    }
+};
+
 static void armv7m_register_devices(void)
 {
-    sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState),
-                        bitband_init);
+    sysbus_register_withprop(&bitband_info);
 }
 
 device_init(armv7m_register_devices)
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 79a4d71..f93f431 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -297,7 +297,7 @@ void axisdev88_init (ram_addr_t ram_size,
     cpu_irq = cris_pic_init_cpu(env);
     dev = qdev_create(NULL, "etraxfs,pic");
     /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, 0x3001c000);
diff --git a/hw/esp.c b/hw/esp.c
index 88d42a1..9eacccb 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -650,12 +650,14 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
 {
     DeviceState *dev;
     SysBusDevice *s;
+    ESPState *esp;
 
     dev = qdev_create(NULL, "esp");
-    qdev_set_prop_ptr(dev, "dma_memory_read", dma_memory_read);
-    qdev_set_prop_ptr(dev, "dma_memory_write", dma_memory_write);
-    qdev_set_prop_ptr(dev, "dma_opaque", dma_opaque);
-    qdev_set_prop_int(dev, "it_shift", it_shift);
+    esp = DO_UPCAST(ESPState, busdev.qdev, dev);
+    esp->dma_memory_read = dma_memory_read;
+    esp->dma_memory_write = dma_memory_write;
+    esp->dma_opaque = dma_opaque;
+    esp->it_shift = it_shift;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_connect_irq(s, 0, irq);
@@ -668,11 +670,7 @@ static void esp_init1(SysBusDevice *dev)
     int esp_io_memory;
 
     sysbus_init_irq(dev, &s->irq);
-    s->it_shift = qdev_get_prop_int(&dev->qdev, "it_shift", -1);
     assert(s->it_shift != -1);
-    s->dma_memory_read = qdev_get_prop_ptr(&dev->qdev, "dma_memory_read");
-    s->dma_memory_write = qdev_get_prop_ptr(&dev->qdev, "dma_memory_write");
-    s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma_opaque");
 
     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 94cd6bc..c2eca52 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -88,7 +88,7 @@ void bareetraxfs_init (ram_addr_t ram_size,
     cpu_irq = cris_pic_init_cpu(env);
     dev = qdev_create(NULL, "etraxfs,pic");
     /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, 0x3001c000);
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 1c67427..e627218 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -140,7 +140,6 @@ static void etraxfs_pic_init(SysBusDevice *dev)
     struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
     int intr_vect_regs;
 
-    s->interrupt_vector = qdev_get_prop_ptr(&dev->qdev, "interrupt_vector");
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_nmi);
@@ -149,10 +148,23 @@ static void etraxfs_pic_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
 }
 
+static SysBusDeviceInfo etraxfs_pic_info = {
+    .init = etraxfs_pic_init,
+    .qdev.name  = "etraxfs,pic",
+    .qdev.size  = sizeof(struct etrax_pic),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "interrupt_vector",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(struct etrax_pic, interrupt_vector),
+        },
+        {/* end of list */}
+    }
+};
+
 static void etraxfs_pic_register(void)
 {
-    sysbus_register_dev("etraxfs,pic", sizeof (struct etrax_pic),
-                        etraxfs_pic_init);
+    sysbus_register_withprop(&etraxfs_pic_info);
 }
 
 device_init(etraxfs_pic_register)
diff --git a/hw/i2c.c b/hw/i2c.c
index 98aa7fc..42a5d7a 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -20,6 +20,14 @@ struct i2c_bus
 static struct BusInfo i2c_bus_info = {
     .name = "I2C",
     .size = sizeof(i2c_bus),
+    .props = (Property[]) {
+        {
+            .name   = "address",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct i2c_slave, address),
+        },
+        {/* end of list */}
+    }
 };
 
 static void i2c_bus_save(QEMUFile *f, void *opaque)
@@ -151,7 +159,6 @@ static void i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base)
     i2c_slave *s = I2C_SLAVE_FROM_QDEV(dev);
 
     s->info = info;
-    s->address = qdev_get_prop_int(dev, "address", 0);
 
     info->init(s);
 }
@@ -169,7 +176,7 @@ DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, int addr)
     DeviceState *dev;
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_set_prop_int(dev, "address", addr);
+    qdev_prop_set_uint32(dev, "address", addr);
     qdev_init(dev);
     return dev;
 }
diff --git a/hw/i2c.h b/hw/i2c.h
index c4df399..479ff4b 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -40,7 +40,7 @@ struct i2c_slave
     I2CSlaveInfo *info;
 
     /* Remaining fields for internal use by the I2C code.  */
-    int address;
+    uint32_t address;
 };
 
 i2c_bus *i2c_init_bus(DeviceState *parent, const char *name);
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 50eae0c..ddc8d85 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -17,6 +17,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    uint32_t memsz;
     uint32_t flash_offset;
     uint32_t cm_osc;
     uint32_t cm_ctrl;
@@ -230,23 +231,21 @@ static void integratorcm_init(SysBusDevice *dev)
 {
     int iomemtype;
     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
-    int memsz;
 
-    memsz = qdev_get_prop_int(&dev->qdev, "memsz", 0);
     s->cm_osc = 0x01000048;
     /* ??? What should the high bits of this value be?  */
     s->cm_auxosc = 0x0007feff;
     s->cm_sdram = 0x00011122;
-    if (memsz >= 256) {
+    if (s->memsz >= 256) {
         integrator_spd[31] = 64;
         s->cm_sdram |= 0x10;
-    } else if (memsz >= 128) {
+    } else if (s->memsz >= 128) {
         integrator_spd[31] = 32;
         s->cm_sdram |= 0x0c;
-    } else if (memsz >= 64) {
+    } else if (s->memsz >= 64) {
         integrator_spd[31] = 16;
         s->cm_sdram |= 0x08;
-    } else if (memsz >= 32) {
+    } else if (s->memsz >= 32) {
         integrator_spd[31] = 4;
         s->cm_sdram |= 0x04;
     } else {
@@ -475,7 +474,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM);
 
     dev = qdev_create(NULL, "integrator_core");
-    qdev_set_prop_int(dev, "memsz", ram_size >> 20);
+    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
     qdev_init(dev);
     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
 
@@ -522,11 +521,24 @@ static void integratorcp_machine_init(void)
 
 machine_init(integratorcp_machine_init);
 
+static SysBusDeviceInfo core_info = {
+    .init = integratorcm_init,
+    .qdev.name  = "integrator_core",
+    .qdev.size  = sizeof(integratorcm_state),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "memsz",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(integratorcm_state, memsz),
+        },
+        {/* end of list */}
+    }
+};
+
 static void integratorcp_register_devices(void)
 {
     sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
-    sysbus_register_dev("integrator_core", sizeof(integratorcm_state),
-                        integratorcm_init);
+    sysbus_register_withprop(&core_info);
 }
 
 device_init(integratorcp_register_devices)
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 853ec2b..7728e58 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -914,8 +914,8 @@ void mips_malta_init (ram_addr_t ram_size,
         /* TODO: Populate SPD eeprom data.  */
         DeviceState *eeprom;
         eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-        qdev_set_prop_int(eeprom, "address", 0x50 + i);
-        qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
+        qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
         qdev_init(eeprom);
     }
     pit = pit_init(0x40, i8259[0]);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 10be69b..e636791 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1578,7 +1578,7 @@ static void musicpal_init(ram_addr_t ram_size,
 
     qemu_check_nic_model(&nd_table[0], "mv88w8618");
     dev = qdev_create(NULL, "mv88w8618_eth");
-    qdev_set_netdev(dev, &nd_table[0]);
+    dev->nd = &nd_table[0];
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, MP_ETH_BASE);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[MP_ETH_IRQ]);
diff --git a/hw/pc.c b/hw/pc.c
index 553ba5c..bdcec52 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1374,8 +1374,8 @@ static void pc_init1(ram_addr_t ram_size,
         for (i = 0; i < 8; i++) {
             DeviceState *eeprom;
             eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-            qdev_set_prop_int(eeprom, "address", 0x50 + i);
-            qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
+            qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
             qdev_init(eeprom);
         }
     }
diff --git a/hw/pci.c b/hw/pci.c
index 71d9227..73f2a4b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -54,6 +54,15 @@ static struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
+    .props      = (Property[]) {
+        {
+            .name   = "devfn",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(PCIDevice, devfn),
+            .defval = (uint32_t[]) { -1 },
+        },
+        {/* end of list */}
+    }
 };
 
 static void pci_update_mappings(PCIDevice *d);
@@ -769,7 +778,7 @@ PCIDevice *pci_create(const char *name, const char *devaddr)
     }
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_set_prop_int(dev, "devfn", devfn);
+    qdev_prop_set_uint32(dev, "devfn", devfn);
     return (PCIDevice *)dev;
 }
 
@@ -812,7 +821,7 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
         if (strcmp(nd->model, pci_nic_models[i]) == 0) {
             pci_dev = pci_create(pci_nic_names[i], devaddr);
             dev = &pci_dev->qdev;
-            qdev_set_netdev(dev, nd);
+            dev->nd = nd;
             qdev_init(dev);
             nd->private = dev;
             return pci_dev;
@@ -890,7 +899,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     int devfn;
 
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
-    devfn = qdev_get_prop_int(qdev, "devfn", -1);
+    devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
                                      info->config_read, info->config_write);
     assert(pci_dev);
@@ -917,7 +926,7 @@ 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_prop_set_uint32(dev, "devfn", devfn);
     qdev_init(dev);
 
     return (PCIDevice *)dev;
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 4519780..22ab6be 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2128,8 +2128,6 @@ static void lance_init(SysBusDevice *dev)
     s->mmio_index =
         cpu_register_io_memory(lance_mem_read, lance_mem_write, d);
 
-    s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma");
-
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
     sysbus_init_mmio(dev, 4, s->mmio_index);
@@ -2141,6 +2139,21 @@ static void lance_init(SysBusDevice *dev)
 
     pcnet_common_init(&dev->qdev, s, lance_cleanup);
 }
+
+static SysBusDeviceInfo lance_info = {
+    .init = lance_init,
+    .qdev.name  = "lance",
+    .qdev.size  = sizeof(SysBusPCNetState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "dma",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(SysBusPCNetState, state.dma_opaque),
+        },
+        {/* end of list */}
+    }
+};
+
 #endif /* TARGET_SPARC */
 
 static PCIDeviceInfo pcnet_info = {
@@ -2153,7 +2166,7 @@ static void pcnet_register_devices(void)
 {
     pci_qdev_register(&pcnet_info);
 #if defined (TARGET_SPARC) && !defined(TARGET_SPARC64)
-    sysbus_register_dev("lance", sizeof(SysBusPCNetState), lance_init);
+    sysbus_register_withprop(&lance_info);
 #endif
 }
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
new file mode 100644
index 0000000..b4f4f21
--- /dev/null
+++ b/hw/qdev-properties.c
@@ -0,0 +1,207 @@
+#include "qdev.h"
+
+static void *prop_ptr(DeviceState *dev, Property *prop)
+{
+    void *ptr = dev;
+    ptr += prop->offset;
+    return ptr;
+}
+
+/* --- 32bit integer --- */
+
+static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIu32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "%" PRIu32, *ptr);
+}
+
+PropertyInfo qdev_prop_uint32 = {
+    .name  = "uint32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_uint32,
+    .print = print_uint32,
+};
+
+/* --- 32bit hex value --- */
+
+static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIx32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x%" PRIx32, *ptr);
+}
+
+PropertyInfo qdev_prop_hex32 = {
+    .name  = "hex32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_hex32,
+    .print = print_hex32,
+};
+
+/* --- pointer --- */
+
+static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    void **ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "<%p>", *ptr);
+}
+
+PropertyInfo qdev_prop_ptr = {
+    .name  = "ptr",
+    .size  = sizeof(void*),
+    .print = print_ptr,
+};
+
+/* --- mac address --- */
+
+/*
+ * accepted syntax versions:
+ *   01:02:03:04:05:06
+ *   01-02-03-04-05-06
+ */
+static int parse_mac(DeviceState *dev, Property *prop, const char *str)
+{
+    uint8_t *mac = prop_ptr(dev, prop);
+    int i, pos;
+    char *p;
+
+    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
+        if (!isxdigit(str[pos]))
+            return -1;
+        if (!isxdigit(str[pos+1]))
+            return -1;
+        if (i == 5 && str[pos+2] != '\0')
+            return -1;
+        if (str[pos+2] != ':' && str[pos+2] != '-')
+            return -1;
+        mac[i] = strtol(str+pos, &p, 16);
+    }
+    return 0;
+}
+
+static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint8_t *mac = prop_ptr(dev, prop);
+    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
+                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+PropertyInfo qdev_prop_mac = {
+    .name  = "mac",
+    .size  = 6,
+    .parse = parse_mac,
+    .print = print_mac,
+};
+
+/* --- public helpers --- */
+
+static Property *qdev_prop_walk(Property *props, const char *name)
+{
+    if (!props)
+        return NULL;
+    while (props->name) {
+        if (strcmp(props->name, name) == 0)
+            return props;
+        props++;
+    }
+    return NULL;
+}
+
+static Property *qdev_prop_find(DeviceState *dev, const char *name)
+{
+    Property *prop;
+
+    /* device properties */
+    prop = qdev_prop_walk(dev->info->props, name);
+    if (prop)
+        return prop;
+
+    /* bus properties */
+    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
+    if (prop)
+        return prop;
+
+    return NULL;
+}
+
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
+{
+    Property *prop;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (!prop->info->parse) {
+        fprintf(stderr, "property \"%s.%s\" has no parser\n",
+                dev->info->name, name);
+        return -1;
+    }
+    return prop->info->parse(dev, prop, value);
+}
+
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size)
+{
+    Property *prop;
+    void *dst;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (prop->info->size != size) {
+        fprintf(stderr, "property \"%s.%s\" size mismatch (%zd / %zd)\n",
+                dev->info->name, name, prop->info->size, size);
+        return -1;
+    }
+    dst = prop_ptr(dev, prop);
+    memcpy(dst, src, size);
+    return 0;
+}
+
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
+{
+    return qdev_prop_set(dev, name, &value, sizeof(value));
+}
+
+int qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
+{
+    return qdev_prop_set(dev, name, &value, sizeof(value));
+}
+
+void qdev_prop_set_defaults(DeviceState *dev, Property *props)
+{
+    char *dst;
+
+    if (!props)
+        return;
+    while (props->name) {
+        if (props->defval) {
+            dst = prop_ptr(dev, props);
+            memcpy(dst, props->defval, props->info->size);
+        }
+        props++;
+    }
+}
+
diff --git a/hw/qdev.c b/hw/qdev.c
index 83e98bf..9912bd9 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -31,16 +31,6 @@
 #include "sysemu.h"
 #include "monitor.h"
 
-struct DeviceProperty {
-    const char *name;
-    DevicePropType type;
-    union {
-        uint64_t i;
-        void *ptr;
-    } value;
-    DeviceProperty *next;
-};
-
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 static BusState *main_system_bus;
 extern struct BusInfo system_bus_info;
@@ -86,6 +76,8 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     dev = qemu_mallocz(info->size);
     dev->info = info;
     dev->parent_bus = bus;
+    qdev_prop_set_defaults(dev, dev->info->props);
+    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
     LIST_INSERT_HEAD(&bus->children, dev, sibling);
     return dev;
 }
@@ -105,52 +97,6 @@ void qdev_free(DeviceState *dev)
     free(dev);
 }
 
-static DeviceProperty *create_prop(DeviceState *dev, const char *name,
-                                   DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    /* TODO: Check for duplicate properties.  */
-    prop = qemu_mallocz(sizeof(*prop));
-    prop->name = qemu_strdup(name);
-    prop->type = type;
-    prop->next = dev->props;
-    dev->props = prop;
-
-    return prop;
-}
-
-void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_INT);
-    prop->value.i = value;
-}
-
-void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_DEV);
-    prop->value.ptr = value;
-}
-
-void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_PTR);
-    prop->value.ptr = value;
-}
-
-void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
-{
-    assert(!dev->nd);
-    dev->nd = nd;
-}
-
-
 /* Get a character (serial) device interface.  */
 CharDriverState *qdev_init_chardev(DeviceState *dev)
 {
@@ -169,52 +115,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
     return dev->parent_bus;
 }
 
-static DeviceProperty *find_prop(DeviceState *dev, const char *name,
-                                 DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    for (prop = dev->props; prop; prop = prop->next) {
-        if (strcmp(prop->name, name) == 0) {
-            assert (prop->type == type);
-            return prop;
-        }
-    }
-    return NULL;
-}
-
-uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_INT);
-    if (!prop) {
-        return def;
-    }
-
-    return prop->value.i;
-}
-
-void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_PTR);
-    assert(prop);
-    return prop->value.ptr;
-}
-
-DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_DEV);
-    if (!prop) {
-        return NULL;
-    }
-    return prop->value.ptr;
-}
-
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
 {
     assert(dev->num_gpio_in == 0);
@@ -327,9 +227,24 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
 static void qbus_print(Monitor *mon, BusState *bus, int indent);
 
+static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
+                             const char *prefix, int indent)
+{
+    char buf[64];
+
+    if (!props)
+        return;
+    while (props->name) {
+        if (props->info->print) {
+            props->info->print(dev, props, buf, sizeof(buf));
+            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
+        }
+        props++;
+    }
+}
+
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 {
-    DeviceProperty *prop;
     BusState *child;
     qdev_printf("dev: %s\n", dev->info->name);
     indent += 2;
@@ -339,24 +254,8 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
     if (dev->num_gpio_out) {
         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
     }
-    for (prop = dev->props; prop; prop = prop->next) {
-        switch (prop->type) {
-        case PROP_TYPE_INT:
-            qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
-                        prop->value.i);
-            break;
-        case PROP_TYPE_PTR:
-            qdev_printf("prop-ptr %s\n", prop->name);
-            break;
-        case PROP_TYPE_DEV:
-            qdev_printf("prop-dev %s %s\n", prop->name,
-                        ((DeviceState *)prop->value.ptr)->info->name);
-            break;
-        default:
-            qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
-            break;
-        }
-    }
+    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
+    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
     if (dev->parent_bus->info->print_dev)
         dev->parent_bus->info->print_dev(mon, dev, indent);
     LIST_FOREACH(child, &dev->child_bus, sibling) {
diff --git a/hw/qdev.h b/hw/qdev.h
index b18dbf9..64e9b75 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -4,9 +4,11 @@
 #include "hw.h"
 #include "sys-queue.h"
 
-typedef struct DeviceInfo DeviceInfo;
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
 
-typedef struct DeviceProperty DeviceProperty;
+typedef struct DeviceInfo DeviceInfo;
 
 typedef struct BusState BusState;
 
@@ -17,7 +19,6 @@ typedef struct BusInfo BusInfo;
 struct DeviceState {
     DeviceInfo *info;
     BusState *parent_bus;
-    DeviceProperty *props;
     int num_gpio_out;
     qemu_irq *gpio_out;
     int num_gpio_in;
@@ -32,6 +33,7 @@ struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    Property *props;
 };
 
 struct BusState {
@@ -42,18 +44,26 @@ struct BusState {
     LIST_ENTRY(BusState) sibling;
 };
 
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+    void         *defval;
+};
+
+struct PropertyInfo {
+    const char *name;
+    size_t size;
+    int (*parse)(DeviceState *dev, Property *prop, const char *str);
+    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+};
+
 /*** Board API.  This should go away once we have a machine config file.  ***/
 
 DeviceState *qdev_create(BusState *bus, const char *name);
 void qdev_init(DeviceState *dev);
 void qdev_free(DeviceState *dev);
 
-/* Set properties between creation and init.  */
-void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value);
-void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value);
-void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value);
-void qdev_set_netdev(DeviceState *dev, NICInfo *nd);
-
 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
 void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
 
@@ -61,17 +71,6 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
 /*** Device API.  ***/
 
-typedef enum {
-    PROP_TYPE_INT,
-    PROP_TYPE_PTR,
-    PROP_TYPE_DEV
-} DevicePropType;
-
-typedef struct {
-    const char *name;
-    DevicePropType type;
-} DevicePropList;
-
 typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
 typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
               int unit);
@@ -79,7 +78,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
 struct DeviceInfo {
     const char *name;
     size_t size;
-    DevicePropList *props;
+    Property *props;
 
     /* Private to qdev / bus.  */
     qdev_initfn init;
@@ -99,10 +98,6 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach);
 CharDriverState *qdev_init_chardev(DeviceState *dev);
 
 BusState *qdev_get_parent_bus(DeviceState *dev);
-uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def);
-DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name);
-/* FIXME: Remove opaque pointer properties.  */
-void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
 
 /* Convery from a base type to a parent type, with compile time checking.  */
 #ifdef __GNUC__
@@ -124,4 +119,19 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
 
 void do_info_qtree(Monitor *mon);
 
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_mac;
+
+/* Set properties between creation and init.  */
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size);
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+/* FIXME: Remove opaque pointer properties.  */
+int qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+void qdev_prop_set_defaults(DeviceState *dev, Property *props);
+
 #endif
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 05a70d9..c071fb1 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -99,14 +99,20 @@ static void smbus_eeprom_init(SMBusDevice *dev)
 {
     SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev;
 
-    /* FIXME: Should be a blob rather than a ptr.  */
-    eeprom->data = qdev_get_prop_ptr(&dev->i2c.qdev, "data");
     eeprom->offset = 0;
 }
 
 static SMBusDeviceInfo smbus_eeprom_info = {
     .i2c.qdev.name = "smbus-eeprom",
     .i2c.qdev.size = sizeof(SMBusEEPROMDevice),
+    .i2c.qdev.props = (Property[]) {
+        {
+            .name   = "data",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(SMBusEEPROMDevice, data),
+        },
+        {/* end of list */}
+    },
     .init = smbus_eeprom_init,
     .quick_cmd = eeprom_quick_cmd,
     .send_byte = eeprom_send_byte,
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index cf8d864..5f6956a 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -733,7 +733,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
 
     qemu_check_nic_model(nd, "smc91c111");
     dev = qdev_create(NULL, "smc91c111");
-    qdev_set_netdev(dev, nd);
+    dev->nd = nd;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, base);
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5f44bff..d9434ca 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1378,7 +1378,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         qemu_check_nic_model(&nd_table[0], "stellaris");
 
         enet = qdev_create(NULL, "stellaris_enet");
-        qdev_set_netdev(enet, &nd_table[0]);
+        enet->nd = &nd_table[0];
         qdev_init(enet);
         sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000);
         sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index c67bf0b..0805f6e 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -373,8 +373,7 @@ static void lance_init(NICInfo *nd, target_phys_addr_t leaddr,
     qemu_check_nic_model(&nd_table[0], "lance");
 
     dev = qdev_create(NULL, "lance");
-    qdev_set_netdev(dev, nd);
-    qdev_set_prop_ptr(dev, "dma", dma_opaque);
+    dev->nd = nd;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, leaddr);
diff --git a/hw/syborg.c b/hw/syborg.c
index 5ca9977..d8d38d4 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -64,7 +64,7 @@ static void syborg_init(ram_addr_t ram_size,
     sysbus_create_simple("syborg,rtc", 0xC0001000, NULL);
 
     dev = qdev_create(NULL, "syborg,timer");
-    qdev_set_prop_int(dev, "frequency", 1000000);
+    qdev_prop_set_uint32(dev, "frequency", 1000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]);
@@ -83,7 +83,7 @@ static void syborg_init(ram_addr_t ram_size,
 
         qemu_check_nic_model(&nd_table[0], "virtio");
         dev = qdev_create(NULL, "syborg,virtio-net");
-        qdev_set_netdev(dev, &nd_table[0]);
+        dev->nd = &nd_table[0];
         qdev_init(dev);
         s = sysbus_from_qdev(dev);
         sysbus_mmio_map(s, 0, 0xc000c000);
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 42c6274..2929ffd 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -76,8 +76,8 @@ typedef struct {
 
     uint32_t base;
     uint32_t pitch;
-    int rows;
-    int cols;
+    uint32_t rows;
+    uint32_t cols;
     int blank;
     int bpp;
     int rgb; /* 0 = BGR, 1 = RGB */
@@ -507,41 +507,50 @@ static void syborg_fb_init(SysBusDevice *dev)
 {
     SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
     int iomemtype;
-    int width;
-    int height;
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_fb_readfn,
                                        syborg_fb_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-    width = qdev_get_prop_int(&dev->qdev, "width", 0);
-    height = qdev_get_prop_int(&dev->qdev, "height", 0);
-
     s->ds = graphic_console_init(syborg_fb_update_display,
                                  syborg_fb_invalidate_display,
                                  NULL, NULL, s);
 
-    if (width != 0 && height != 0) {
-        qemu_console_resize(s->ds, width, height);
+    if (s->cols != 0 && s->rows != 0) {
+        qemu_console_resize(s->ds, s->cols, s->rows);
     }
 
-    if (!width)
-        width = ds_get_width(s->ds);
-    if (!height)
-        height = ds_get_height(s->ds);
-
-    s->cols = width;
-    s->rows = height;
+    if (!s->cols)
+        s->cols = ds_get_width(s->ds);
+    if (!s->rows)
+        s->rows = ds_get_height(s->ds);
 
     register_savevm("syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
 }
 
+static SysBusDeviceInfo syborg_fb_info = {
+    .init = syborg_fb_init,
+    .qdev.name  = "syborg,framebuffer",
+    .qdev.size  = sizeof(SyborgFBState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "width",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgFBState, cols),
+        },{
+            .name   = "height",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgFBState, rows),
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_fb_register_devices(void)
 {
-    sysbus_register_dev("syborg,framebuffer", sizeof(SyborgFBState),
-                        syborg_fb_init);
+    sysbus_register_withprop(&syborg_fb_info);
 }
 
 device_init(syborg_fb_register_devices)
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 569c7f6..a372ec1 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -56,7 +56,7 @@ typedef struct {
 typedef struct {
     SysBusDevice busdev;
     int pending_count;
-    int num_irqs;
+    uint32_t num_irqs;
     syborg_int_flags *flags;
     qemu_irq parent_irq;
 } SyborgIntState;
@@ -208,7 +208,6 @@ static void syborg_int_init(SysBusDevice *dev)
     int iomemtype;
 
     sysbus_init_irq(dev, &s->parent_irq);
-    s->num_irqs = qdev_get_prop_int(&dev->qdev, "num-interrupts", 64);
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
     iomemtype = cpu_register_io_memory(syborg_int_readfn,
                                        syborg_int_writefn, s);
@@ -218,10 +217,24 @@ static void syborg_int_init(SysBusDevice *dev)
     register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
 }
 
+static SysBusDeviceInfo syborg_int_info = {
+    .init = syborg_int_init,
+    .qdev.name  = "syborg,interrupt",
+    .qdev.size  = sizeof(SyborgIntState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "num-interrupts",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgIntState, num_irqs),
+            .defval = (uint32_t[]) { 64 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_interrupt_register_devices(void)
 {
-    sysbus_register_dev("syborg,interrupt", sizeof(SyborgIntState),
-                        syborg_int_init);
+    sysbus_register_withprop(&syborg_int_info);
 }
 
 device_init(syborg_interrupt_register_devices)
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 84a099e..ffc85a5 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -53,7 +53,7 @@ typedef struct {
     SysBusDevice busdev;
     int int_enabled;
     int extension_bit;
-    int fifo_size;
+    uint32_t fifo_size;
     uint32_t *key_fifo;
     int read_pos, read_count;
     qemu_irq irq;
@@ -212,7 +212,6 @@ static void syborg_keyboard_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
                                        syborg_keyboard_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
         s->fifo_size = 16;
@@ -225,10 +224,24 @@ static void syborg_keyboard_init(SysBusDevice *dev)
                     syborg_keyboard_save, syborg_keyboard_load, s);
 }
 
+static SysBusDeviceInfo syborg_keyboard_info = {
+    .init = syborg_keyboard_init,
+    .qdev.name  = "syborg,keyboard",
+    .qdev.size  = sizeof(SyborgKeyboardState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgKeyboardState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_keyboard_register_devices(void)
 {
-    sysbus_register_dev("syborg,keyboard", sizeof(SyborgKeyboardState),
-                        syborg_keyboard_init);
+    sysbus_register_withprop(&syborg_keyboard_info);
 }
 
 device_init(syborg_keyboard_register_devices)
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index e0a892d..edd1f22 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -45,11 +45,11 @@ typedef struct {
 typedef struct {
     SysBusDevice busdev;
     int int_enabled;
-    int fifo_size;
+    uint32_t fifo_size;
     event_data *event_fifo;
     int read_pos, read_count;
     qemu_irq irq;
-    int absolute;
+    uint32_t absolute;
 } SyborgPointerState;
 
 static void syborg_pointer_update(SyborgPointerState *s)
@@ -209,8 +209,6 @@ static void syborg_pointer_init(SysBusDevice *dev)
 				       syborg_pointer_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-    s->absolute = qdev_get_prop_int(&dev->qdev, "absolute", 1);
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_pointer: fifo too small\n");
         s->fifo_size = 16;
@@ -224,10 +222,29 @@ static void syborg_pointer_init(SysBusDevice *dev)
                     syborg_pointer_save, syborg_pointer_load, s);
 }
 
+static SysBusDeviceInfo syborg_pointer_info = {
+    .init = syborg_pointer_init,
+    .qdev.name  = "syborg,pointer",
+    .qdev.size  = sizeof(SyborgPointerState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgPointerState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },{
+            .name   = "absolute",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgPointerState, absolute),
+            .defval = (uint32_t[]) { 1 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_pointer_register_devices(void)
 {
-    sysbus_register_dev("syborg,pointer", sizeof(SyborgPointerState),
-                        syborg_pointer_init);
+    sysbus_register_withprop(&syborg_pointer_info);
 }
 
 device_init(syborg_pointer_register_devices)
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index f430508..f693421 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -59,7 +59,7 @@ enum {
 typedef struct {
     SysBusDevice busdev;
     uint32_t int_enable;
-    int fifo_size;
+    uint32_t fifo_size;
     uint32_t *read_fifo;
     int read_pos;
     int read_count;
@@ -329,7 +329,6 @@ static void syborg_serial_init(SysBusDevice *dev)
         qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
                               syborg_serial_receive, syborg_serial_event, s);
     }
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_serial: fifo too small\n");
         s->fifo_size = 16;
@@ -340,10 +339,24 @@ static void syborg_serial_init(SysBusDevice *dev)
                     syborg_serial_save, syborg_serial_load, s);
 }
 
+static SysBusDeviceInfo syborg_serial_info = {
+    .init = syborg_serial_init,
+    .qdev.name  = "syborg,serial",
+    .qdev.size  = sizeof(SyborgSerialState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgSerialState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_serial_register_devices(void)
 {
-    sysbus_register_dev("syborg,serial", sizeof(SyborgSerialState),
-                        syborg_serial_init);
+    sysbus_register_withprop(&syborg_serial_info);
 }
 
 device_init(syborg_serial_register_devices)
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 4f5e3a1..cf96c5f 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -209,7 +209,6 @@ static void syborg_timer_init(SysBusDevice *dev)
     QEMUBH *bh;
     int iomemtype;
 
-    s->freq = qdev_get_prop_int(&dev->qdev, "frequency", 0);
     if (s->freq == 0) {
         fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
         exit(1);
@@ -230,9 +229,13 @@ static SysBusDeviceInfo syborg_timer_info = {
     .init = syborg_timer_init,
     .qdev.name  = "syborg,timer",
     .qdev.size  = sizeof(SyborgTimerState),
-    .qdev.props = (DevicePropList[]) {
-        {.name = "frequency", .type = PROP_TYPE_INT},
-        {.name = NULL}
+    .qdev.props = (Property[]) {
+        {
+            .name   = "frequency",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgTimerState, freq),
+        },
+        {/* end of list */}
     }
 };
 
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 9707a0e..070679c 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -8,7 +8,7 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "xilinx,intc");
-    qdev_set_prop_int(dev, "kind-of-intr", kind_of_intr);
+    qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -22,8 +22,8 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int nr, int freq)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "xilinx,timer");
-    qdev_set_prop_int(dev, "nr-timers", nr);
-    qdev_set_prop_int(dev, "frequency", freq);
+    qdev_prop_set_uint32(dev, "nr-timers", nr);
+    qdev_prop_set_uint32(dev, "frequency", freq);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -40,9 +40,9 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
     qemu_check_nic_model(nd, "xilinx-ethlite");
 
     dev = qdev_create(NULL, "xilinx,ethlite");
-    qdev_set_netdev(dev, nd);
-    qdev_set_prop_int(dev, "txpingpong", txpingpong);
-    qdev_set_prop_int(dev, "rxpingpong", rxpingpong);
+    dev->nd = nd;
+    qdev_prop_set_uint32(dev, "txpingpong", txpingpong);
+    qdev_prop_set_uint32(dev, "rxpingpong", rxpingpong);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index f4b40c7..b3fd25b 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -53,8 +53,8 @@ struct xlx_ethlite
     qemu_irq irq;
     VLANClientState *vc;
 
-    unsigned int c_tx_pingpong;
-    unsigned int c_rx_pingpong;
+    uint32_t c_tx_pingpong;
+    uint32_t c_rx_pingpong;
     unsigned int txbuf;
     unsigned int rxbuf;
 
@@ -213,8 +213,6 @@ static void xilinx_ethlite_init(SysBusDevice *dev)
     int regs;
 
     sysbus_init_irq(dev, &s->irq);
-    s->c_tx_pingpong = qdev_get_prop_int(&dev->qdev, "txpingpong", 1);
-    s->c_rx_pingpong = qdev_get_prop_int(&dev->qdev, "rxpingpong", 1);
     s->rxbuf = 0;
 
     regs = cpu_register_io_memory(eth_read, eth_write, s);
@@ -225,10 +223,29 @@ static void xilinx_ethlite_init(SysBusDevice *dev)
                                  eth_can_rx, eth_rx, NULL, eth_cleanup, s);
 }
 
+static SysBusDeviceInfo xilinx_ethlite_info = {
+    .init = xilinx_ethlite_init,
+    .qdev.name  = "xilinx,ethlite",
+    .qdev.size  = sizeof(struct xlx_ethlite),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "txpingpong",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_ethlite, c_tx_pingpong),
+            .defval = (uint32_t[]) { 1 },
+        },{
+            .name   = "rxpingpong",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_ethlite, c_rx_pingpong),
+            .defval = (uint32_t[]) { 1 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_ethlite_register(void)
 {
-    sysbus_register_dev("xilinx,ethlite", sizeof (struct xlx_ethlite),
-                        xilinx_ethlite_init);
+    sysbus_register_withprop(&xilinx_ethlite_info);
 }
 
 device_init(xilinx_ethlite_register)
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 0540f52..3f08bf8 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -150,7 +150,6 @@ static void xilinx_intc_init(SysBusDevice *dev)
     struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev);
     int pic_regs;
 
-    p->c_kind_of_intr = qdev_get_prop_int(&dev->qdev, "kind-of-intr", 0);
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &p->parent_irq);
 
@@ -158,10 +157,23 @@ static void xilinx_intc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, R_MAX * 4, pic_regs);
 }
 
+static SysBusDeviceInfo xilinx_intc_info = {
+    .init = xilinx_intc_init,
+    .qdev.name  = "xilinx,intc",
+    .qdev.size  = sizeof(struct xlx_pic),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "kind-of-intr",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_pic, c_kind_of_intr),
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_intc_register(void)
 {
-    sysbus_register_dev("xilinx,intc", sizeof (struct xlx_pic),
-                        xilinx_intc_init);
+    sysbus_register_withprop(&xilinx_intc_info);
 }
 
 device_init(xilinx_intc_register)
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index a64ad2d..efb6a04 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -61,7 +61,8 @@ struct timerblock
 {
     SysBusDevice busdev;
     qemu_irq irq;
-    unsigned int nr_timers;
+    uint32_t nr_timers;
+    uint32_t freq_hz;
     struct xlx_timer *timers;
 };
 
@@ -192,14 +193,12 @@ static void xilinx_timer_init(SysBusDevice *dev)
 {
     struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
     unsigned int i;
-    int timer_regs, freq_hz;
+    int timer_regs;
 
     /* All timers share a single irq line.  */
     sysbus_init_irq(dev, &t->irq);
 
     /* Init all the ptimers.  */
-    freq_hz = qdev_get_prop_int(&dev->qdev, "frequency", 2);
-    t->nr_timers = qdev_get_prop_int(&dev->qdev, "nr-timers", 2);
     t->timers = qemu_mallocz(sizeof t->timers[0] * t->nr_timers);
     for (i = 0; i < t->nr_timers; i++) {
         struct xlx_timer *xt = &t->timers[i];
@@ -208,17 +207,36 @@ static void xilinx_timer_init(SysBusDevice *dev)
         xt->nr = i;
         xt->bh = qemu_bh_new(timer_hit, xt);
         xt->ptimer = ptimer_init(xt->bh);
-        ptimer_set_freq(xt->ptimer, freq_hz);
+        ptimer_set_freq(xt->ptimer, t->freq_hz);
     }
 
     timer_regs = cpu_register_io_memory(timer_read, timer_write, t);
     sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs);
 }
 
+static SysBusDeviceInfo xilinx_timer_info = {
+    .init = xilinx_timer_init,
+    .qdev.name  = "xilinx,timer",
+    .qdev.size  = sizeof(struct timerblock),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "frequency",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct timerblock, freq_hz),
+            .defval = (uint32_t[]) { 2 },
+        },{
+            .name   = "nr-timers",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct timerblock, nr_timers),
+            .defval = (uint32_t[]) { 2 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_timer_register(void)
 {
-    sysbus_register_dev("xilinx,timer", sizeof (struct timerblock),
-                        xilinx_timer_init);
+    sysbus_register_withprop(&xilinx_timer_info);
 }
 
 device_init(xilinx_timer_register)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 02/13] qdev: factor out driver search to qdev_find_info()
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 03/13] qdev/pci: make pci_create return DeviceState instead of PCIDevice Gerd Hoffmann
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/qdev.c |   22 +++++++++++++++-------
 1 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index 9912bd9..644a5be 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -47,6 +47,20 @@ void qdev_register(DeviceInfo *info)
     device_info_list = info;
 }
 
+static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
+{
+    DeviceInfo *info;
+
+    for (info = device_info_list; info != NULL; info = info->next) {
+        if (bus_info && info->bus_info != bus_info)
+            continue;
+        if (strcmp(info->name, name) != 0)
+            continue;
+        return info;
+    }
+    return NULL;
+}
+
 /* Create a new device.  This only initializes the device state structure
    and allows properties to be set.  qdev_init should be called to
    initialize the actual device emulation.  */
@@ -62,13 +76,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
         bus = main_system_bus;
     }
 
-    for (info = device_info_list; info != NULL; info = info->next) {
-        if (info->bus_info != bus->info)
-            continue;
-        if (strcmp(info->name, name) != 0)
-            continue;
-        break;
-    }
+    info = qdev_find_info(bus->info, name);
     if (!info) {
         hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
     }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 03/13] qdev/pci: make pci_create return DeviceState instead of PCIDevice.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 02/13] qdev: factor out driver search to qdev_find_info() Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add() Gerd Hoffmann
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Rationale: wanna use it as callback in qdev code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pc.c                |   12 ++++++------
 hw/pci-hotplug.c       |    6 +++---
 hw/pci.c               |   10 ++++------
 hw/pci.h               |    2 +-
 hw/ppc440_bamboo.c     |    6 +++---
 hw/ppce500_mpc8544ds.c |    6 +++---
 6 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index bdcec52..2b89356 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1094,7 +1094,7 @@ static void pc_init1(ram_addr_t ram_size,
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     int bios_size, isa_bios_size, oprom_area_size;
     PCIBus *pci_bus;
-    PCIDevice *pci_dev;
+    DeviceState *qdev;
     int piix3_devfn = -1;
     CPUState *env;
     qemu_irq *cpu_irq;
@@ -1400,17 +1400,17 @@ static void pc_init1(ram_addr_t ram_size,
         int unit_id = 0;
 
         while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
-            pci_dev = pci_create("virtio-blk-pci",
-                                 drives_table[index].devaddr);
-            qdev_init(&pci_dev->qdev);
+            qdev = pci_create("virtio-blk-pci",
+                              drives_table[index].devaddr);
+            qdev_init(qdev);
             unit_id++;
         }
     }
 
     /* Add virtio balloon device */
     if (pci_enabled && virtio_balloon) {
-        pci_dev = pci_create("virtio-balloon-pci", virtio_balloon_devaddr);
-        qdev_init(&pci_dev->qdev);
+        qdev = pci_create("virtio-balloon-pci", virtio_balloon_devaddr);
+        qdev_init(qdev);
     }
 
     /* Add virtio console devices */
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index d0f2911..0781b52 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -97,7 +97,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
                                            const char *devaddr,
                                            const char *opts)
 {
-    PCIDevice *dev;
+    DeviceState *dev;
     int type = -1, drive_idx = -1;
     char buf[128];
 
@@ -139,8 +139,8 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
         dev = NULL;
     }
     if (dev)
-        qdev_init(&dev->qdev);
-    return dev;
+        qdev_init(dev);
+    return DO_UPCAST(PCIDevice, qdev, dev);
 }
 
 void pci_device_hot_add(Monitor *mon, const char *pci_addr, const char *type,
diff --git a/hw/pci.c b/hw/pci.c
index 73f2a4b..a52fe3a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -764,7 +764,7 @@ void pci_info(Monitor *mon)
     pci_for_each_device(0, pci_info_device);
 }
 
-PCIDevice *pci_create(const char *name, const char *devaddr)
+DeviceState *pci_create(const char *name, const char *devaddr)
 {
     PCIBus *bus;
     int devfn;
@@ -779,7 +779,7 @@ PCIDevice *pci_create(const char *name, const char *devaddr)
 
     dev = qdev_create(&bus->qbus, name);
     qdev_prop_set_uint32(dev, "devfn", devfn);
-    return (PCIDevice *)dev;
+    return dev;
 }
 
 static const char * const pci_nic_models[] = {
@@ -811,7 +811,6 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr)
 {
     const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
-    PCIDevice *pci_dev;
     DeviceState *dev;
     int i;
 
@@ -819,12 +818,11 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 
     for (i = 0; pci_nic_models[i]; i++) {
         if (strcmp(nd->model, pci_nic_models[i]) == 0) {
-            pci_dev = pci_create(pci_nic_names[i], devaddr);
-            dev = &pci_dev->qdev;
+            dev = pci_create(pci_nic_names[i], devaddr);
             dev->nd = nd;
             qdev_init(dev);
             nd->private = dev;
-            return pci_dev;
+            return DO_UPCAST(PCIDevice, qdev, dev);
         }
     }
 
diff --git a/hw/pci.h b/hw/pci.h
index cbfea6a..17563ed 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -324,7 +324,7 @@ typedef struct {
 void pci_qdev_register(PCIDeviceInfo *info);
 void pci_qdev_register_many(PCIDeviceInfo *info);
 
-PCIDevice *pci_create(const char *name, const char *devaddr);
+DeviceState *pci_create(const char *name, const char *devaddr);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
 /* lsi53c895a.c */
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index d9ef3ec..b6b8f8a 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -90,7 +90,7 @@ static void bamboo_init(ram_addr_t ram_size,
 {
     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
     PCIBus *pcibus;
-    PCIDevice *pci_dev;
+    DeviceState *qdev;
     CPUState *env;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
@@ -111,8 +111,8 @@ static void bamboo_init(ram_addr_t ram_size,
 
         /* Add virtio block devices. */
         while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
-            pci_dev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
-            qdev_init(&pci_dev->qdev);
+            qdev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
+            qdev_init(qdev);
             unit_id++;
         }
 
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index c0e367d..d21eb95 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -157,7 +157,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                          const char *cpu_model)
 {
     PCIBus *pci_bus;
-    PCIDevice *pci_dev;
+    DeviceState *qdev;
     CPUState *env;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
@@ -220,8 +220,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
 
         /* Add virtio block devices. */
         while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
-            pci_dev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
-            qdev_init(&pci_dev->qdev);
+            qdev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
+            qdev_init(qdev);
             unit_id++;
         }
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 03/13] qdev/pci: make pci_create return DeviceState instead of PCIDevice Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 17:23   ` Paul Brook
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 05/13] qdev: add -device command line option Gerd Hoffmann
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Will be used for -device command line.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci.c  |    1 +
 hw/qdev.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h |    3 +++
 3 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index a52fe3a..a8e7c78 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -54,6 +54,7 @@ static struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
+    .add_dev    = pci_create,
     .props      = (Property[]) {
         {
             .name   = "devfn",
diff --git a/hw/qdev.c b/hw/qdev.c
index 644a5be..e86c896 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -90,6 +90,57 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     return dev;
 }
 
+DeviceState *qdev_device_add(const char *cmdline)
+{
+    DeviceInfo *info;
+    DeviceState *qdev;
+    char driver[32], addr[32] = "";
+    char tag[32], value[256];
+    const char *params = NULL;
+    int n = 0;
+
+    if (1 != sscanf(cmdline, "%32[^,],%n", driver, &n)) {
+        fprintf(stderr, "device parse error: \"%s\"\n", cmdline);
+        return NULL;
+    }
+    if (strcmp(driver, "?") == 0) {
+        for (info = device_info_list; info != NULL; info = info->next) {
+            fprintf(stderr, "name \"%s\", bus %s\n", info->name, info->bus_info->name);
+        }
+        return NULL;
+    }
+    if (n) {
+        params = cmdline + n;
+        get_param_value(addr, sizeof(addr), "addr", params);
+    }
+    info = qdev_find_info(NULL, driver);
+
+    if (!info->bus_info->add_dev) {
+        fprintf(stderr, "bus \"%s\" can't add devices.\n",
+                info->bus_info->name);
+        return NULL;
+    }
+
+    qdev = info->bus_info->add_dev(driver, strlen(addr) ? addr : NULL);
+
+    if (params) {
+        while (params[0]) {
+            if (2 != sscanf(params, "%31[^=]=%255[^,]%n", tag, value, &n))
+                break;
+            params += n;
+            if (strcmp(tag, "addr") == 0)
+                continue;
+            if (-1 == qdev_prop_parse(qdev, tag, value)) {
+                fprintf(stderr, "can't set property \"%s\" to \"%s\" for \"%s\"\n",
+                        tag, value, driver);
+            }
+        }
+    }
+
+    qdev_init(qdev);
+    return qdev;
+}
+
 /* Initialize a device.  Device properties should be set before calling
    this function.  IRQs and MMIO regions should be connected/mapped after
    calling this function.  */
diff --git a/hw/qdev.h b/hw/qdev.h
index 64e9b75..98c11a0 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -29,10 +29,12 @@ struct DeviceState {
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
+typedef DeviceState* (*bus_dev_addfn)(const char *name, const char *addr);
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    bus_dev_addfn add_dev;
     Property *props;
 };
 
@@ -61,6 +63,7 @@ struct PropertyInfo {
 /*** Board API.  This should go away once we have a machine config file.  ***/
 
 DeviceState *qdev_create(BusState *bus, const char *name);
+DeviceState *qdev_device_add(const char *cmdline);
 void qdev_init(DeviceState *dev);
 void qdev_free(DeviceState *dev);
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 05/13] qdev: add -device command line option.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add() Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 06/13] qdev: add no_user, alias and desc Gerd Hoffmann
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add a linked list where command line options can be saved.
Use it for the new -device and for the -usbdevice and -bt switches.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/qdev.c       |    9 ++++-
 qemu-options.hx |    2 +
 vl.c            |   97 ++++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 74 insertions(+), 34 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index e86c896..3f8e456 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -115,6 +115,11 @@ DeviceState *qdev_device_add(const char *cmdline)
     }
     info = qdev_find_info(NULL, driver);
 
+    if (!info) {
+        fprintf(stderr, "Device \"%s\" not found.  Try -device '?' for a list.\n",
+                driver);
+        return NULL;
+    }
     if (!info->bus_info->add_dev) {
         fprintf(stderr, "bus \"%s\" can't add devices.\n",
                 info->bus_info->name);
@@ -125,8 +130,10 @@ DeviceState *qdev_device_add(const char *cmdline)
 
     if (params) {
         while (params[0]) {
-            if (2 != sscanf(params, "%31[^=]=%255[^,]%n", tag, value, &n))
+            if (2 != sscanf(params, "%31[^=]=%255[^,]%n", tag, value, &n)) {
+                fprintf(stderr, "parse error at \"%s\"\n", params);
                 break;
+            }
             params += n;
             if (strcmp(tag, "addr") == 0)
                 continue;
diff --git a/qemu-options.hx b/qemu-options.hx
index 3f69965..a8ef373 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -362,6 +362,8 @@ Network adapter that supports CDC ethernet and RNDIS protocols.
 @end table
 ETEXI
 
+DEF("device", HAS_ARG, QEMU_OPTION_device,
+    "-device driver[,options]  add device\n")
 DEF("name", HAS_ARG, QEMU_OPTION_name,
     "-name string1[,process=string2]    set the name of the guest\n"
     "            string1 sets the window title and string2 the process name (on Linux)\n")
diff --git a/vl.c b/vl.c
index 50665cf..dddceef 100644
--- a/vl.c
+++ b/vl.c
@@ -143,6 +143,7 @@ int main(int argc, char **argv)
 #include "hw/watchdog.h"
 #include "hw/smbios.h"
 #include "hw/xen.h"
+#include "hw/qdev.h"
 #include "bt-host.h"
 #include "net.h"
 #include "monitor.h"
@@ -173,12 +174,6 @@ int main(int argc, char **argv)
 
 #define DEFAULT_RAM_SIZE 128
 
-/* Max number of USB devices that can be specified on the commandline.  */
-#define MAX_USB_CMDLINE 8
-
-/* Max number of bluetooth switches on the commandline.  */
-#define MAX_BT_CMDLINE 10
-
 static const char *data_dir;
 const char *bios_name = NULL;
 /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
@@ -2574,6 +2569,11 @@ static int usb_device_del(const char *devname)
     return usb_device_del_addr(bus_num, addr);
 }
 
+static int usb_parse(const char *cmdline)
+{
+    return usb_device_add(cmdline, 0);
+}
+
 void do_usb_add(Monitor *mon, const char *devname)
 {
     usb_device_add(devname, 1);
@@ -4757,6 +4757,52 @@ char *qemu_find_file(int type, const char *name)
     return buf;
 }
 
+struct device_config {
+    enum {
+        DEV_GENERIC,   /* -device      */
+        DEV_USB,       /* -usbdevice   */
+        DEV_BT,        /* -bt          */
+    } type;
+    const char *cmdline;
+    TAILQ_ENTRY(device_config) next;
+};
+TAILQ_HEAD(, device_config) device_configs = TAILQ_HEAD_INITIALIZER(device_configs);
+
+static void add_device_config(int type, const char *cmdline)
+{
+    struct device_config *conf;
+
+    conf = qemu_mallocz(sizeof(*conf));
+    conf->type = type;
+    conf->cmdline = cmdline;
+    TAILQ_INSERT_TAIL(&device_configs, conf, next);
+}
+
+static int foreach_device_config(int type, int (*func)(const char *cmdline))
+{
+    struct device_config *conf;
+    int rc;
+
+    TAILQ_FOREACH(conf, &device_configs, next) {
+        if (conf->type != type)
+            continue;
+        rc = func(conf->cmdline);
+        if (0 != rc)
+            return rc;
+    }
+    return 0;
+}
+
+static int generic_parse(const char *cmdline)
+{
+    DeviceState *dev;
+
+    dev = qdev_device_add(cmdline);
+    if (!dev)
+        return -1;
+    return 0;
+}
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -4771,8 +4817,6 @@ int main(int argc, char **argv, char **envp)
     int cyls, heads, secs, translation;
     const char *net_clients[MAX_NET_CLIENTS];
     int nb_net_clients;
-    const char *bt_opts[MAX_BT_CMDLINE];
-    int nb_bt_opts;
     int hda_index;
     int optind;
     const char *r, *optarg;
@@ -4787,8 +4831,6 @@ int main(int argc, char **argv, char **envp)
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-    const char *usb_devices[MAX_USB_CMDLINE];
-    int usb_devices_index;
 #ifndef _WIN32
     int fds[2];
 #endif
@@ -4868,10 +4910,7 @@ int main(int argc, char **argv, char **envp)
         node_cpumask[i] = 0;
     }
 
-    usb_devices_index = 0;
-
     nb_net_clients = 0;
-    nb_bt_opts = 0;
     nb_drives = 0;
     nb_drives_opt = 0;
     nb_numa_nodes = 0;
@@ -5118,11 +5157,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_bt:
-                if (nb_bt_opts >= MAX_BT_CMDLINE) {
-                    fprintf(stderr, "qemu: too many bluetooth options\n");
-                    exit(1);
-                }
-                bt_opts[nb_bt_opts++] = optarg;
+                add_device_config(DEV_BT, optarg);
                 break;
 #ifdef HAS_AUDIO
             case QEMU_OPTION_audio_help:
@@ -5364,12 +5399,10 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_usbdevice:
                 usb_enabled = 1;
-                if (usb_devices_index >= MAX_USB_CMDLINE) {
-                    fprintf(stderr, "Too many USB devices\n");
-                    exit(1);
-                }
-                usb_devices[usb_devices_index] = optarg;
-                usb_devices_index++;
+                add_device_config(DEV_USB, optarg);
+                break;
+            case QEMU_OPTION_device:
+                add_device_config(DEV_GENERIC, optarg);
                 break;
             case QEMU_OPTION_smp:
                 smp_cpus = atoi(optarg);
@@ -5692,9 +5725,8 @@ int main(int argc, char **argv, char **envp)
     net_client_check();
 
     /* init the bluetooth world */
-    for (i = 0; i < nb_bt_opts; i++)
-        if (bt_parse(bt_opts[i]))
-            exit(1);
+    if (foreach_device_config(DEV_BT, bt_parse))
+        exit(1);
 
     /* init the memory */
     if (ram_size == 0)
@@ -5882,14 +5914,13 @@ int main(int argc, char **argv, char **envp)
 
     /* init USB devices */
     if (usb_enabled) {
-        for(i = 0; i < usb_devices_index; i++) {
-            if (usb_device_add(usb_devices[i], 0) < 0) {
-                fprintf(stderr, "Warning: could not add USB device %s\n",
-                        usb_devices[i]);
-            }
-        }
+        foreach_device_config(DEV_USB, usb_parse);
     }
 
+    /* init generic devices */
+    if (foreach_device_config(DEV_GENERIC, generic_parse))
+        exit(1);
+
     if (!display_state)
         dumb_display_init();
     /* just use the first displaystate for the moment */
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 06/13] qdev: add no_user, alias and desc
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 05/13] qdev: add -device command line option Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 07/13] qdev: es1370 description Gerd Hoffmann
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

no_user: prevent users from adding certain devices.
desc: description of the device.
alias: to allow user friendly shortcuts on the command line, i.e.
  -device usbmouse  instead of  -device "QEMU USB Mouse"  or
  -device lsi       instead of  -device lsi53c895a

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/qdev.c |   26 +++++++++++++++++++++++++-
 hw/qdev.h |    3 +++
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index 3f8e456..dcca6ac 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -51,6 +51,7 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
 {
     DeviceInfo *info;
 
+    /* first check device names */
     for (info = device_info_list; info != NULL; info = info->next) {
         if (bus_info && info->bus_info != bus_info)
             continue;
@@ -58,6 +59,17 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
             continue;
         return info;
     }
+
+    /* failing that check the aliases */
+    for (info = device_info_list; info != NULL; info = info->next) {
+        if (bus_info && info->bus_info != bus_info)
+            continue;
+        if (!info->alias)
+            continue;
+        if (strcmp(info->alias, name) != 0)
+            continue;
+        return info;
+    }
     return NULL;
 }
 
@@ -105,7 +117,14 @@ DeviceState *qdev_device_add(const char *cmdline)
     }
     if (strcmp(driver, "?") == 0) {
         for (info = device_info_list; info != NULL; info = info->next) {
-            fprintf(stderr, "name \"%s\", bus %s\n", info->name, info->bus_info->name);
+            fprintf(stderr, "name \"%s\", bus %s", info->name, info->bus_info->name);
+            if (info->alias)
+                fprintf(stderr, ", alias \"%s\"", info->alias);
+            if (info->desc)
+                fprintf(stderr, ", desc \"%s\"", info->desc);
+            if (info->no_user)
+                fprintf(stderr, ", no-user");
+            fprintf(stderr, "\n");
         }
         return NULL;
     }
@@ -125,6 +144,11 @@ DeviceState *qdev_device_add(const char *cmdline)
                 info->bus_info->name);
         return NULL;
     }
+    if (info->no_user) {
+        fprintf(stderr, "device \"%s\" can't be added via command line\n",
+                info->name);
+        return NULL;
+    }
 
     qdev = info->bus_info->add_dev(driver, strlen(addr) ? addr : NULL);
 
diff --git a/hw/qdev.h b/hw/qdev.h
index 98c11a0..15c1481 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -80,8 +80,11 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
 
 struct DeviceInfo {
     const char *name;
+    const char *alias;
+    const char *desc;
     size_t size;
     Property *props;
+    int no_user;
 
     /* Private to qdev / bus.  */
     qdev_initfn init;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 07/13] qdev: es1370 description
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 06/13] qdev: add no_user, alias and desc Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 08/13] qdev: convert all vga Gerd Hoffmann
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/es1370.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/es1370.c b/hw/es1370.c
index 9e860f9..3fc30d0 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1054,7 +1054,8 @@ int es1370_init (PCIBus *bus)
 
 static PCIDeviceInfo es1370_info = {
     .qdev.name    = "ES1370",
-    .qdev.size    = sizeof(PCIES1370State),
+    .qdev.desc    = "ENSONIQ AudioPCI ES1370",
+    .qdev.size    = sizeof (PCIES1370State),
     .init         = es1370_initfn,
 };
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 08/13] qdev: convert all vga
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 07/13] qdev: es1370 description Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 09/13] qdev/pci: hook up i440fx Gerd Hoffmann
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/cirrus_vga.c |   85 ++++++++++++++++++++++++++---------------------
 hw/vga.c        |   98 ++++++++++++++++++++++++++++++++++--------------------
 hw/vmware_vga.c |   26 +++++++++++---
 3 files changed, 129 insertions(+), 80 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 902b3ee..1d800e9 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3301,46 +3301,55 @@ static void pci_cirrus_write_config(PCIDevice *d,
     cirrus_update_memory_access(s);
 }
 
+static void pci_cirrus_vga_initfn(PCIDevice *dev)
+{
+     PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
+     CirrusVGAState *s = &d->cirrus_vga;
+     uint8_t *pci_conf = d->dev.config;
+     int device_id = CIRRUS_ID_CLGD5446;
+
+     /* setup VGA */
+     vga_common_init(&s->vga, VGA_RAM_SIZE);
+     cirrus_init_common(s, device_id, 1);
+     s->vga.pci_dev = (PCIDevice *)d;
+     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
+                                      s->vga.screen_dump, s->vga.text_update,
+                                      &s->vga);
+
+     /* setup PCI */
+     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS);
+     pci_config_set_device_id(pci_conf, device_id);
+     pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
+     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+     pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+
+     /* setup memory space */
+     /* memory #0 LFB */
+     /* memory #1 memory-mapped I/O */
+     /* XXX: s->vga.vram_size must be a power of two */
+     pci_register_bar((PCIDevice *)d, 0, 0x2000000,
+                      PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
+     if (device_id == CIRRUS_ID_CLGD5446) {
+         pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
+                          PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+     }
+     /* XXX: ROM BIOS */
+}
+
 void pci_cirrus_vga_init(PCIBus *bus)
 {
-    PCICirrusVGAState *d;
-    uint8_t *pci_conf;
-    CirrusVGAState *s;
-    int device_id;
-
-    device_id = CIRRUS_ID_CLGD5446;
-
-    /* setup PCI configuration registers */
-    d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
-                                                 sizeof(PCICirrusVGAState),
-                                                 -1, NULL, pci_cirrus_write_config);
-    pci_conf = d->dev.config;
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_CIRRUS);
-    pci_config_set_device_id(pci_conf, device_id);
-    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
-    pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
-    pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
-
-    /* setup VGA */
-    s = &d->cirrus_vga;
-    vga_common_init(&s->vga, VGA_RAM_SIZE);
-    cirrus_init_common(s, device_id, 1);
-
-    s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                     s->vga.screen_dump, s->vga.text_update,
-                                     &s->vga);
+    pci_create_simple(bus, -1, "Cirrus VGA");
+}
 
-    s->vga.pci_dev = (PCIDevice *)d;
+static PCIDeviceInfo cirrus_vga_info = {
+    .qdev.name    = "Cirrus VGA",
+    .qdev.size    = sizeof(PCICirrusVGAState),
+    .init         = pci_cirrus_vga_initfn,
+    .config_write = pci_cirrus_write_config,
+};
 
-    /* setup memory space */
-    /* memory #0 LFB */
-    /* memory #1 memory-mapped I/O */
-    /* XXX: s->vga.vram_size must be a power of two */
-    pci_register_bar((PCIDevice *)d, 0, 0x2000000,
-			   PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
-    if (device_id == CIRRUS_ID_CLGD5446) {
-        pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
-                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
-    }
-    /* XXX: ROM BIOS */
+static void cirrus_vga_register(void)
+{
+    pci_qdev_register(&cirrus_vga_info);
 }
+device_init(cirrus_vga_register);
diff --git a/hw/vga.c b/hw/vga.c
index 403f6ff..e1a470d 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2480,52 +2480,78 @@ static void pci_vga_write_config(PCIDevice *d,
         s->map_addr = 0;
 }
 
-int pci_vga_init(PCIBus *bus,
-                 unsigned long vga_bios_offset, int vga_bios_size)
-{
-    PCIVGAState *d;
-    VGAState *s;
-    uint8_t *pci_conf;
-
-    d = (PCIVGAState *)pci_register_device(bus, "VGA",
-                                           sizeof(PCIVGAState),
-                                           -1, NULL, pci_vga_write_config);
-    if (!d)
-        return -1;
-    s = &d->vga_state;
-
-    vga_common_init(s, VGA_RAM_SIZE);
-    vga_init(s);
-
-    s->ds = graphic_console_init(s->update, s->invalidate,
-                                 s->screen_dump, s->text_update, s);
-
-    s->pci_dev = &d->dev;
-
-    pci_conf = d->dev.config;
-    // dummy VGA (same as Bochs ID)
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
-    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
-    pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
-    pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
-
-    /* XXX: VGA_RAM_SIZE must be a power of two */
-    pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
-                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
-    if (vga_bios_size != 0) {
+static void pci_vga_initfn(PCIDevice *dev)
+{
+     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
+     VGAState *s = &d->vga_state;
+     uint8_t *pci_conf = d->dev.config;
+
+     // vga + console init
+     vga_common_init(s, VGA_RAM_SIZE);
+     vga_init(s);
+     s->pci_dev = &d->dev;
+     s->ds = graphic_console_init(s->update, s->invalidate,
+                                  s->screen_dump, s->text_update, s);
+
+     // dummy VGA (same as Bochs ID)
+     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
+     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
+     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+     pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+
+     /* XXX: VGA_RAM_SIZE must be a power of two */
+     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
+                      PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+
+     if (s->bios_size) {
         unsigned int bios_total_size;
-        s->bios_offset = vga_bios_offset;
-        s->bios_size = vga_bios_size;
         /* must be a power of two */
         bios_total_size = 1;
-        while (bios_total_size < vga_bios_size)
+        while (bios_total_size < s->bios_size)
             bios_total_size <<= 1;
         pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
-                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+                         PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
     }
+}
+
+int pci_vga_init(PCIBus *bus,
+                 unsigned long vga_bios_offset, int vga_bios_size)
+{
+    DeviceState *qdev;
+
+    qdev = pci_create("VGA", NULL);
+    qdev_prop_set_uint32(qdev, "bios-offset", vga_bios_offset);
+    qdev_prop_set_uint32(qdev, "bios-size", vga_bios_offset);
+    qdev_init(qdev);
+
     return 0;
 }
 
+static PCIDeviceInfo vga_info = {
+    .qdev.name    = "VGA",
+    .qdev.size    = sizeof(PCIVGAState),
+    .init         = pci_vga_initfn,
+    .config_write = pci_vga_write_config,
+    .qdev.props   = (Property[]) {
+        {
+            .name   = "bios-offset",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(PCIVGAState, vga_state.bios_offset),
+        },{
+            .name   = "bios-size",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(PCIVGAState, vga_state.bios_size),
+        },
+        {/* end of list */}
+    }
+};
+
+static void vga_register(void)
+{
+    pci_qdev_register(&vga_info);
+}
+device_init(vga_register);
+
 /********************************************************/
 /* vga screen dump */
 
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index accdac4..5ceebf1 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1210,14 +1210,11 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
                     iomemtype);
 }
 
-void pci_vmsvga_init(PCIBus *bus)
+static void pci_vmsvga_initfn(PCIDevice *dev)
 {
-    struct pci_vmsvga_state_s *s;
+    struct pci_vmsvga_state_s *s =
+        DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
 
-    /* Setup PCI configuration */
-    s = (struct pci_vmsvga_state_s *)
-        pci_register_device(bus, "QEMUware SVGA",
-                sizeof(struct pci_vmsvga_state_s), -1, NULL, NULL);
     pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
     pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
     s->card.config[PCI_COMMAND]		= 0x07;		/* I/O + Memory */
@@ -1240,3 +1237,20 @@ void pci_vmsvga_init(PCIBus *bus)
 
     register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
 }
+
+void pci_vmsvga_init(PCIBus *bus)
+{
+    pci_create_simple(bus, -1, "QEMUware SVGA");
+}
+
+static PCIDeviceInfo vmsvga_info = {
+    .qdev.name    = "QEMUware SVGA",
+    .qdev.size    = sizeof(struct pci_vmsvga_state_s),
+    .init         = pci_vmsvga_initfn,
+};
+
+static void vmsvga_register(void)
+{
+    pci_qdev_register(&vmsvga_info);
+}
+device_init(vmsvga_register);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 09/13] qdev/pci: hook up i440fx.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 08/13] qdev: convert all vga Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices Gerd Hoffmann
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Hook i44fx pcihost into sysbus.
Convert Host bridge and ISA bridge pci devices to qdev.
Tag as no-user.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci_host.h |    3 ++
 hw/piix_pci.c |  108 +++++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 85 insertions(+), 26 deletions(-)

diff --git a/hw/pci_host.h b/hw/pci_host.h
index 757b0e2..48862b5 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -28,6 +28,8 @@
 /* debug PCI */
 //#define DEBUG_PCI
 
+#include "sysbus.h"
+
 #ifdef DEBUG_PCI
 #define PCI_DPRINTF(fmt, ...) \
 do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
@@ -36,6 +38,7 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #endif
 
 typedef struct {
+    SysBusDevice busdev;
     uint32_t config_reg;
     PCIBus *bus;
 } PCIHostState;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index fce01d4..a5d42d1 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -25,6 +25,7 @@
 #include "hw.h"
 #include "pc.h"
 #include "pci.h"
+#include "sysbus.h"
 
 typedef uint32_t pci_addr_t;
 #include "pci_host.h"
@@ -169,16 +170,9 @@ static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
-PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
+static void i440fx_pcihost_initfn(SysBusDevice *dev)
 {
-    PCIBus *b;
-    PCIDevice *d;
-    I440FXState *s;
-
-    s = qemu_mallocz(sizeof(I440FXState));
-    b = pci_register_bus(NULL, "pci", 
-                         piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
-    s->bus = b;
+    I440FXState *s = FROM_SYSBUS(I440FXState, dev);
 
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
@@ -189,10 +183,10 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
     register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
     register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
     register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+}
 
-    d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
-                            NULL, i440fx_write_config);
-
+static void i440fx_initfn(PCIDevice *d)
+{
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441);
     d->config[0x08] = 0x02; // revision
@@ -202,7 +196,25 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
     d->config[0x72] = 0x02; /* SMRAM */
 
     register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
+}
+
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
+{
+    DeviceState *dev;
+    PCIBus *b;
+    PCIDevice *d;
+    I440FXState *s;
+
+    dev = qdev_create(NULL, "i440FX-pcihost");
+    s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
+    b = pci_register_bus(&s->busdev.qdev, "pci",
+                         piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
+    s->bus = b;
+    qdev_init(dev);
+
+    d = pci_create_simple(b, 0, "i440FX");
     *pi440fx_state = d;
+
     return b;
 }
 
@@ -326,49 +338,93 @@ static int piix_load(QEMUFile* f, void *opaque, int version_id)
     return pci_device_load(d, f);
 }
 
-int piix3_init(PCIBus *bus, int devfn)
+static void piix3_initfn(PCIDevice *d)
 {
-    PCIDevice *d;
     uint8_t *pci_conf;
 
-    d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    devfn, NULL, NULL);
     register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 
-    piix3_dev = d;
     pci_conf = d->config;
-
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
     pci_conf[PCI_HEADER_TYPE] =
         PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
 
+    piix3_dev = d;
     piix3_reset(d);
     qemu_register_reset(piix3_reset, d);
-    return d->devfn;
 }
 
-int piix4_init(PCIBus *bus, int devfn)
+static void piix4_initfn(PCIDevice *d)
 {
-    PCIDevice *d;
     uint8_t *pci_conf;
 
-    d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
-                                    devfn, NULL, NULL);
     register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
 
-    piix4_dev = d;
     pci_conf = d->config;
-
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
     pci_conf[PCI_HEADER_TYPE] =
         PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
 
-
+    piix4_dev = d;
     piix4_reset(d);
     qemu_register_reset(piix4_reset, d);
+}
+
+int piix3_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+
+    d = pci_create_simple(bus, devfn, "PIIX3");
     return d->devfn;
 }
+
+int piix4_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+
+    d = pci_create_simple(bus, devfn, "PIIX4");
+    return d->devfn;
+}
+
+static PCIDeviceInfo i440fx_info[] = {
+    {
+        .qdev.name    = "i440FX",
+        .qdev.desc    = "Host bridge",
+        .qdev.size    = sizeof(PCIDevice),
+        .qdev.no_user = 1,
+        .init         = i440fx_initfn,
+        .config_write = i440fx_write_config,
+    },{
+        .qdev.name    = "PIIX3",
+        .qdev.desc    = "ISA bridge",
+        .qdev.size    = sizeof(PCIDevice),
+        .qdev.no_user = 1,
+        .init         = piix3_initfn,
+    },{
+        .qdev.name    = "PIIX4",
+        .qdev.desc    = "ISA bridge",
+        .qdev.size    = sizeof(PCIDevice),
+        .qdev.no_user = 1,
+        .init         = piix4_initfn,
+    },{
+        /* end of list */
+    }
+};
+
+static SysBusDeviceInfo i440fx_pcihost_info = {
+    .init         = i440fx_pcihost_initfn,
+    .qdev.name    = "i440FX-pcihost",
+    .qdev.size    = sizeof(I440FXState),
+    .qdev.no_user = 1,
+};
+
+static void i440fx_register(void)
+{
+    sysbus_register_withprop(&i440fx_pcihost_info);
+    pci_qdev_register_many(i440fx_info);
+}
+device_init(i440fx_register);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 09/13] qdev/pci: hook up i440fx Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 17:31   ` Paul Brook
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 11/13] switch balloon initialization to -device Gerd Hoffmann
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add id field to DeviceState.  Make qdev_device_add() fill it if supplied
on the command line (i.e. -device foo,id=bar).  Make "info qtree" print it.

This helps users and management apps identifying devices in monitor
output, which is especially useful with otherwise identical devices
such as two virtio disks.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/qdev.c |    5 ++++-
 hw/qdev.h |    1 +
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index dcca6ac..a075e86 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -153,6 +153,7 @@ DeviceState *qdev_device_add(const char *cmdline)
     qdev = info->bus_info->add_dev(driver, strlen(addr) ? addr : NULL);
 
     if (params) {
+        get_param_value(qdev->id, sizeof(qdev->id), "id", params);
         while (params[0]) {
             if (2 != sscanf(params, "%31[^=]=%255[^,]%n", tag, value, &n)) {
                 fprintf(stderr, "parse error at \"%s\"\n", params);
@@ -161,6 +162,8 @@ DeviceState *qdev_device_add(const char *cmdline)
             params += n;
             if (strcmp(tag, "addr") == 0)
                 continue;
+            if (strcmp(tag, "id") == 0)
+                continue;
             if (-1 == qdev_prop_parse(qdev, tag, value)) {
                 fprintf(stderr, "can't set property \"%s\" to \"%s\" for \"%s\"\n",
                         tag, value, driver);
@@ -336,7 +339,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 {
     BusState *child;
-    qdev_printf("dev: %s\n", dev->info->name);
+    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name, dev->id);
     indent += 2;
     if (dev->num_gpio_in) {
         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
diff --git a/hw/qdev.h b/hw/qdev.h
index 15c1481..c61ef4a 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -17,6 +17,7 @@ typedef struct BusInfo BusInfo;
 /* This structure should not be accessed directly.  We declare it here
    so that it can be embedded in individual device state structures.  */
 struct DeviceState {
+    char id[32];
     DeviceInfo *info;
     BusState *parent_bus;
     int num_gpio_out;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 11/13] switch balloon initialization to -device.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 12/13] qdev: add id= support for pci nics Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 13/13] qdev: print device id in "info pci" Gerd Hoffmann
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

With that patch applied "-balloon virtio,args" becomes a shortcut for
"-device virtio-balloon-pci,args".

Side effects:
 - ballon device gains support for id=<tag>.
 - ballon device is off by default now.
 - initialization order changes, which may in different pci slot
   assignment depending on the VM configuration.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pc.c  |    6 -----
 sysemu.h |    2 -
 vl.c     |   65 +++++++++++++++++++++++++++++++++++++------------------------
 3 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 2b89356..ccd2fed 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1407,12 +1407,6 @@ static void pc_init1(ram_addr_t ram_size,
         }
     }
 
-    /* Add virtio balloon device */
-    if (pci_enabled && virtio_balloon) {
-        qdev = pci_create("virtio-balloon-pci", virtio_balloon_devaddr);
-        qdev_init(qdev);
-    }
-
     /* Add virtio console devices */
     if (pci_enabled) {
         for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
diff --git a/sysemu.h b/sysemu.h
index 06dc4c6..9a83bfe 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -116,8 +116,6 @@ extern int win2k_install_hack;
 extern int rtc_td_hack;
 extern int alt_grab;
 extern int usb_enabled;
-extern int virtio_balloon;
-extern const char *virtio_balloon_devaddr;
 extern int smp_cpus;
 extern int cursor_hide;
 extern int graphic_rotate;
diff --git a/vl.c b/vl.c
index dddceef..cdc7b8a 100644
--- a/vl.c
+++ b/vl.c
@@ -223,8 +223,6 @@ int smp_cpus = 1;
 const char *vnc_display;
 int acpi_enabled = 1;
 int no_hpet = 0;
-int virtio_balloon = 1;
-const char *virtio_balloon_devaddr;
 int fd_bootchk = 1;
 int no_reboot = 0;
 int no_shutdown = 0;
@@ -4550,29 +4548,6 @@ static void select_vgahw (const char *p)
     }
 }
 
-#ifdef TARGET_I386
-static int balloon_parse(const char *arg)
-{
-    char buf[128];
-    const char *p;
-
-    if (!strcmp(arg, "none")) {
-        virtio_balloon = 0;
-    } else if (!strncmp(arg, "virtio", 6)) {
-        virtio_balloon = 1;
-        if (arg[6] == ',')  {
-            p = arg + 7;
-            if (get_param_value(buf, sizeof(buf), "addr", p)) {
-                virtio_balloon_devaddr = strdup(buf);
-            }
-        }
-    } else {
-        return -1;
-    }
-    return 0;
-}
-#endif
-
 #ifdef _WIN32
 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 {
@@ -4778,6 +4753,24 @@ static void add_device_config(int type, const char *cmdline)
     TAILQ_INSERT_TAIL(&device_configs, conf, next);
 }
 
+#ifdef TARGET_I386
+static void add_device_config_params(int type, const char *driver,
+                                     const char *params)
+{
+    char *buf;
+    size_t len,pos;
+
+    len = strlen(driver) + 1;
+    if (params)
+        len += strlen(params) + 1;
+    buf = qemu_mallocz(len);
+    pos = snprintf(buf, len, "%s", driver);
+    if (params)
+        pos += snprintf(buf+pos, len-pos, ",%s", params);
+    add_device_config(type, buf);
+}
+#endif
+
 static int foreach_device_config(int type, int (*func)(const char *cmdline))
 {
     struct device_config *conf;
@@ -4803,6 +4796,26 @@ static int generic_parse(const char *cmdline)
     return 0;
 }
 
+#ifdef TARGET_I386
+static int add_device_balloon(const char *arg)
+{
+    const char *name = NULL, *params = NULL;
+
+    if (!strcmp(arg, "none"))
+        return 0;
+    if (!strncmp(arg, "virtio", 6)) {
+        name = "virtio-balloon-pci";
+        if (arg[6] == ',')
+            params = arg+7;
+    }
+    if (!name)
+        return -1;
+
+    add_device_config_params(DEV_GENERIC, name, params);
+    return 0;
+}
+#endif
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -5423,7 +5436,7 @@ int main(int argc, char **argv, char **envp)
                 no_hpet = 1;
                 break;
             case QEMU_OPTION_balloon:
-                if (balloon_parse(optarg) < 0) {
+                if (add_device_balloon(optarg) < 0) {
                     fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
                     exit(1);
                 }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 12/13] qdev: add id= support for pci nics.
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 11/13] switch balloon initialization to -device Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 13/13] qdev: print device id in "info pci" Gerd Hoffmann
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci.c |    2 ++
 net.c    |    5 ++++-
 net.h    |    1 +
 3 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index a8e7c78..ae24402 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -820,6 +820,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
     for (i = 0; pci_nic_models[i]; i++) {
         if (strcmp(nd->model, pci_nic_models[i]) == 0) {
             dev = pci_create(pci_nic_names[i], devaddr);
+            if (nd->id)
+                snprintf(dev->id, sizeof(dev->id), "%s", nd->id);
             dev->nd = nd;
             qdev_init(dev);
             nd->private = dev;
diff --git a/net.c b/net.c
index 1507f37..ca8d232 100644
--- a/net.c
+++ b/net.c
@@ -2428,7 +2428,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
     }
     if (!strcmp(device, "nic")) {
         static const char * const nic_params[] = {
-            "vlan", "name", "macaddr", "model", "addr", "vectors", NULL
+            "vlan", "name", "macaddr", "model", "addr", "id", "vectors", NULL
         };
         NICInfo *nd;
         uint8_t *macaddr;
@@ -2466,6 +2466,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "addr", p)) {
             nd->devaddr = strdup(buf);
         }
+        if (get_param_value(buf, sizeof(buf), "id", p)) {
+            nd->id = strdup(buf);
+        }
         nd->nvectors = NIC_NVECTORS_UNSPECIFIED;
         if (get_param_value(buf, sizeof(buf), "vectors", p)) {
             char *endptr;
diff --git a/net.h b/net.h
index 6026e10..188fa39 100644
--- a/net.h
+++ b/net.h
@@ -95,6 +95,7 @@ struct NICInfo {
     const char *model;
     const char *name;
     const char *devaddr;
+    const char *id;
     VLANState *vlan;
     VLANClientState *vc;
     void *private;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 13/13] qdev: print device id in "info pci".
  2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 12/13] qdev: add id= support for pci nics Gerd Hoffmann
@ 2009-07-10 11:26 ` Gerd Hoffmann
  12 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 11:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann


Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index ae24402..80e99c7 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -738,6 +738,7 @@ static void pci_info_device(PCIDevice *d)
             }
         }
     }
+    monitor_printf(mon, "      id \"%s\"\n", d->qdev.id);
     if (class == 0x0604 && d->config[0x19] != 0) {
         pci_for_each_device(d->config[0x19], pci_info_device);
     }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann
@ 2009-07-10 17:13   ` Paul Brook
  2009-07-10 19:28     ` Gerd Hoffmann
  0 siblings, 1 reply; 28+ messages in thread
From: Paul Brook @ 2009-07-10 17:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

>+extern PropertyInfo qdev_prop_uint32;
>+extern PropertyInfo qdev_prop_hex32;

Having both of these seems wrong.

>+            .name   = "fifo-size",
>+            .info   = &qdev_prop_uint32,
>+            .offset = offsetof(SyborgPointerState, fifo_size),
>+            .defval = (uint32_t[]) { 16 },

This feels kinda crufty. Very easy to get the wrong types. There's also no 
typechecking in qdev_set_prop*.

>+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t
> value);

Why does this return a value?

Paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add() Gerd Hoffmann
@ 2009-07-10 17:23   ` Paul Brook
  2009-07-10 20:27     ` Gerd Hoffmann
  0 siblings, 1 reply; 28+ messages in thread
From: Paul Brook @ 2009-07-10 17:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

On Friday 10 July 2009, Gerd Hoffmann wrote:
> Will be used for -device command line.

I think this is going in the wrong direction. The device tree provides us with 
a standard way of identifying which bus to add a device to. We should be 
removing uses of pci_create, not adding new ones.

Paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices.
  2009-07-10 11:26 ` [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices Gerd Hoffmann
@ 2009-07-10 17:31   ` Paul Brook
  2009-07-10 19:03     ` Gerd Hoffmann
  0 siblings, 1 reply; 28+ messages in thread
From: Paul Brook @ 2009-07-10 17:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

On Friday 10 July 2009, Gerd Hoffmann wrote:
>  struct DeviceState {
> +    char id[32];

Fixed size buffers are almost always wrong. Why 31 characters?

Paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices.
  2009-07-10 17:31   ` Paul Brook
@ 2009-07-10 19:03     ` Gerd Hoffmann
  0 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 19:03 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 07/10/09 19:31, Paul Brook wrote:
> On Friday 10 July 2009, Gerd Hoffmann wrote:
>>   struct DeviceState {
>> +    char id[32];
>
> Fixed size buffers are almost always wrong. Why 31 characters?

640k is enougth for everybody ;)

I'll fix it up and make it dynamic.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-10 17:13   ` Paul Brook
@ 2009-07-10 19:28     ` Gerd Hoffmann
  2009-07-10 19:42       ` Paul Brook
  0 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 19:28 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 07/10/09 19:13, Paul Brook wrote:
>> +extern PropertyInfo qdev_prop_uint32;
>> +extern PropertyInfo qdev_prop_hex32;
>
> Having both of these seems wrong.

Why?

There are properties which tend to be specified as decimal numbers 
(counts, sizes, ...) and some which tend to be specified in hex 
(adresses, ioports, ...).  I think it is useful to have separate 
parse/print functions for them, although they both end up being an uint32_t.

>> +            .name   = "fifo-size",
>> +            .info   =&qdev_prop_uint32,
>> +            .offset = offsetof(SyborgPointerState, fifo_size),
>> +            .defval = (uint32_t[]) { 16 },
>
> This feels kinda crufty. Very easy to get the wrong types.

I think I can make defval a string instead, then go through 
PropertyInfo->parse().  OK?

> There's also no
> typechecking in qdev_set_prop*.

It checks the size.  Which will miss some type mismatches.  I'll fix it.

>> +int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t
>> value);
>
> Why does this return a value?

It can fail if the size check (soon to be type check) mentioned above 
failed.  Such a failure would be a clear qemu bug though, so maybe 
abort() instead?

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-10 19:28     ` Gerd Hoffmann
@ 2009-07-10 19:42       ` Paul Brook
  2009-07-10 20:10         ` Gerd Hoffmann
  0 siblings, 1 reply; 28+ messages in thread
From: Paul Brook @ 2009-07-10 19:42 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Friday 10 July 2009, Gerd Hoffmann wrote:
> On 07/10/09 19:13, Paul Brook wrote:
> >> +extern PropertyInfo qdev_prop_uint32;
> >> +extern PropertyInfo qdev_prop_hex32;
> >
> > Having both of these seems wrong.
>
> Why?
>
> There are properties which tend to be specified as decimal numbers
> (counts, sizes, ...) and some which tend to be specified in hex
> (adresses, ioports, ...).  I think it is useful to have separate
> parse/print functions for them, although they both end up being an
> uint32_t.

I think this is the wrong distinction. Whether you specify something in hex or 
decimal (or even binary/octal) is personal user preference.  Distinguishing 
between integers and addresses may make sense, as those actually have 
different types.

> >> +            .name   = "fifo-size",
> >> +            .info   =&qdev_prop_uint32,
> >> +            .offset = offsetof(SyborgPointerState, fifo_size),
> >> +            .defval = (uint32_t[]) { 16 },
> >
> > This feels kinda crufty. Very easy to get the wrong types.
>
> I think I can make defval a string instead, then go through
> PropertyInfo->parse().  OK?

I don't think that's really any better. I guess it may just be something we 
have to put up with. Possibly have a helper macro that sets all the fields. 
Something like:

  .properties = (Property[]) {
    DEFINE_PROPERTY_UINT32("fifo-size", SyborgPointerState, fifo_size, 16)
  }

Ideally we'd have a single DEFINE_PROPERTY macro and the type would be figured 
out from typeof(fifo_size), but I can't think how to do that.

> >> +int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t
> >> value);
> >
> > Why does this return a value?
>
> It can fail if the size check (soon to be type check) mentioned above
> failed.  Such a failure would be a clear qemu bug though, so maybe
> abort() instead?

Yes. Returning a status code then never checking it is completely pointless.

Paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-10 19:42       ` Paul Brook
@ 2009-07-10 20:10         ` Gerd Hoffmann
  0 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 20:10 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 07/10/09 21:42, Paul Brook wrote:
> On Friday 10 July 2009, Gerd Hoffmann wrote:
>> There are properties which tend to be specified as decimal numbers
>> (counts, sizes, ...) and some which tend to be specified in hex
>> (adresses, ioports, ...).  I think it is useful to have separate
>> parse/print functions for them, although they both end up being an
>> uint32_t.
>
> I think this is the wrong distinction. Whether you specify something in hex or
> decimal (or even binary/octal) is personal user preference.

Hmm.  hex32 will accept/print hex numbers only.  uint32 should accept 
0x<hexnumber> though.  I'll double-check it actually does.

>    .properties = (Property[]) {
>      DEFINE_PROPERTY_UINT32("fifo-size", SyborgPointerState, fifo_size, 16)
>    }
>
> Ideally we'd have a single DEFINE_PROPERTY macro and the type would be figured
> out from typeof(fifo_size), but I can't think how to do that.

I'll have a look whenever I can work out some macro+typeof magic.  Would 
be great if we can catch type mismatches at compile time.

>> It can fail if the size check (soon to be type check) mentioned above
>> failed.  Such a failure would be a clear qemu bug though, so maybe
>> abort() instead?
>
> Yes. Returning a status code then never checking it is completely pointless.

Ok.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-10 17:23   ` Paul Brook
@ 2009-07-10 20:27     ` Gerd Hoffmann
  2009-07-10 20:51       ` Paul Brook
  0 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-10 20:27 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 07/10/09 19:23, Paul Brook wrote:
> On Friday 10 July 2009, Gerd Hoffmann wrote:
>> Will be used for -device command line.
>
> I think this is going in the wrong direction. The device tree provides us with
> a standard way of identifying which bus to add a device to. We should be
> removing uses of pci_create, not adding new ones.

Why?

Let me guess: Because pci bus numbers are guest-changeable and thus not 
stable?

How about using user-specified ids to specify busses then?

PCI example:
   instead of  -device $name,addr=$bus:$slot.$fn
   use         -device $name,bus=root,addr=$slot.$fn

SCSI example:
   host adapter:  -device lsi,id=foo
   scsi disk:     -device scsi-disk,bus=foo,addr=$lun

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-10 20:27     ` Gerd Hoffmann
@ 2009-07-10 20:51       ` Paul Brook
  2009-07-14  7:40         ` Gerd Hoffmann
  0 siblings, 1 reply; 28+ messages in thread
From: Paul Brook @ 2009-07-10 20:51 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Friday 10 July 2009, Gerd Hoffmann wrote:
> On 07/10/09 19:23, Paul Brook wrote:
> > On Friday 10 July 2009, Gerd Hoffmann wrote:
> >> Will be used for -device command line.
> >
> > I think this is going in the wrong direction. The device tree provides us
> > with a standard way of identifying which bus to add a device to. We
> > should be removing uses of pci_create, not adding new ones.
>
> Why?
>
> Let me guess: Because pci bus numbers are guest-changeable and thus not
> stable?

Because I don't think this code need to be bus specific.

> How about using user-specified ids to specify busses then?
>
>PCI example:
>   instead of  -device $name,addr=$bus:$slot.$fn
>   use         -device $name,bus=root,addr=$slot.$fn
>
>SCSI example:
>   host adapter:  -device lsi,id=foo
>   scsi disk:     -device scsi-disk,bus=foo,addr=$lun

I was thinking something a bit more like

  -device lsi,bus=/i440fx/pci
  -device scsi-disk,bus=/i440fx/pci/lsi/scsi

This example is maybe slightly unclear because the i440fx and lsi child busses 
happen to be called "pci" and "scsi". For devices with multiple child busses 
they may have different names.

Adding some form of aliases may be convenient. For example the pci machine 
could alias "pci0" to "/i440fx/pci", which would give 
  -device lsi,bus=pci0
  -device scsi-disk,bus=pci0/lsi/scsi

We also need to figure out the naming of multiple similar devices on the same 
bus. Possibly your "device id" could be used to identify devices on a bus. 
e.g. if we wanted two scsi adapters:

 -device lsi,bus=pci0,id=foo
 -device lsi,bus=pci0,id=bar
 -device scsi-disk,bus=pci0/foo/scsi
 -device scsi-disk,bus=pci0/bar/scsi

Paul

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-10 20:51       ` Paul Brook
@ 2009-07-14  7:40         ` Gerd Hoffmann
  2009-07-14 23:43           ` Markus Armbruster
  0 siblings, 1 reply; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-14  7:40 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On 07/10/09 22:51, Paul Brook wrote:
>>> I think this is going in the wrong direction. The device tree provides us
>>> with a standard way of identifying which bus to add a device to. We
>>> should be removing uses of pci_create, not adding new ones.
>> Why?
>>
>> Let me guess: Because pci bus numbers are guest-changeable and thus not
>> stable?
>
> Because I don't think this code need to be bus specific.

Parts of the problem are certainly bus-specific though, such as parsing 
bus addresses.

> We also need to figure out the naming of multiple similar devices on the same
> bus. Possibly your "device id" could be used to identify devices on a bus.
> e.g. if we wanted two scsi adapters:
>
>   -device lsi,bus=pci0,id=foo
>   -device lsi,bus=pci0,id=bar
>   -device scsi-disk,bus=pci0/foo/scsi
>   -device scsi-disk,bus=pci0/bar/scsi

I think what we will see used in practice is:

  - either go with the defaults (i.e. don't specify a bus at all
    -> device is attached to the first (and often only)
    pci/scsi/usb/whatever bus.
  - or usage of ids to identify devices and busses.

I think nobody will use stuff like
   -device scsi-disk,bus=/main-system-bus/i440FX-pcihost/pci/lsi/scsi
in practice.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-14  7:40         ` Gerd Hoffmann
@ 2009-07-14 23:43           ` Markus Armbruster
  2009-07-15  1:28             ` Markus Armbruster
  2009-07-15  6:26             ` Gerd Hoffmann
  0 siblings, 2 replies; 28+ messages in thread
From: Markus Armbruster @ 2009-07-14 23:43 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Paul Brook, qemu-devel

Gerd Hoffmann <kraxel@redhat.com> writes:

> On 07/10/09 22:51, Paul Brook wrote:
>>>> I think this is going in the wrong direction. The device tree provides us
>>>> with a standard way of identifying which bus to add a device to. We
>>>> should be removing uses of pci_create, not adding new ones.
>>> Why?
>>>
>>> Let me guess: Because pci bus numbers are guest-changeable and thus not
>>> stable?
>>
>> Because I don't think this code need to be bus specific.
>
> Parts of the problem are certainly bus-specific though, such as
> parsing bus addresses.

Yes.

Provide a bus method to parse the addr property?

>> We also need to figure out the naming of multiple similar devices on the same
>> bus. Possibly your "device id" could be used to identify devices on a bus.
>> e.g. if we wanted two scsi adapters:
>>
>>   -device lsi,bus=pci0,id=foo
>>   -device lsi,bus=pci0,id=bar
>>   -device scsi-disk,bus=pci0/foo/scsi
>>   -device scsi-disk,bus=pci0/bar/scsi

Why foo/scsi?  Is there a node "scsi" between the lsi device and the
disk?  If yes, why?

What's the namespace for ids?

A single, flat namespace would do just fine for me.  Then I could do

     -device lsi,bus=pci0,id=scsi0
     -device lsi,bus=pci0,id=scsi1
     -device scsi-disk,bus=scsi0
     -device scsi-disk,bus=scsi1

> I think what we will see used in practice is:
>
>  - either go with the defaults (i.e. don't specify a bus at all
>    -> device is attached to the first (and often only)
>    pci/scsi/usb/whatever bus.
>  - or usage of ids to identify devices and busses.
>
> I think nobody will use stuff like
>   -device scsi-disk,bus=/main-system-bus/i440FX-pcihost/pci/lsi/scsi
> in practice.

I figure I wouldn't.  Still, using tree path names to identify nodes
feels natural.  The more convenient id property fits in easily, just
treat is as abbreviation mechanism.

So, I'd be fine with

    -device DEVNAME,bus=TREE-PATH,addr=ADDR

where TREE-PATH can start either with / (root node) or an id (start
there instead of at the root), and ADDR is interpreted according to the
bus.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-14 23:43           ` Markus Armbruster
@ 2009-07-15  1:28             ` Markus Armbruster
  2009-07-15  6:26             ` Gerd Hoffmann
  1 sibling, 0 replies; 28+ messages in thread
From: Markus Armbruster @ 2009-07-15  1:28 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Paul Brook, qemu-devel

Markus Armbruster <armbru@redhat.com> writes:

> Gerd Hoffmann <kraxel@redhat.com> writes:
>
>> On 07/10/09 22:51, Paul Brook wrote:
>>>>> I think this is going in the wrong direction. The device tree provides us
>>>>> with a standard way of identifying which bus to add a device to. We
>>>>> should be removing uses of pci_create, not adding new ones.
>>>> Why?
>>>>
>>>> Let me guess: Because pci bus numbers are guest-changeable and thus not
>>>> stable?
>>>
>>> Because I don't think this code need to be bus specific.
>>
>> Parts of the problem are certainly bus-specific though, such as
>> parsing bus addresses.
>
> Yes.
>
> Provide a bus method to parse the addr property?
>
>>> We also need to figure out the naming of multiple similar devices on the same
>>> bus. Possibly your "device id" could be used to identify devices on a bus.
>>> e.g. if we wanted two scsi adapters:
>>>
>>>   -device lsi,bus=pci0,id=foo
>>>   -device lsi,bus=pci0,id=bar
>>>   -device scsi-disk,bus=pci0/foo/scsi
>>>   -device scsi-disk,bus=pci0/bar/scsi
>
> Why foo/scsi?  Is there a node "scsi" between the lsi device and the
> disk?  If yes, why?

Got it: because qdev distinguishes between device nodes and bus nodes,
there is a scsi bus node between the lsi device node and the scsi-disk
device node.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add()
  2009-07-14 23:43           ` Markus Armbruster
  2009-07-15  1:28             ` Markus Armbruster
@ 2009-07-15  6:26             ` Gerd Hoffmann
  1 sibling, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-15  6:26 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Paul Brook, qemu-devel

On 07/15/09 01:43, Markus Armbruster wrote:
> Gerd Hoffmann<kraxel@redhat.com>  writes:
>
>> On 07/10/09 22:51, Paul Brook wrote:
>>>>> I think this is going in the wrong direction. The device tree provides us
>>>>> with a standard way of identifying which bus to add a device to. We
>>>>> should be removing uses of pci_create, not adding new ones.
>>>> Why?
>>>>
>>>> Let me guess: Because pci bus numbers are guest-changeable and thus not
>>>> stable?
>>> Because I don't think this code need to be bus specific.
>> Parts of the problem are certainly bus-specific though, such as
>> parsing bus addresses.
>
> Yes.
>
> Provide a bus method to parse the addr property?

Would be an option, yes.

I plan to sort bus= first, then look how to solve the addr= puzzle.

>>>    -device lsi,bus=pci0,id=foo
>>>    -device lsi,bus=pci0,id=bar
>>>    -device scsi-disk,bus=pci0/foo/scsi
>>>    -device scsi-disk,bus=pci0/bar/scsi
>
> Why foo/scsi?  Is there a node "scsi" between the lsi device and the
> disk?  If yes, why?

scsi bus (and we can't skip it as a scsi adapter might have more than 
one bus).

Have hacked up something yesterday, will post RfC patch later today.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 01/13] qdev: rework device properties.
  2009-07-03 10:22 [Qemu-devel] [PATCH 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
@ 2009-07-03 10:22 ` Gerd Hoffmann
  0 siblings, 0 replies; 28+ messages in thread
From: Gerd Hoffmann @ 2009-07-03 10:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch is a major overhaul of the device properties.  The properties
are saved directly in the device state struct now, the linked list of
property values is gone.

Advantages:
  * We don't have to maintain the list with the property values.
  * The value in the property list and the value actually used by
    the device can't go out of sync any more (used to happen for
    the pci.devfn == -1 case) because there is only one place where
    the value is stored.
  * A record describing the property is required now, you can't set
    random properties any more.

There are bus-specific and device-specific properties.  The former
should be used for properties common to all bus drivers.  Typical
use case is bus addressing, i.e. pci.devfn and i2c.address.

Properties have a PropertyInfo struct attached with name, size and
function pointers to parse and print properties.  A few common property
types have PropertyInfos defined in qdev-properties.c.  Drivers are free
to implement their own very special property parsers if needed.

Properties can have default values.  If unset they are zero-filled.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile              |    2 +-
 hw/arm_sysctl.c       |   20 ++++-
 hw/armv7m.c           |   22 ++++-
 hw/axis_dev88.c       |    2 +-
 hw/esp.c              |   14 ++--
 hw/etraxfs.c          |    2 +-
 hw/etraxfs_pic.c      |   18 ++++-
 hw/i2c.c              |   11 ++-
 hw/i2c.h              |    2 +-
 hw/integratorcp.c     |   30 +++++--
 hw/mips_malta.c       |    4 +-
 hw/musicpal.c         |    2 +-
 hw/pc.c               |    4 +-
 hw/pci.c              |   17 +++-
 hw/pcnet.c            |   19 ++++-
 hw/qdev-properties.c  |  207 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c             |  141 +++++----------------------------
 hw/qdev.h             |   60 ++++++++------
 hw/smbus_eeprom.c     |   10 ++-
 hw/smc91c111.c        |    2 +-
 hw/stellaris.c        |    2 +-
 hw/sun4m.c            |    3 +-
 hw/syborg.c           |    4 +-
 hw/syborg_fb.c        |   45 +++++++----
 hw/syborg_interrupt.c |   21 ++++-
 hw/syborg_keyboard.c  |   21 ++++-
 hw/syborg_pointer.c   |   29 ++++++--
 hw/syborg_serial.c    |   21 ++++-
 hw/syborg_timer.c     |   11 ++-
 hw/xilinx.h           |   12 ++--
 hw/xilinx_ethlite.c   |   29 ++++++--
 hw/xilinx_intc.c      |   18 ++++-
 hw/xilinx_timer.c     |   32 ++++++--
 33 files changed, 574 insertions(+), 263 deletions(-)
 create mode 100644 hw/qdev-properties.c

diff --git a/Makefile b/Makefile
index 66c28e5..39143ba 100644
--- a/Makefile
+++ b/Makefile
@@ -108,7 +108,7 @@ obj-y += bt-hci-csr.o
 obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
 obj-y += qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
 obj-y += msmouse.o ps2.o
-obj-y += qdev.o ssi.o
+obj-y += qdev.o qdev-properties.o ssi.o
 
 obj-$(CONFIG_BRLAPI) += baum.o
 
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index c9d1e3f..bb005c8 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -194,7 +194,6 @@ static void arm_sysctl_init1(SysBusDevice *dev)
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
     int iomemtype;
 
-    s->sys_id = qdev_get_prop_int(&dev->qdev, "sys_id", 0);
     /* The MPcore bootloader uses these flags to start secondary CPUs.
        We don't use a bootloader, so do this here.  */
     s->flags = 3;
@@ -210,15 +209,28 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "realview_sysctl");
-    qdev_set_prop_int(dev, "sys_id", sys_id);
+    qdev_prop_set_uint32(dev, "sys_id", sys_id);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 }
 
+static SysBusDeviceInfo arm_sysctl_info = {
+    .init = arm_sysctl_init1,
+    .qdev.name  = "realview_sysctl",
+    .qdev.size  = sizeof(arm_sysctl_state),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "sys_id",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(arm_sysctl_state, sys_id),
+        },
+        {/* end of list */}
+    }
+};
+
 static void arm_sysctl_register_devices(void)
 {
-    sysbus_register_dev("realview_sysctl", sizeof(arm_sysctl_state),
-                        arm_sysctl_init1);
+    sysbus_register_withprop(&arm_sysctl_info);
 }
 
 device_init(arm_sysctl_register_devices)
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 297a3e1..2e66d7e 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -127,7 +127,6 @@ static void bitband_init(SysBusDevice *dev)
     BitBandState *s = FROM_SYSBUS(BitBandState, dev);
     int iomemtype;
 
-    s->base = qdev_get_prop_int(&dev->qdev, "base", 0);
     iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
                                        &s->base);
     sysbus_init_mmio(dev, 0x02000000, iomemtype);
@@ -138,12 +137,12 @@ static void armv7m_bitband_init(void)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_set_prop_int(dev, "base", 0x20000000);
+    qdev_prop_set_uint32(dev, "base", 0x20000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
 
     dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_set_prop_int(dev, "base", 0x40000000);
+    qdev_prop_set_uint32(dev, "base", 0x40000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
 }
@@ -238,10 +237,23 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
     return pic;
 }
 
+static SysBusDeviceInfo bitband_info = {
+    .init = bitband_init,
+    .qdev.name  = "ARM,bitband-memory",
+    .qdev.size  = sizeof(BitBandState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "base",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(BitBandState, base),
+        },
+        {/* end of list */}
+    }
+};
+
 static void armv7m_register_devices(void)
 {
-    sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState),
-                        bitband_init);
+    sysbus_register_withprop(&bitband_info);
 }
 
 device_init(armv7m_register_devices)
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 79a4d71..f93f431 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -297,7 +297,7 @@ void axisdev88_init (ram_addr_t ram_size,
     cpu_irq = cris_pic_init_cpu(env);
     dev = qdev_create(NULL, "etraxfs,pic");
     /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, 0x3001c000);
diff --git a/hw/esp.c b/hw/esp.c
index 88d42a1..9eacccb 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -650,12 +650,14 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
 {
     DeviceState *dev;
     SysBusDevice *s;
+    ESPState *esp;
 
     dev = qdev_create(NULL, "esp");
-    qdev_set_prop_ptr(dev, "dma_memory_read", dma_memory_read);
-    qdev_set_prop_ptr(dev, "dma_memory_write", dma_memory_write);
-    qdev_set_prop_ptr(dev, "dma_opaque", dma_opaque);
-    qdev_set_prop_int(dev, "it_shift", it_shift);
+    esp = DO_UPCAST(ESPState, busdev.qdev, dev);
+    esp->dma_memory_read = dma_memory_read;
+    esp->dma_memory_write = dma_memory_write;
+    esp->dma_opaque = dma_opaque;
+    esp->it_shift = it_shift;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_connect_irq(s, 0, irq);
@@ -668,11 +670,7 @@ static void esp_init1(SysBusDevice *dev)
     int esp_io_memory;
 
     sysbus_init_irq(dev, &s->irq);
-    s->it_shift = qdev_get_prop_int(&dev->qdev, "it_shift", -1);
     assert(s->it_shift != -1);
-    s->dma_memory_read = qdev_get_prop_ptr(&dev->qdev, "dma_memory_read");
-    s->dma_memory_write = qdev_get_prop_ptr(&dev->qdev, "dma_memory_write");
-    s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma_opaque");
 
     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 94cd6bc..c2eca52 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -88,7 +88,7 @@ void bareetraxfs_init (ram_addr_t ram_size,
     cpu_irq = cris_pic_init_cpu(env);
     dev = qdev_create(NULL, "etraxfs,pic");
     /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, 0x3001c000);
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 1c67427..e627218 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -140,7 +140,6 @@ static void etraxfs_pic_init(SysBusDevice *dev)
     struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
     int intr_vect_regs;
 
-    s->interrupt_vector = qdev_get_prop_ptr(&dev->qdev, "interrupt_vector");
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_nmi);
@@ -149,10 +148,23 @@ static void etraxfs_pic_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
 }
 
+static SysBusDeviceInfo etraxfs_pic_info = {
+    .init = etraxfs_pic_init,
+    .qdev.name  = "etraxfs,pic",
+    .qdev.size  = sizeof(struct etrax_pic),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "interrupt_vector",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(struct etrax_pic, interrupt_vector),
+        },
+        {/* end of list */}
+    }
+};
+
 static void etraxfs_pic_register(void)
 {
-    sysbus_register_dev("etraxfs,pic", sizeof (struct etrax_pic),
-                        etraxfs_pic_init);
+    sysbus_register_withprop(&etraxfs_pic_info);
 }
 
 device_init(etraxfs_pic_register)
diff --git a/hw/i2c.c b/hw/i2c.c
index 98aa7fc..42a5d7a 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -20,6 +20,14 @@ struct i2c_bus
 static struct BusInfo i2c_bus_info = {
     .name = "I2C",
     .size = sizeof(i2c_bus),
+    .props = (Property[]) {
+        {
+            .name   = "address",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct i2c_slave, address),
+        },
+        {/* end of list */}
+    }
 };
 
 static void i2c_bus_save(QEMUFile *f, void *opaque)
@@ -151,7 +159,6 @@ static void i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base)
     i2c_slave *s = I2C_SLAVE_FROM_QDEV(dev);
 
     s->info = info;
-    s->address = qdev_get_prop_int(dev, "address", 0);
 
     info->init(s);
 }
@@ -169,7 +176,7 @@ DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, int addr)
     DeviceState *dev;
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_set_prop_int(dev, "address", addr);
+    qdev_prop_set_uint32(dev, "address", addr);
     qdev_init(dev);
     return dev;
 }
diff --git a/hw/i2c.h b/hw/i2c.h
index c4df399..479ff4b 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -40,7 +40,7 @@ struct i2c_slave
     I2CSlaveInfo *info;
 
     /* Remaining fields for internal use by the I2C code.  */
-    int address;
+    uint32_t address;
 };
 
 i2c_bus *i2c_init_bus(DeviceState *parent, const char *name);
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 50eae0c..ddc8d85 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -17,6 +17,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    uint32_t memsz;
     uint32_t flash_offset;
     uint32_t cm_osc;
     uint32_t cm_ctrl;
@@ -230,23 +231,21 @@ static void integratorcm_init(SysBusDevice *dev)
 {
     int iomemtype;
     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
-    int memsz;
 
-    memsz = qdev_get_prop_int(&dev->qdev, "memsz", 0);
     s->cm_osc = 0x01000048;
     /* ??? What should the high bits of this value be?  */
     s->cm_auxosc = 0x0007feff;
     s->cm_sdram = 0x00011122;
-    if (memsz >= 256) {
+    if (s->memsz >= 256) {
         integrator_spd[31] = 64;
         s->cm_sdram |= 0x10;
-    } else if (memsz >= 128) {
+    } else if (s->memsz >= 128) {
         integrator_spd[31] = 32;
         s->cm_sdram |= 0x0c;
-    } else if (memsz >= 64) {
+    } else if (s->memsz >= 64) {
         integrator_spd[31] = 16;
         s->cm_sdram |= 0x08;
-    } else if (memsz >= 32) {
+    } else if (s->memsz >= 32) {
         integrator_spd[31] = 4;
         s->cm_sdram |= 0x04;
     } else {
@@ -475,7 +474,7 @@ static void integratorcp_init(ram_addr_t ram_size,
     cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM);
 
     dev = qdev_create(NULL, "integrator_core");
-    qdev_set_prop_int(dev, "memsz", ram_size >> 20);
+    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
     qdev_init(dev);
     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
 
@@ -522,11 +521,24 @@ static void integratorcp_machine_init(void)
 
 machine_init(integratorcp_machine_init);
 
+static SysBusDeviceInfo core_info = {
+    .init = integratorcm_init,
+    .qdev.name  = "integrator_core",
+    .qdev.size  = sizeof(integratorcm_state),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "memsz",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(integratorcm_state, memsz),
+        },
+        {/* end of list */}
+    }
+};
+
 static void integratorcp_register_devices(void)
 {
     sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
-    sysbus_register_dev("integrator_core", sizeof(integratorcm_state),
-                        integratorcm_init);
+    sysbus_register_withprop(&core_info);
 }
 
 device_init(integratorcp_register_devices)
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 853ec2b..7728e58 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -914,8 +914,8 @@ void mips_malta_init (ram_addr_t ram_size,
         /* TODO: Populate SPD eeprom data.  */
         DeviceState *eeprom;
         eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-        qdev_set_prop_int(eeprom, "address", 0x50 + i);
-        qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
+        qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
         qdev_init(eeprom);
     }
     pit = pit_init(0x40, i8259[0]);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 10be69b..e636791 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1578,7 +1578,7 @@ static void musicpal_init(ram_addr_t ram_size,
 
     qemu_check_nic_model(&nd_table[0], "mv88w8618");
     dev = qdev_create(NULL, "mv88w8618_eth");
-    qdev_set_netdev(dev, &nd_table[0]);
+    dev->nd = &nd_table[0];
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, MP_ETH_BASE);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[MP_ETH_IRQ]);
diff --git a/hw/pc.c b/hw/pc.c
index 553ba5c..bdcec52 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1374,8 +1374,8 @@ static void pc_init1(ram_addr_t ram_size,
         for (i = 0; i < 8; i++) {
             DeviceState *eeprom;
             eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-            qdev_set_prop_int(eeprom, "address", 0x50 + i);
-            qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
+            qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
             qdev_init(eeprom);
         }
     }
diff --git a/hw/pci.c b/hw/pci.c
index 9c7289a..07b62e9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -54,6 +54,15 @@ static struct BusInfo pci_bus_info = {
     .name  = "PCI",
     .size  = sizeof(PCIBus),
     .print = pcibus_dev_print,
+    .props = (Property[]) {
+        {
+            .name   = "devfn",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(PCIDevice, devfn),
+            .defval = (uint32_t[]) { -1 },
+        },
+        {/* end of list */}
+    }
 };
 
 static void pci_update_mappings(PCIDevice *d);
@@ -769,7 +778,7 @@ PCIDevice *pci_create(const char *name, const char *devaddr)
     }
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_set_prop_int(dev, "devfn", devfn);
+    qdev_prop_set_uint32(dev, "devfn", devfn);
     return (PCIDevice *)dev;
 }
 
@@ -812,7 +821,7 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
         if (strcmp(nd->model, pci_nic_models[i]) == 0) {
             pci_dev = pci_create(pci_nic_names[i], devaddr);
             dev = &pci_dev->qdev;
-            qdev_set_netdev(dev, nd);
+            dev->nd = nd;
             qdev_init(dev);
             nd->private = dev;
             return pci_dev;
@@ -890,7 +899,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     int devfn;
 
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
-    devfn = qdev_get_prop_int(qdev, "devfn", -1);
+    devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
                                      info->config_read, info->config_write);
     assert(pci_dev);
@@ -917,7 +926,7 @@ 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_prop_set_uint32(dev, "devfn", devfn);
     qdev_init(dev);
 
     return (PCIDevice *)dev;
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 4519780..22ab6be 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2128,8 +2128,6 @@ static void lance_init(SysBusDevice *dev)
     s->mmio_index =
         cpu_register_io_memory(lance_mem_read, lance_mem_write, d);
 
-    s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma");
-
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
     sysbus_init_mmio(dev, 4, s->mmio_index);
@@ -2141,6 +2139,21 @@ static void lance_init(SysBusDevice *dev)
 
     pcnet_common_init(&dev->qdev, s, lance_cleanup);
 }
+
+static SysBusDeviceInfo lance_info = {
+    .init = lance_init,
+    .qdev.name  = "lance",
+    .qdev.size  = sizeof(SysBusPCNetState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "dma",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(SysBusPCNetState, state.dma_opaque),
+        },
+        {/* end of list */}
+    }
+};
+
 #endif /* TARGET_SPARC */
 
 static PCIDeviceInfo pcnet_info = {
@@ -2153,7 +2166,7 @@ static void pcnet_register_devices(void)
 {
     pci_qdev_register(&pcnet_info);
 #if defined (TARGET_SPARC) && !defined(TARGET_SPARC64)
-    sysbus_register_dev("lance", sizeof(SysBusPCNetState), lance_init);
+    sysbus_register_withprop(&lance_info);
 #endif
 }
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
new file mode 100644
index 0000000..b4f4f21
--- /dev/null
+++ b/hw/qdev-properties.c
@@ -0,0 +1,207 @@
+#include "qdev.h"
+
+static void *prop_ptr(DeviceState *dev, Property *prop)
+{
+    void *ptr = dev;
+    ptr += prop->offset;
+    return ptr;
+}
+
+/* --- 32bit integer --- */
+
+static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIu32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "%" PRIu32, *ptr);
+}
+
+PropertyInfo qdev_prop_uint32 = {
+    .name  = "uint32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_uint32,
+    .print = print_uint32,
+};
+
+/* --- 32bit hex value --- */
+
+static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+
+    if (sscanf(str, "%" PRIx32, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint32_t *ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x%" PRIx32, *ptr);
+}
+
+PropertyInfo qdev_prop_hex32 = {
+    .name  = "hex32",
+    .size  = sizeof(uint32_t),
+    .parse = parse_hex32,
+    .print = print_hex32,
+};
+
+/* --- pointer --- */
+
+static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    void **ptr = prop_ptr(dev, prop);
+    return snprintf(dest, len, "<%p>", *ptr);
+}
+
+PropertyInfo qdev_prop_ptr = {
+    .name  = "ptr",
+    .size  = sizeof(void*),
+    .print = print_ptr,
+};
+
+/* --- mac address --- */
+
+/*
+ * accepted syntax versions:
+ *   01:02:03:04:05:06
+ *   01-02-03-04-05-06
+ */
+static int parse_mac(DeviceState *dev, Property *prop, const char *str)
+{
+    uint8_t *mac = prop_ptr(dev, prop);
+    int i, pos;
+    char *p;
+
+    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
+        if (!isxdigit(str[pos]))
+            return -1;
+        if (!isxdigit(str[pos+1]))
+            return -1;
+        if (i == 5 && str[pos+2] != '\0')
+            return -1;
+        if (str[pos+2] != ':' && str[pos+2] != '-')
+            return -1;
+        mac[i] = strtol(str+pos, &p, 16);
+    }
+    return 0;
+}
+
+static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint8_t *mac = prop_ptr(dev, prop);
+    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
+                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+PropertyInfo qdev_prop_mac = {
+    .name  = "mac",
+    .size  = 6,
+    .parse = parse_mac,
+    .print = print_mac,
+};
+
+/* --- public helpers --- */
+
+static Property *qdev_prop_walk(Property *props, const char *name)
+{
+    if (!props)
+        return NULL;
+    while (props->name) {
+        if (strcmp(props->name, name) == 0)
+            return props;
+        props++;
+    }
+    return NULL;
+}
+
+static Property *qdev_prop_find(DeviceState *dev, const char *name)
+{
+    Property *prop;
+
+    /* device properties */
+    prop = qdev_prop_walk(dev->info->props, name);
+    if (prop)
+        return prop;
+
+    /* bus properties */
+    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
+    if (prop)
+        return prop;
+
+    return NULL;
+}
+
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
+{
+    Property *prop;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (!prop->info->parse) {
+        fprintf(stderr, "property \"%s.%s\" has no parser\n",
+                dev->info->name, name);
+        return -1;
+    }
+    return prop->info->parse(dev, prop, value);
+}
+
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size)
+{
+    Property *prop;
+    void *dst;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "property \"%s.%s\" not found\n",
+                dev->info->name, name);
+        return -1;
+    }
+    if (prop->info->size != size) {
+        fprintf(stderr, "property \"%s.%s\" size mismatch (%zd / %zd)\n",
+                dev->info->name, name, prop->info->size, size);
+        return -1;
+    }
+    dst = prop_ptr(dev, prop);
+    memcpy(dst, src, size);
+    return 0;
+}
+
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
+{
+    return qdev_prop_set(dev, name, &value, sizeof(value));
+}
+
+int qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
+{
+    return qdev_prop_set(dev, name, &value, sizeof(value));
+}
+
+void qdev_prop_set_defaults(DeviceState *dev, Property *props)
+{
+    char *dst;
+
+    if (!props)
+        return;
+    while (props->name) {
+        if (props->defval) {
+            dst = prop_ptr(dev, props);
+            memcpy(dst, props->defval, props->info->size);
+        }
+        props++;
+    }
+}
+
diff --git a/hw/qdev.c b/hw/qdev.c
index fc49b05..9e10454 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -31,16 +31,6 @@
 #include "sysemu.h"
 #include "monitor.h"
 
-struct DeviceProperty {
-    const char *name;
-    DevicePropType type;
-    union {
-        uint64_t i;
-        void *ptr;
-    } value;
-    DeviceProperty *next;
-};
-
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 static BusState *main_system_bus;
 extern struct BusInfo system_bus_info;
@@ -85,6 +75,8 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     dev = qemu_mallocz(info->size);
     dev->info = info;
     dev->parent_bus = bus;
+    qdev_prop_set_defaults(dev, dev->info->props);
+    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
     LIST_INSERT_HEAD(&bus->children, dev, sibling);
     return dev;
 }
@@ -104,52 +96,6 @@ void qdev_free(DeviceState *dev)
     free(dev);
 }
 
-static DeviceProperty *create_prop(DeviceState *dev, const char *name,
-                                   DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    /* TODO: Check for duplicate properties.  */
-    prop = qemu_mallocz(sizeof(*prop));
-    prop->name = qemu_strdup(name);
-    prop->type = type;
-    prop->next = dev->props;
-    dev->props = prop;
-
-    return prop;
-}
-
-void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_INT);
-    prop->value.i = value;
-}
-
-void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_DEV);
-    prop->value.ptr = value;
-}
-
-void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
-{
-    DeviceProperty *prop;
-
-    prop = create_prop(dev, name, PROP_TYPE_PTR);
-    prop->value.ptr = value;
-}
-
-void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
-{
-    assert(!dev->nd);
-    dev->nd = nd;
-}
-
-
 /* Get a character (serial) device interface.  */
 CharDriverState *qdev_init_chardev(DeviceState *dev)
 {
@@ -168,52 +114,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
     return dev->parent_bus;
 }
 
-static DeviceProperty *find_prop(DeviceState *dev, const char *name,
-                                 DevicePropType type)
-{
-    DeviceProperty *prop;
-
-    for (prop = dev->props; prop; prop = prop->next) {
-        if (strcmp(prop->name, name) == 0) {
-            assert (prop->type == type);
-            return prop;
-        }
-    }
-    return NULL;
-}
-
-uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_INT);
-    if (!prop) {
-        return def;
-    }
-
-    return prop->value.i;
-}
-
-void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_PTR);
-    assert(prop);
-    return prop->value.ptr;
-}
-
-DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
-{
-    DeviceProperty *prop;
-
-    prop = find_prop(dev, name, PROP_TYPE_DEV);
-    if (!prop) {
-        return NULL;
-    }
-    return prop->value.ptr;
-}
-
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
 {
     assert(dev->num_gpio_in == 0);
@@ -325,9 +225,24 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
 static void qbus_print(Monitor *mon, BusState *bus, int indent);
 
+static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
+                             const char *prefix, int indent)
+{
+    char buf[64];
+
+    if (!props)
+        return;
+    while (props->name) {
+        if (props->info->print) {
+            props->info->print(dev, props, buf, sizeof(buf));
+            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
+        }
+        props++;
+    }
+}
+
 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 {
-    DeviceProperty *prop;
     BusState *child;
     qdev_printf("dev: %s\n", dev->info->name);
     indent += 2;
@@ -337,24 +252,8 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
     if (dev->num_gpio_out) {
         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
     }
-    for (prop = dev->props; prop; prop = prop->next) {
-        switch (prop->type) {
-        case PROP_TYPE_INT:
-            qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
-                        prop->value.i);
-            break;
-        case PROP_TYPE_PTR:
-            qdev_printf("prop-ptr %s\n", prop->name);
-            break;
-        case PROP_TYPE_DEV:
-            qdev_printf("prop-dev %s %s\n", prop->name,
-                        ((DeviceState *)prop->value.ptr)->info->name);
-            break;
-        default:
-            qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
-            break;
-        }
-    }
+    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
+    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
     if (dev->parent_bus->info->print)
         dev->parent_bus->info->print(mon, dev, indent);
     LIST_FOREACH(child, &dev->child_bus, sibling) {
diff --git a/hw/qdev.h b/hw/qdev.h
index 8ce5c23..9a3de47 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -4,9 +4,11 @@
 #include "hw.h"
 #include "sys-queue.h"
 
-typedef struct DeviceInfo DeviceInfo;
+typedef struct Property Property;
+
+typedef struct PropertyInfo PropertyInfo;
 
-typedef struct DeviceProperty DeviceProperty;
+typedef struct DeviceInfo DeviceInfo;
 
 typedef struct BusState BusState;
 
@@ -17,7 +19,6 @@ typedef struct BusInfo BusInfo;
 struct DeviceState {
     DeviceInfo *info;
     BusState *parent_bus;
-    DeviceProperty *props;
     int num_gpio_out;
     qemu_irq *gpio_out;
     int num_gpio_in;
@@ -31,6 +32,7 @@ typedef void (*bus_dev_print)(Monitor *mon, DeviceState *dev, int indent);
 struct BusInfo {
     const char *name;
     size_t size;
+    Property *props;
     bus_dev_print print;
 };
 
@@ -42,18 +44,26 @@ struct BusState {
     LIST_ENTRY(BusState) sibling;
 };
 
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+    void         *defval;
+};
+
+struct PropertyInfo {
+    const char *name;
+    size_t size;
+    int (*parse)(DeviceState *dev, Property *prop, const char *str);
+    int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+};
+
 /*** Board API.  This should go away once we have a machine config file.  ***/
 
 DeviceState *qdev_create(BusState *bus, const char *name);
 void qdev_init(DeviceState *dev);
 void qdev_free(DeviceState *dev);
 
-/* Set properties between creation and init.  */
-void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value);
-void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value);
-void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value);
-void qdev_set_netdev(DeviceState *dev, NICInfo *nd);
-
 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
 void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
 
@@ -61,17 +71,6 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
 /*** Device API.  ***/
 
-typedef enum {
-    PROP_TYPE_INT,
-    PROP_TYPE_PTR,
-    PROP_TYPE_DEV
-} DevicePropType;
-
-typedef struct {
-    const char *name;
-    DevicePropType type;
-} DevicePropList;
-
 typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
 typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
               int unit);
@@ -79,7 +78,7 @@ typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
 struct DeviceInfo {
     const char *name;
     size_t size;
-    DevicePropList *props;
+    Property *props;
 
     /* Private to qdev / bus.  */
     qdev_initfn init;
@@ -99,10 +98,6 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach);
 CharDriverState *qdev_init_chardev(DeviceState *dev);
 
 BusState *qdev_get_parent_bus(DeviceState *dev);
-uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def);
-DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name);
-/* FIXME: Remove opaque pointer properties.  */
-void *qdev_get_prop_ptr(DeviceState *dev, const char *name);
 
 /* Convery from a base type to a parent type, with compile time checking.  */
 #ifdef __GNUC__
@@ -125,4 +120,19 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
 void do_info_qtree(Monitor *mon);
 void do_info_qdrv(Monitor *mon);
 
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_mac;
+
+/* Set properties between creation and init.  */
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+int qdev_prop_set(DeviceState *dev, const char *name, void *src, size_t size);
+int qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+/* FIXME: Remove opaque pointer properties.  */
+int qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
+void qdev_prop_set_defaults(DeviceState *dev, Property *props);
+
 #endif
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 05a70d9..c071fb1 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -99,14 +99,20 @@ static void smbus_eeprom_init(SMBusDevice *dev)
 {
     SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev;
 
-    /* FIXME: Should be a blob rather than a ptr.  */
-    eeprom->data = qdev_get_prop_ptr(&dev->i2c.qdev, "data");
     eeprom->offset = 0;
 }
 
 static SMBusDeviceInfo smbus_eeprom_info = {
     .i2c.qdev.name = "smbus-eeprom",
     .i2c.qdev.size = sizeof(SMBusEEPROMDevice),
+    .i2c.qdev.props = (Property[]) {
+        {
+            .name   = "data",
+            .info   = &qdev_prop_ptr,
+            .offset = offsetof(SMBusEEPROMDevice, data),
+        },
+        {/* end of list */}
+    },
     .init = smbus_eeprom_init,
     .quick_cmd = eeprom_quick_cmd,
     .send_byte = eeprom_send_byte,
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index cf8d864..5f6956a 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -733,7 +733,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
 
     qemu_check_nic_model(nd, "smc91c111");
     dev = qdev_create(NULL, "smc91c111");
-    qdev_set_netdev(dev, nd);
+    dev->nd = nd;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, base);
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5f44bff..d9434ca 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1378,7 +1378,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         qemu_check_nic_model(&nd_table[0], "stellaris");
 
         enet = qdev_create(NULL, "stellaris_enet");
-        qdev_set_netdev(enet, &nd_table[0]);
+        enet->nd = &nd_table[0];
         qdev_init(enet);
         sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000);
         sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index c67bf0b..0805f6e 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -373,8 +373,7 @@ static void lance_init(NICInfo *nd, target_phys_addr_t leaddr,
     qemu_check_nic_model(&nd_table[0], "lance");
 
     dev = qdev_create(NULL, "lance");
-    qdev_set_netdev(dev, nd);
-    qdev_set_prop_ptr(dev, "dma", dma_opaque);
+    dev->nd = nd;
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, leaddr);
diff --git a/hw/syborg.c b/hw/syborg.c
index 5ca9977..d8d38d4 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -64,7 +64,7 @@ static void syborg_init(ram_addr_t ram_size,
     sysbus_create_simple("syborg,rtc", 0xC0001000, NULL);
 
     dev = qdev_create(NULL, "syborg,timer");
-    qdev_set_prop_int(dev, "frequency", 1000000);
+    qdev_prop_set_uint32(dev, "frequency", 1000000);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]);
@@ -83,7 +83,7 @@ static void syborg_init(ram_addr_t ram_size,
 
         qemu_check_nic_model(&nd_table[0], "virtio");
         dev = qdev_create(NULL, "syborg,virtio-net");
-        qdev_set_netdev(dev, &nd_table[0]);
+        dev->nd = &nd_table[0];
         qdev_init(dev);
         s = sysbus_from_qdev(dev);
         sysbus_mmio_map(s, 0, 0xc000c000);
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 42c6274..2929ffd 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -76,8 +76,8 @@ typedef struct {
 
     uint32_t base;
     uint32_t pitch;
-    int rows;
-    int cols;
+    uint32_t rows;
+    uint32_t cols;
     int blank;
     int bpp;
     int rgb; /* 0 = BGR, 1 = RGB */
@@ -507,41 +507,50 @@ static void syborg_fb_init(SysBusDevice *dev)
 {
     SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
     int iomemtype;
-    int width;
-    int height;
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_fb_readfn,
                                        syborg_fb_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-    width = qdev_get_prop_int(&dev->qdev, "width", 0);
-    height = qdev_get_prop_int(&dev->qdev, "height", 0);
-
     s->ds = graphic_console_init(syborg_fb_update_display,
                                  syborg_fb_invalidate_display,
                                  NULL, NULL, s);
 
-    if (width != 0 && height != 0) {
-        qemu_console_resize(s->ds, width, height);
+    if (s->cols != 0 && s->rows != 0) {
+        qemu_console_resize(s->ds, s->cols, s->rows);
     }
 
-    if (!width)
-        width = ds_get_width(s->ds);
-    if (!height)
-        height = ds_get_height(s->ds);
-
-    s->cols = width;
-    s->rows = height;
+    if (!s->cols)
+        s->cols = ds_get_width(s->ds);
+    if (!s->rows)
+        s->rows = ds_get_height(s->ds);
 
     register_savevm("syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
 }
 
+static SysBusDeviceInfo syborg_fb_info = {
+    .init = syborg_fb_init,
+    .qdev.name  = "syborg,framebuffer",
+    .qdev.size  = sizeof(SyborgFBState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "width",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgFBState, cols),
+        },{
+            .name   = "height",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgFBState, rows),
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_fb_register_devices(void)
 {
-    sysbus_register_dev("syborg,framebuffer", sizeof(SyborgFBState),
-                        syborg_fb_init);
+    sysbus_register_withprop(&syborg_fb_info);
 }
 
 device_init(syborg_fb_register_devices)
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 569c7f6..a372ec1 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -56,7 +56,7 @@ typedef struct {
 typedef struct {
     SysBusDevice busdev;
     int pending_count;
-    int num_irqs;
+    uint32_t num_irqs;
     syborg_int_flags *flags;
     qemu_irq parent_irq;
 } SyborgIntState;
@@ -208,7 +208,6 @@ static void syborg_int_init(SysBusDevice *dev)
     int iomemtype;
 
     sysbus_init_irq(dev, &s->parent_irq);
-    s->num_irqs = qdev_get_prop_int(&dev->qdev, "num-interrupts", 64);
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
     iomemtype = cpu_register_io_memory(syborg_int_readfn,
                                        syborg_int_writefn, s);
@@ -218,10 +217,24 @@ static void syborg_int_init(SysBusDevice *dev)
     register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
 }
 
+static SysBusDeviceInfo syborg_int_info = {
+    .init = syborg_int_init,
+    .qdev.name  = "syborg,interrupt",
+    .qdev.size  = sizeof(SyborgIntState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "num-interrupts",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgIntState, num_irqs),
+            .defval = (uint32_t[]) { 64 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_interrupt_register_devices(void)
 {
-    sysbus_register_dev("syborg,interrupt", sizeof(SyborgIntState),
-                        syborg_int_init);
+    sysbus_register_withprop(&syborg_int_info);
 }
 
 device_init(syborg_interrupt_register_devices)
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 84a099e..ffc85a5 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -53,7 +53,7 @@ typedef struct {
     SysBusDevice busdev;
     int int_enabled;
     int extension_bit;
-    int fifo_size;
+    uint32_t fifo_size;
     uint32_t *key_fifo;
     int read_pos, read_count;
     qemu_irq irq;
@@ -212,7 +212,6 @@ static void syborg_keyboard_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
                                        syborg_keyboard_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
         s->fifo_size = 16;
@@ -225,10 +224,24 @@ static void syborg_keyboard_init(SysBusDevice *dev)
                     syborg_keyboard_save, syborg_keyboard_load, s);
 }
 
+static SysBusDeviceInfo syborg_keyboard_info = {
+    .init = syborg_keyboard_init,
+    .qdev.name  = "syborg,keyboard",
+    .qdev.size  = sizeof(SyborgKeyboardState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgKeyboardState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_keyboard_register_devices(void)
 {
-    sysbus_register_dev("syborg,keyboard", sizeof(SyborgKeyboardState),
-                        syborg_keyboard_init);
+    sysbus_register_withprop(&syborg_keyboard_info);
 }
 
 device_init(syborg_keyboard_register_devices)
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index e0a892d..edd1f22 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -45,11 +45,11 @@ typedef struct {
 typedef struct {
     SysBusDevice busdev;
     int int_enabled;
-    int fifo_size;
+    uint32_t fifo_size;
     event_data *event_fifo;
     int read_pos, read_count;
     qemu_irq irq;
-    int absolute;
+    uint32_t absolute;
 } SyborgPointerState;
 
 static void syborg_pointer_update(SyborgPointerState *s)
@@ -209,8 +209,6 @@ static void syborg_pointer_init(SysBusDevice *dev)
 				       syborg_pointer_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-    s->absolute = qdev_get_prop_int(&dev->qdev, "absolute", 1);
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_pointer: fifo too small\n");
         s->fifo_size = 16;
@@ -224,10 +222,29 @@ static void syborg_pointer_init(SysBusDevice *dev)
                     syborg_pointer_save, syborg_pointer_load, s);
 }
 
+static SysBusDeviceInfo syborg_pointer_info = {
+    .init = syborg_pointer_init,
+    .qdev.name  = "syborg,pointer",
+    .qdev.size  = sizeof(SyborgPointerState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgPointerState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },{
+            .name   = "absolute",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgPointerState, absolute),
+            .defval = (uint32_t[]) { 1 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_pointer_register_devices(void)
 {
-    sysbus_register_dev("syborg,pointer", sizeof(SyborgPointerState),
-                        syborg_pointer_init);
+    sysbus_register_withprop(&syborg_pointer_info);
 }
 
 device_init(syborg_pointer_register_devices)
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index f430508..f693421 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -59,7 +59,7 @@ enum {
 typedef struct {
     SysBusDevice busdev;
     uint32_t int_enable;
-    int fifo_size;
+    uint32_t fifo_size;
     uint32_t *read_fifo;
     int read_pos;
     int read_count;
@@ -329,7 +329,6 @@ static void syborg_serial_init(SysBusDevice *dev)
         qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
                               syborg_serial_receive, syborg_serial_event, s);
     }
-    s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_serial: fifo too small\n");
         s->fifo_size = 16;
@@ -340,10 +339,24 @@ static void syborg_serial_init(SysBusDevice *dev)
                     syborg_serial_save, syborg_serial_load, s);
 }
 
+static SysBusDeviceInfo syborg_serial_info = {
+    .init = syborg_serial_init,
+    .qdev.name  = "syborg,serial",
+    .qdev.size  = sizeof(SyborgSerialState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "fifo-size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgSerialState, fifo_size),
+            .defval = (uint32_t[]) { 16 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void syborg_serial_register_devices(void)
 {
-    sysbus_register_dev("syborg,serial", sizeof(SyborgSerialState),
-                        syborg_serial_init);
+    sysbus_register_withprop(&syborg_serial_info);
 }
 
 device_init(syborg_serial_register_devices)
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 4f5e3a1..cf96c5f 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -209,7 +209,6 @@ static void syborg_timer_init(SysBusDevice *dev)
     QEMUBH *bh;
     int iomemtype;
 
-    s->freq = qdev_get_prop_int(&dev->qdev, "frequency", 0);
     if (s->freq == 0) {
         fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
         exit(1);
@@ -230,9 +229,13 @@ static SysBusDeviceInfo syborg_timer_info = {
     .init = syborg_timer_init,
     .qdev.name  = "syborg,timer",
     .qdev.size  = sizeof(SyborgTimerState),
-    .qdev.props = (DevicePropList[]) {
-        {.name = "frequency", .type = PROP_TYPE_INT},
-        {.name = NULL}
+    .qdev.props = (Property[]) {
+        {
+            .name   = "frequency",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(SyborgTimerState, freq),
+        },
+        {/* end of list */}
     }
 };
 
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 9707a0e..070679c 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -8,7 +8,7 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "xilinx,intc");
-    qdev_set_prop_int(dev, "kind-of-intr", kind_of_intr);
+    qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -22,8 +22,8 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int nr, int freq)
     DeviceState *dev;
 
     dev = qdev_create(NULL, "xilinx,timer");
-    qdev_set_prop_int(dev, "nr-timers", nr);
-    qdev_set_prop_int(dev, "frequency", freq);
+    qdev_prop_set_uint32(dev, "nr-timers", nr);
+    qdev_prop_set_uint32(dev, "frequency", freq);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
@@ -40,9 +40,9 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq,
     qemu_check_nic_model(nd, "xilinx-ethlite");
 
     dev = qdev_create(NULL, "xilinx,ethlite");
-    qdev_set_netdev(dev, nd);
-    qdev_set_prop_int(dev, "txpingpong", txpingpong);
-    qdev_set_prop_int(dev, "rxpingpong", rxpingpong);
+    dev->nd = nd;
+    qdev_prop_set_uint32(dev, "txpingpong", txpingpong);
+    qdev_prop_set_uint32(dev, "rxpingpong", rxpingpong);
     qdev_init(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
     sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index f4b40c7..b3fd25b 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -53,8 +53,8 @@ struct xlx_ethlite
     qemu_irq irq;
     VLANClientState *vc;
 
-    unsigned int c_tx_pingpong;
-    unsigned int c_rx_pingpong;
+    uint32_t c_tx_pingpong;
+    uint32_t c_rx_pingpong;
     unsigned int txbuf;
     unsigned int rxbuf;
 
@@ -213,8 +213,6 @@ static void xilinx_ethlite_init(SysBusDevice *dev)
     int regs;
 
     sysbus_init_irq(dev, &s->irq);
-    s->c_tx_pingpong = qdev_get_prop_int(&dev->qdev, "txpingpong", 1);
-    s->c_rx_pingpong = qdev_get_prop_int(&dev->qdev, "rxpingpong", 1);
     s->rxbuf = 0;
 
     regs = cpu_register_io_memory(eth_read, eth_write, s);
@@ -225,10 +223,29 @@ static void xilinx_ethlite_init(SysBusDevice *dev)
                                  eth_can_rx, eth_rx, NULL, eth_cleanup, s);
 }
 
+static SysBusDeviceInfo xilinx_ethlite_info = {
+    .init = xilinx_ethlite_init,
+    .qdev.name  = "xilinx,ethlite",
+    .qdev.size  = sizeof(struct xlx_ethlite),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "txpingpong",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_ethlite, c_tx_pingpong),
+            .defval = (uint32_t[]) { 1 },
+        },{
+            .name   = "rxpingpong",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_ethlite, c_rx_pingpong),
+            .defval = (uint32_t[]) { 1 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_ethlite_register(void)
 {
-    sysbus_register_dev("xilinx,ethlite", sizeof (struct xlx_ethlite),
-                        xilinx_ethlite_init);
+    sysbus_register_withprop(&xilinx_ethlite_info);
 }
 
 device_init(xilinx_ethlite_register)
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 0540f52..3f08bf8 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -150,7 +150,6 @@ static void xilinx_intc_init(SysBusDevice *dev)
     struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev);
     int pic_regs;
 
-    p->c_kind_of_intr = qdev_get_prop_int(&dev->qdev, "kind-of-intr", 0);
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &p->parent_irq);
 
@@ -158,10 +157,23 @@ static void xilinx_intc_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, R_MAX * 4, pic_regs);
 }
 
+static SysBusDeviceInfo xilinx_intc_info = {
+    .init = xilinx_intc_init,
+    .qdev.name  = "xilinx,intc",
+    .qdev.size  = sizeof(struct xlx_pic),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "kind-of-intr",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct xlx_pic, c_kind_of_intr),
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_intc_register(void)
 {
-    sysbus_register_dev("xilinx,intc", sizeof (struct xlx_pic),
-                        xilinx_intc_init);
+    sysbus_register_withprop(&xilinx_intc_info);
 }
 
 device_init(xilinx_intc_register)
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index a64ad2d..efb6a04 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -61,7 +61,8 @@ struct timerblock
 {
     SysBusDevice busdev;
     qemu_irq irq;
-    unsigned int nr_timers;
+    uint32_t nr_timers;
+    uint32_t freq_hz;
     struct xlx_timer *timers;
 };
 
@@ -192,14 +193,12 @@ static void xilinx_timer_init(SysBusDevice *dev)
 {
     struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
     unsigned int i;
-    int timer_regs, freq_hz;
+    int timer_regs;
 
     /* All timers share a single irq line.  */
     sysbus_init_irq(dev, &t->irq);
 
     /* Init all the ptimers.  */
-    freq_hz = qdev_get_prop_int(&dev->qdev, "frequency", 2);
-    t->nr_timers = qdev_get_prop_int(&dev->qdev, "nr-timers", 2);
     t->timers = qemu_mallocz(sizeof t->timers[0] * t->nr_timers);
     for (i = 0; i < t->nr_timers; i++) {
         struct xlx_timer *xt = &t->timers[i];
@@ -208,17 +207,36 @@ static void xilinx_timer_init(SysBusDevice *dev)
         xt->nr = i;
         xt->bh = qemu_bh_new(timer_hit, xt);
         xt->ptimer = ptimer_init(xt->bh);
-        ptimer_set_freq(xt->ptimer, freq_hz);
+        ptimer_set_freq(xt->ptimer, t->freq_hz);
     }
 
     timer_regs = cpu_register_io_memory(timer_read, timer_write, t);
     sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs);
 }
 
+static SysBusDeviceInfo xilinx_timer_info = {
+    .init = xilinx_timer_init,
+    .qdev.name  = "xilinx,timer",
+    .qdev.size  = sizeof(struct timerblock),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "frequency",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct timerblock, freq_hz),
+            .defval = (uint32_t[]) { 2 },
+        },{
+            .name   = "nr-timers",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(struct timerblock, nr_timers),
+            .defval = (uint32_t[]) { 2 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void xilinx_timer_register(void)
 {
-    sysbus_register_dev("xilinx,timer", sizeof (struct timerblock),
-                        xilinx_timer_init);
+    sysbus_register_withprop(&xilinx_timer_info);
 }
 
 device_init(xilinx_timer_register)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2009-07-15  6:34 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-10 11:26 [Qemu-devel] [PATCH v2 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann
2009-07-10 17:13   ` Paul Brook
2009-07-10 19:28     ` Gerd Hoffmann
2009-07-10 19:42       ` Paul Brook
2009-07-10 20:10         ` Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 02/13] qdev: factor out driver search to qdev_find_info() Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 03/13] qdev/pci: make pci_create return DeviceState instead of PCIDevice Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 04/13] qdev: add generic qdev_device_add() Gerd Hoffmann
2009-07-10 17:23   ` Paul Brook
2009-07-10 20:27     ` Gerd Hoffmann
2009-07-10 20:51       ` Paul Brook
2009-07-14  7:40         ` Gerd Hoffmann
2009-07-14 23:43           ` Markus Armbruster
2009-07-15  1:28             ` Markus Armbruster
2009-07-15  6:26             ` Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 05/13] qdev: add -device command line option Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 06/13] qdev: add no_user, alias and desc Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 07/13] qdev: es1370 description Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 08/13] qdev: convert all vga Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 09/13] qdev/pci: hook up i440fx Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 10/13] qdev: add user-specified identifier to devices Gerd Hoffmann
2009-07-10 17:31   ` Paul Brook
2009-07-10 19:03     ` Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 11/13] switch balloon initialization to -device Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 12/13] qdev: add id= support for pci nics Gerd Hoffmann
2009-07-10 11:26 ` [Qemu-devel] [PATCH 13/13] qdev: print device id in "info pci" Gerd Hoffmann
  -- strict thread matches above, loose matches on Subject: below --
2009-07-03 10:22 [Qemu-devel] [PATCH 0/13] qdev patches: properties, -device switch, id=<tag> & more Gerd Hoffmann
2009-07-03 10:22 ` [Qemu-devel] [PATCH 01/13] qdev: rework device properties Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.