qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/6] qdev: rework device properties.


From: Gerd Hoffmann
Subject: [Qemu-devel] [PATCH 1/6] qdev: rework device properties.
Date: Wed, 15 Jul 2009 13:43:31 +0200

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 <address@hidden>
---
 Makefile              |    2 +-
 Makefile.hw           |    2 +-
 hw/arm_sysctl.c       |   20 +++-
 hw/armv7m.c           |   22 ++++-
 hw/axis_dev88.c       |    2 +-
 hw/eccmemctl.c        |   21 ++++-
 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/m48t59.c           |   39 ++++++--
 hw/mips_malta.c       |    4 +-
 hw/musicpal.c         |    2 +-
 hw/pc.c               |    4 +-
 hw/pci.c              |   17 +++-
 hw/pcnet.c            |   19 +++-
 hw/qdev-addr.c        |   32 +++++++
 hw/qdev-addr.h        |    2 +
 hw/qdev-properties.c  |  246 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c             |  141 ++++------------------------
 hw/qdev.h             |   73 ++++++++++-----
 hw/slavio_misc.c      |    6 -
 hw/smbus_eeprom.c     |   10 ++-
 hw/smc91c111.c        |    2 +-
 hw/stellaris.c        |    2 +-
 hw/sun4m.c            |    6 +-
 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/tcx.c              |   65 ++++++++++----
 hw/xilinx.h           |   12 +-
 hw/xilinx_ethlite.c   |   29 +++++-
 hw/xilinx_intc.c      |   18 +++-
 hw/xilinx_timer.c     |   32 +++++--
 40 files changed, 757 insertions(+), 302 deletions(-)
 create mode 100644 hw/qdev-addr.c
 create mode 100644 hw/qdev-addr.h
 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/Makefile.hw b/Makefile.hw
index f7a9507..571e518 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -26,7 +26,7 @@ obj-y += m48t59.o escc.o
 # SCSI layer
 obj-y += lsi53c895a.o esp.o
 
-obj-y += dma-helpers.o sysbus.o
+obj-y += dma-helpers.o sysbus.o qdev-addr.o
 
 all: $(HWLIB)
 # Dummy command so that make thinks it has done something
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/eccmemctl.c b/hw/eccmemctl.c
index d05962b..c5d6449 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -321,7 +321,6 @@ static void ecc_init1(SysBusDevice *dev)
     ECCState *s = FROM_SYSBUS(ECCState, dev);
 
     sysbus_init_irq(dev, &s->irq);
-    s->version = qdev_get_prop_int(&dev->qdev, "version", -1);
     s->regs[0] = s->version;
     ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s);
     sysbus_init_mmio(dev, ECC_SIZE, ecc_io_memory);
@@ -342,7 +341,7 @@ void ecc_init(target_phys_addr_t base, qemu_irq irq, 
uint32_t version)
     SysBusDevice *s;
 
     dev = qdev_create(NULL, "eccmemctl");
-    qdev_set_prop_int(dev, "version", version);
+    qdev_prop_set_uint32(dev, "version", version);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_connect_irq(s, 0, irq);
@@ -352,9 +351,25 @@ void ecc_init(target_phys_addr_t base, qemu_irq irq, 
uint32_t version)
     }
 }
 
+static SysBusDeviceInfo ecc_info = {
+    .init = ecc_init1,
+    .qdev.name  = "eccmemctl",
+    .qdev.size  = sizeof(ECCState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "version",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(ECCState, version),
+            .defval = (uint32_t[]) { -1 },
+        },
+        {/* end of list */}
+    }
+};
+
+
 static void ecc_register_devices(void)
 {
-    sysbus_register_dev("eccmemctl", sizeof(ECCState), ecc_init1);
+    sysbus_register_withprop(&ecc_info);
 }
 
 device_init(ecc_register_devices)
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/m48t59.c b/hw/m48t59.c
index 798d292..7e53dce 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -43,11 +43,11 @@
 struct m48t59_t {
     SysBusDevice busdev;
     /* Model parameters */
-    int type; // 2 = m48t02, 8 = m48t08, 59 = m48t59
+    uint32_t type; // 2 = m48t02, 8 = m48t08, 59 = m48t59
     /* Hardware parameters */
     qemu_irq IRQ;
     uint32_t io_base;
-    uint16_t size;
+    uint32_t size;
     /* RTC management */
     time_t   time_offset;
     time_t   stop_time;
@@ -623,9 +623,9 @@ m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t 
mem_base,
     m48t59_t *d;
 
     dev = qdev_create(NULL, "m48t59");
-    qdev_set_prop_int(dev, "type", type);
-    qdev_set_prop_int(dev, "size", size);
-    qdev_set_prop_int(dev, "io_base", io_base);
+    qdev_prop_set_uint32(dev, "type", type);
+    qdev_prop_set_uint32(dev, "size", size);
+    qdev_prop_set_uint32(dev, "io_base", io_base);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_connect_irq(s, 0, IRQ);
@@ -647,11 +647,8 @@ static void m48t59_init1(SysBusDevice *dev)
     m48t59_t *s = FROM_SYSBUS(m48t59_t, dev);
     int mem_index;
 
-    s->size = qdev_get_prop_int(&dev->qdev, "size", -1);
     s->buffer = qemu_mallocz(s->size);
     sysbus_init_irq(dev, &s->IRQ);
-    s->io_base = qdev_get_prop_int(&dev->qdev, "io_base", 0);
-    s->type = qdev_get_prop_int(&dev->qdev, "type", -1);
 
     mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
     sysbus_init_mmio(dev, s->size, mem_index);
@@ -666,9 +663,33 @@ static void m48t59_init1(SysBusDevice *dev)
     register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s);
 }
 
+static SysBusDeviceInfo m48t59_info = {
+    .init = m48t59_init1,
+    .qdev.name  = "m48t59",
+    .qdev.size  = sizeof(m48t59_t),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "size",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(m48t59_t, size),
+            .defval = (uint32_t[]) { -1 },
+        },{
+            .name   = "type",
+            .info   = &qdev_prop_uint32,
+            .offset = offsetof(m48t59_t, type),
+            .defval = (uint32_t[]) { -1 },
+        },{
+            .name   = "io_base",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(m48t59_t, io_base),
+        },
+        {/* end of list */}
+    }
+};
+
 static void m48t59_register_devices(void)
 {
-    sysbus_register_dev("m48t59", sizeof(m48t59_t), m48t59_init1);
+    sysbus_register_withprop(&m48t59_info);
 }
 
 device_init(m48t59_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 a6fb957..3232dda 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-addr.c b/hw/qdev-addr.c
new file mode 100644
index 0000000..305c2d3
--- /dev/null
+++ b/hw/qdev-addr.c
@@ -0,0 +1,32 @@
+#include "qdev.h"
+#include "qdev-addr.h"
+#include "targphys.h"
+
+/* --- target physical address --- */
+
+static int parse_taddr(DeviceState *dev, Property *prop, const char *str)
+{
+    target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+    *ptr = strtoull(str, NULL, 16);
+    return 0;
+}
+
+static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t 
len)
+{
+    target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr);
+}
+
+PropertyInfo qdev_prop_taddr = {
+    .name  = "taddr",
+    .type  = PROP_TYPE_TADDR,
+    .size  = sizeof(target_phys_addr_t),
+    .parse = parse_taddr,
+    .print = print_taddr,
+};
+
+void qdev_prop_set_taddr(DeviceState *dev, const char *name, 
target_phys_addr_t value)
+{
+    qdev_prop_set(dev, name, &value, PROP_TYPE_TADDR);
+}
diff --git a/hw/qdev-addr.h b/hw/qdev-addr.h
new file mode 100644
index 0000000..f02bd7a
--- /dev/null
+++ b/hw/qdev-addr.h
@@ -0,0 +1,2 @@
+extern PropertyInfo qdev_prop_taddr;
+void qdev_prop_set_taddr(DeviceState *dev, const char *name, 
target_phys_addr_t value);
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
new file mode 100644
index 0000000..8b0d0ff
--- /dev/null
+++ b/hw/qdev-properties.c
@@ -0,0 +1,246 @@
+#include "qdev.h"
+
+void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
+{
+    void *ptr = dev;
+    ptr += prop->offset;
+    return ptr;
+}
+
+/* --- 16bit integer --- */
+
+static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
+{
+    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    const char *fmt;
+
+    /* accept both hex and decimal */
+    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16;
+    if (sscanf(str, fmt, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t 
len)
+{
+    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "%" PRIu16, *ptr);
+}
+
+PropertyInfo qdev_prop_uint16 = {
+    .name  = "uint16",
+    .type  = PROP_TYPE_UINT16,
+    .size  = sizeof(uint16_t),
+    .parse = parse_uint16,
+    .print = print_uint16,
+};
+
+/* --- 32bit integer --- */
+
+static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
+{
+    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    const char *fmt;
+
+    /* accept both hex and decimal */
+    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32;
+    if (sscanf(str, fmt, ptr) != 1)
+        return -1;
+    return 0;
+}
+
+static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t 
len)
+{
+    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "%" PRIu32, *ptr);
+}
+
+PropertyInfo qdev_prop_uint32 = {
+    .name  = "uint32",
+    .type  = PROP_TYPE_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 = qdev_get_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 = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x%" PRIx32, *ptr);
+}
+
+PropertyInfo qdev_prop_hex32 = {
+    .name  = "hex32",
+    .type  = PROP_TYPE_UINT32,
+    .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 = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "<%p>", *ptr);
+}
+
+PropertyInfo qdev_prop_ptr = {
+    .name  = "ptr",
+    .type  = PROP_TYPE_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 = qdev_get_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 = qdev_get_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_macaddr = {
+    .name  = "mac-addr",
+    .type  = PROP_TYPE_MACADDR,
+    .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);
+}
+
+void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum 
PropertyType type)
+{
+    Property *prop;
+    void *dst;
+
+    prop = qdev_prop_find(dev, name);
+    if (!prop) {
+        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
+                __FUNCTION__, dev->info->name, name);
+        abort();
+    }
+    if (prop->info->type != type) {
+        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
+                __FUNCTION__, dev->info->name, name);
+        abort();
+    }
+    dst = qdev_get_prop_ptr(dev, prop);
+    memcpy(dst, src, prop->info->size);
+}
+
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
+{
+    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
+}
+
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
+{
+    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
+}
+
+void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
+{
+    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
+}
+
+void qdev_prop_set_defaults(DeviceState *dev, Property *props)
+{
+    char *dst;
+
+    if (!props)
+        return;
+    while (props->name) {
+        if (props->defval) {
+            dst = qdev_get_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..9ecc9ec 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,36 @@ struct BusState {
     LIST_ENTRY(BusState) sibling;
 };
 
+struct Property {
+    const char   *name;
+    PropertyInfo *info;
+    int          offset;
+    void         *defval;
+};
+
+enum PropertyType {
+    PROP_TYPE_UNSPEC = 0,
+    PROP_TYPE_UINT16,
+    PROP_TYPE_UINT32,
+    PROP_TYPE_TADDR,
+    PROP_TYPE_MACADDR,
+    PROP_TYPE_PTR,
+};
+
+struct PropertyInfo {
+    const char *name;
+    size_t size;
+    enum PropertyType type;
+    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 +81,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 +88,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 +108,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 +129,22 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, 
const char *name);
 
 void do_info_qtree(Monitor *mon);
 
+/*** qdev-properties.c ***/
+
+extern PropertyInfo qdev_prop_uint16;
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_ptr;
+extern PropertyInfo qdev_prop_macaddr;
+
+/* Set properties between creation and init.  */
+void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
+int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
+void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum 
PropertyType type);
+void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
+void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
+/* FIXME: Remove opaque pointer properties.  */
+void 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/slavio_misc.c b/hw/slavio_misc.c
index 3d246ee..23012a3 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -564,18 +564,12 @@ static SysBusDeviceInfo slavio_misc_info = {
     .init = slavio_misc_init1,
     .qdev.name  = "slavio_misc",
     .qdev.size  = sizeof(MiscState),
-    .qdev.props = (DevicePropList[]) {
-        {.name = NULL}
-    }
 };
 
 static SysBusDeviceInfo apc_info = {
     .init = apc_init1,
     .qdev.name  = "apc",
     .qdev.size  = sizeof(MiscState),
-    .qdev.props = (DevicePropList[]) {
-        {.name = NULL}
-    }
 };
 
 static void slavio_misc_register_devices(void)
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 f3fe11c..b24f7a8 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);
@@ -410,9 +409,6 @@ static SysBusDeviceInfo idreg_info = {
     .init = idreg_init1,
     .qdev.name  = "macio_idreg",
     .qdev.size  = sizeof(SysBusDevice),
-    .qdev.props = (DevicePropList[]) {
-        {.name = NULL}
-    }
 };
 
 static void idreg_register_devices(void)
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/tcx.c b/hw/tcx.c
index d9b07cc..9335b42 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -26,6 +26,7 @@
 #include "console.h"
 #include "pixel_ops.h"
 #include "sysbus.h"
+#include "qdev-addr.h"
 
 #define MAXX 1024
 #define MAXY 768
@@ -41,6 +42,7 @@ typedef struct TCXState {
     uint8_t *vram;
     uint32_t *vram24, *cplane;
     ram_addr_t vram_offset, vram24_offset, cplane_offset;
+    uint32_t vram_size;
     uint16_t width, height, depth;
     uint8_t r[256], g[256], b[256];
     uint32_t palette[256];
@@ -506,11 +508,11 @@ void tcx_init(target_phys_addr_t addr, int vram_size, int 
width, int height,
     SysBusDevice *s;
 
     dev = qdev_create(NULL, "SUNW,tcx");
-    qdev_set_prop_int(dev, "addr", addr);
-    qdev_set_prop_int(dev, "vram_size", vram_size);
-    qdev_set_prop_int(dev, "width", width);
-    qdev_set_prop_int(dev, "height", height);
-    qdev_set_prop_int(dev, "depth", depth);
+    qdev_prop_set_taddr(dev, "addr", addr);
+    qdev_prop_set_uint32(dev, "vram_size", vram_size);
+    qdev_prop_set_uint16(dev, "width", width);
+    qdev_prop_set_uint16(dev, "height", height);
+    qdev_prop_set_uint16(dev, "depth", depth);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     /* 8-bit plane */
@@ -537,22 +539,16 @@ static void tcx_init1(SysBusDevice *dev)
     TCXState *s = FROM_SYSBUS(TCXState, dev);
     int io_memory, dummy_memory;
     ram_addr_t vram_offset;
-    int size, vram_size;
+    int size;
     uint8_t *vram_base;
 
-    vram_size = qdev_get_prop_int(&dev->qdev, "vram_size", -1);
-
-    vram_offset = qemu_ram_alloc(vram_size * (1 + 4 + 4));
+    vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4));
     vram_base = qemu_get_ram_ptr(vram_offset);
-    s->addr = qdev_get_prop_int(&dev->qdev, "addr", -1);
     s->vram_offset = vram_offset;
-    s->width = qdev_get_prop_int(&dev->qdev, "width", -1);
-    s->height = qdev_get_prop_int(&dev->qdev, "height", -1);
-    s->depth = qdev_get_prop_int(&dev->qdev, "depth", -1);
 
     /* 8-bit plane */
     s->vram = vram_base;
-    size = vram_size;
+    size = s->vram_size;
     sysbus_init_mmio(dev, size, s->vram_offset);
     vram_offset += size;
     vram_base += size;
@@ -570,7 +566,7 @@ static void tcx_init1(SysBusDevice *dev)
 
     if (s->depth == 24) {
         /* 24-bit plane */
-        size = vram_size * 4;
+        size = s->vram_size * 4;
         s->vram24 = (uint32_t *)vram_base;
         s->vram24_offset = vram_offset;
         sysbus_init_mmio(dev, size, vram_offset);
@@ -578,7 +574,7 @@ static void tcx_init1(SysBusDevice *dev)
         vram_base += size;
 
         /* Control plane */
-        size = vram_size * 4;
+        size = s->vram_size * 4;
         s->cplane = (uint32_t *)vram_base;
         s->cplane_offset = vram_offset;
         sysbus_init_mmio(dev, size, vram_offset);
@@ -664,9 +660,44 @@ static void tcx24_screen_dump(void *opaque, const char 
*filename)
     return;
 }
 
+static SysBusDeviceInfo tcx_info = {
+    .init = tcx_init1,
+    .qdev.name  = "SUNW,tcx",
+    .qdev.size  = sizeof(TCXState),
+    .qdev.props = (Property[]) {
+        {
+            .name   = "addr",
+            .info   = &qdev_prop_taddr,
+            .offset = offsetof(TCXState, addr),
+            .defval = (target_phys_addr_t[]) { -1 },
+        },{
+            .name   = "vram_size",
+            .info   = &qdev_prop_hex32,
+            .offset = offsetof(TCXState, vram_size),
+            .defval = (uint32_t[]) { -1 },
+        },{
+            .name   = "width",
+            .info   = &qdev_prop_uint16,
+            .offset = offsetof(TCXState, width),
+            .defval = (uint16_t[]) { -1 },
+        },{
+            .name   = "height",
+            .info   = &qdev_prop_uint16,
+            .offset = offsetof(TCXState, height),
+            .defval = (uint16_t[]) { -1 },
+        },{
+            .name   = "depth",
+            .info   = &qdev_prop_uint16,
+            .offset = offsetof(TCXState, depth),
+            .defval = (uint16_t[]) { -1 },
+        },
+        {/* end of list */}
+    }
+};
+
 static void tcx_register_devices(void)
 {
-    sysbus_register_dev("SUNW,tcx", sizeof(TCXState), tcx_init1);
+    sysbus_register_withprop(&tcx_info);
 }
 
 device_init(tcx_register_devices)
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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]