summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/virtio-9p-device.c48
-rw-r--r--hw/a9mpcore.c46
-rw-r--r--hw/ac97.c87
-rw-r--r--hw/acpi_piix4.c63
-rw-r--r--hw/adlib.c2
-rw-r--r--hw/ads7846.c20
-rw-r--r--hw/alpha_pci.c6
-rw-r--r--hw/alpha_typhoon.c21
-rw-r--r--hw/apb_pci.c84
-rw-r--r--hw/apic.c365
-rw-r--r--hw/apic.h1
-rw-r--r--hw/apic_common.c321
-rw-r--r--hw/apic_internal.h122
-rw-r--r--hw/applesmc.c34
-rw-r--r--hw/arm-misc.h17
-rw-r--r--hw/arm11mpcore.c75
-rw-r--r--hw/arm_boot.c65
-rw-r--r--hw/arm_gic.c68
-rw-r--r--hw/arm_l2x0.c35
-rw-r--r--hw/arm_mptimer.c35
-rw-r--r--hw/arm_sysctl.c35
-rw-r--r--hw/arm_timer.c54
-rw-r--r--hw/armv7m.c29
-rw-r--r--hw/armv7m_nvic.c42
-rw-r--r--hw/bitbang_i2c.c21
-rw-r--r--hw/boards.h1
-rw-r--r--hw/bonito.c55
-rw-r--r--hw/ccid-card-emulated.c48
-rw-r--r--hw/ccid-card-passthru.c41
-rw-r--r--hw/ccid.h27
-rw-r--r--hw/cirrus_vga.c115
-rw-r--r--hw/cirrus_vga_template.h102
-rw-r--r--hw/container.c20
-rw-r--r--hw/cs4231.c31
-rw-r--r--hw/cs4231a.c50
-rw-r--r--hw/debugcon.c32
-rw-r--r--hw/dec_pci.c82
-rw-r--r--hw/ds1225y.c33
-rw-r--r--hw/ds1338.c34
-rw-r--r--hw/e1000.c57
-rw-r--r--hw/eccmemctl.c33
-rw-r--r--hw/eepro100.c207
-rw-r--r--hw/empty_slot.c18
-rw-r--r--hw/es1370.c74
-rw-r--r--hw/escc.c47
-rw-r--r--hw/esp.c31
-rw-r--r--hw/etraxfs_eth.c37
-rw-r--r--hw/etraxfs_pic.c29
-rw-r--r--hw/etraxfs_ser.c23
-rw-r--r--hw/etraxfs_timer.c17
-rw-r--r--hw/fdc.c110
-rw-r--r--hw/framebuffer.c9
-rw-r--r--hw/fw_cfg.c37
-rw-r--r--hw/g364fb.c51
-rw-r--r--hw/grackle_pci.c49
-rw-r--r--hw/grlib_apbuart.c135
-rw-r--r--hw/grlib_gptimer.c35
-rw-r--r--hw/grlib_irqmp.c33
-rw-r--r--hw/gt64xxx.c43
-rw-r--r--hw/gus.c58
-rw-r--r--hw/hda-audio.c64
-rw-r--r--hw/highbank.c339
-rw-r--r--hw/hpet.c37
-rw-r--r--hw/i2c.c116
-rw-r--r--hw/i2c.h51
-rw-r--r--hw/i82374.c165
-rw-r--r--hw/i82378.c275
-rw-r--r--hw/i8254.c36
-rw-r--r--hw/i8259.c173
-rw-r--r--hw/i8259_common.c161
-rw-r--r--hw/i8259_internal.h82
-rw-r--r--hw/ide/ahci.c53
-rw-r--r--hw/ide/cmd646.c43
-rw-r--r--hw/ide/ich.c38
-rw-r--r--hw/ide/internal.h20
-rw-r--r--hw/ide/isa.c36
-rw-r--r--hw/ide/pci.c4
-rw-r--r--hw/ide/piix.c97
-rw-r--r--hw/ide/qdev.c136
-rw-r--r--hw/ide/via.c31
-rw-r--r--hw/integratorcp.c45
-rw-r--r--hw/intel-hda.c104
-rw-r--r--hw/intel-hda.h25
-rw-r--r--hw/ioapic.c149
-rw-r--r--hw/ioapic_common.c121
-rw-r--r--hw/ioapic_internal.h102
-rw-r--r--hw/ioh3420.c63
-rw-r--r--hw/isa-bus.c63
-rw-r--r--hw/isa.h21
-rw-r--r--hw/ivshmem.c51
-rw-r--r--hw/kvm/apic.c147
-rw-r--r--hw/kvm/clock.c (renamed from hw/kvmclock.c)27
-rw-r--r--hw/kvm/clock.h (renamed from hw/kvmclock.h)0
-rw-r--r--hw/kvm/i8259.c138
-rw-r--r--hw/kvm/ioapic.c125
-rw-r--r--hw/lan9118.c159
-rw-r--r--hw/lance.c37
-rw-r--r--hw/lm32_juart.c25
-rw-r--r--hw/lm32_pic.c23
-rw-r--r--hw/lm32_sys.c33
-rw-r--r--hw/lm32_timer.c35
-rw-r--r--hw/lm32_uart.c25
-rw-r--r--hw/lm832x.c37
-rw-r--r--hw/loader.c6
-rw-r--r--hw/lsi53c895a.c36
-rw-r--r--hw/m48t59.c75
-rw-r--r--hw/macio.c51
-rw-r--r--hw/marvell_88w8618_audio.c39
-rw-r--r--hw/max111x.c40
-rw-r--r--hw/max7310.c39
-rw-r--r--hw/mc146818rtc.c66
-rw-r--r--hw/milkymist-ac97.c23
-rw-r--r--hw/milkymist-hpdmc.c23
-rw-r--r--hw/milkymist-memcard.c23
-rw-r--r--hw/milkymist-minimac2.c41
-rw-r--r--hw/milkymist-pfpu.c23
-rw-r--r--hw/milkymist-softusb.c47
-rw-r--r--hw/milkymist-sysctl.c47
-rw-r--r--hw/milkymist-tmu2.c23
-rw-r--r--hw/milkymist-uart.c25
-rw-r--r--hw/milkymist-vgafb.c35
-rw-r--r--hw/milkymist-vgafb_template.h2
-rw-r--r--hw/mips_malta.c27
-rw-r--r--hw/mipsnet.c37
-rw-r--r--hw/mpc8544_guts.c18
-rw-r--r--hw/msi.c8
-rw-r--r--hw/msi.h2
-rw-r--r--hw/msix.c9
-rw-r--r--hw/msix.h2
-rw-r--r--hw/mst_fpga.c23
-rw-r--r--hw/musicpal.c182
-rw-r--r--hw/nand.c37
-rw-r--r--hw/ne2000-isa.c34
-rw-r--r--hw/ne2000.c41
-rw-r--r--hw/omap_gpio.c78
-rw-r--r--hw/omap_intc.c70
-rw-r--r--hw/onenand.c39
-rw-r--r--hw/opencores_eth.c35
-rw-r--r--hw/openpic.c30
-rw-r--r--hw/openpic.h2
-rw-r--r--hw/parallel.c34
-rw-r--r--hw/pc.c51
-rw-r--r--hw/pc.h9
-rw-r--r--hw/pc_piix.c75
-rw-r--r--hw/pci.c179
-rw-r--r--hw/pci.h84
-rw-r--r--hw/pci_bridge.c2
-rw-r--r--hw/pci_ids.h4
-rw-r--r--hw/pcie.c2
-rw-r--r--hw/pckbd.c22
-rw-r--r--hw/pcnet-pci.c43
-rw-r--r--hw/pcnet.c5
-rw-r--r--hw/piix4.c37
-rw-r--r--hw/piix_pci.c140
-rw-r--r--hw/pl011.c40
-rw-r--r--hw/pl022.c16
-rw-r--r--hw/pl031.c23
-rw-r--r--hw/pl041.c38
-rw-r--r--hw/pl050.c42
-rw-r--r--hw/pl061.c42
-rw-r--r--hw/pl080.c46
-rw-r--r--hw/pl110.c69
-rw-r--r--hw/pl181.c25
-rw-r--r--hw/pl190.c25
-rw-r--r--hw/ppc440.c106
-rw-r--r--hw/ppc440.h21
-rw-r--r--hw/ppc440_bamboo.c154
-rw-r--r--hw/ppc4xx_pci.c147
-rw-r--r--hw/ppc_newworld.c2
-rw-r--r--hw/ppc_prep.c82
-rw-r--r--hw/ppce500_pci.c46
-rw-r--r--hw/ppce500_spin.c18
-rw-r--r--hw/prep_pci.c184
-rw-r--r--hw/prep_pci.h11
-rw-r--r--hw/pxa2xx.c108
-rw-r--r--hw/pxa2xx_dma.c33
-rw-r--r--hw/pxa2xx_gpio.c33
-rw-r--r--hw/pxa2xx_pic.c23
-rw-r--r--hw/pxa2xx_timer.c74
-rw-r--r--hw/qdev-addr.c6
-rw-r--r--hw/qdev-monitor.c588
-rw-r--r--hw/qdev-properties.c132
-rw-r--r--hw/qdev.c1141
-rw-r--r--hw/qdev.h363
-rw-r--r--hw/qxl.c77
-rw-r--r--hw/realview.c20
-rw-r--r--hw/realview_gic.c24
-rw-r--r--hw/rtl8139.c47
-rw-r--r--hw/s390-virtio-bus.c156
-rw-r--r--hw/s390-virtio-bus.h19
-rw-r--r--hw/s390-virtio.c1
-rw-r--r--hw/sb16.c140
-rw-r--r--hw/sbi.c23
-rw-r--r--hw/scsi-bus.c104
-rw-r--r--hw/scsi-disk.c187
-rw-r--r--hw/scsi-generic.c41
-rw-r--r--hw/scsi.h30
-rw-r--r--hw/serial.c36
-rw-r--r--hw/sga.c21
-rw-r--r--hw/sh_pci.c41
-rw-r--r--hw/slavio_intctl.c23
-rw-r--r--hw/slavio_misc.c41
-rw-r--r--hw/slavio_timer.c33
-rw-r--r--hw/sm501.c11
-rw-r--r--hw/smbus.c85
-rw-r--r--hw/smbus.h40
-rw-r--r--hw/smbus_eeprom.c39
-rw-r--r--hw/smc91c111.c35
-rw-r--r--hw/spapr.c136
-rw-r--r--hw/spapr_llan.c43
-rw-r--r--hw/spapr_pci.c208
-rw-r--r--hw/spapr_vio.c85
-rw-r--r--hw/spapr_vio.h34
-rw-r--r--hw/spapr_vscsi.c39
-rw-r--r--hw/spapr_vty.c39
-rw-r--r--hw/sparc32_dma.c35
-rw-r--r--hw/spitz.c110
-rw-r--r--hw/ssd0303.c37
-rw-r--r--hw/ssd0323.c20
-rw-r--r--hw/ssi-sd.c20
-rw-r--r--hw/ssi.c39
-rw-r--r--hw/ssi.h18
-rw-r--r--hw/stellaris.c71
-rw-r--r--hw/stellaris_enet.c31
-rw-r--r--hw/strongarm.c148
-rw-r--r--hw/sun4c_intctl.c23
-rw-r--r--hw/sun4m.c92
-rw-r--r--hw/sun4m_iommu.c33
-rw-r--r--hw/sun4u.c82
-rw-r--r--hw/sysbus.c50
-rw-r--r--hw/sysbus.h23
-rw-r--r--hw/tcx.c74
-rw-r--r--hw/tmp105.c41
-rw-r--r--hw/tosa.c54
-rw-r--r--hw/tusb6010.c21
-rw-r--r--hw/twl92230.c39
-rw-r--r--hw/unin_pci.c220
-rw-r--r--hw/usb-audio.c715
-rw-r--r--hw/usb-bt.c57
-rw-r--r--hw/usb-bus.c196
-rw-r--r--hw/usb-ccid.c142
-rw-r--r--hw/usb-desc.c161
-rw-r--r--hw/usb-desc.h5
-rw-r--r--hw/usb-ehci.c70
-rw-r--r--hw/usb-hid.c123
-rw-r--r--hw/usb-hub.c44
-rw-r--r--hw/usb-msd.c66
-rw-r--r--hw/usb-musb.c3
-rw-r--r--hw/usb-net.c66
-rw-r--r--hw/usb-ohci.c80
-rw-r--r--hw/usb-serial.c103
-rw-r--r--hw/usb-uhci.c204
-rw-r--r--hw/usb-wacom.c46
-rw-r--r--hw/usb-xhci.c2759
-rw-r--r--hw/usb.c147
-rw-r--r--hw/usb.h93
-rw-r--r--hw/versatile_pci.c58
-rw-r--r--hw/versatilepb.c23
-rw-r--r--hw/vexpress.c1
-rw-r--r--hw/vga-isa.c22
-rw-r--r--hw/vga-pci.c31
-rw-r--r--hw/vga.c397
-rw-r--r--hw/vga.h159
-rw-r--r--hw/vga_int.h16
-rw-r--r--hw/vga_template.h74
-rw-r--r--hw/vhost.c2
-rw-r--r--hw/virtex_ml507.c1
-rw-r--r--hw/virtio-blk.c2
-rw-r--r--hw/virtio-console.c77
-rw-r--r--hw/virtio-net.c2
-rw-r--r--hw/virtio-pci.c242
-rw-r--r--hw/virtio-serial-bus.c77
-rw-r--r--hw/virtio-serial.h85
-rw-r--r--hw/virtio.c12
-rw-r--r--hw/vmmouse.c36
-rw-r--r--hw/vmport.c20
-rw-r--r--hw/vmware_vga.c38
-rw-r--r--hw/vmware_vga.h8
-rw-r--r--hw/vt82c686.c136
-rw-r--r--hw/wdt_i6300esb.c37
-rw-r--r--hw/wdt_ib700.c22
-rw-r--r--hw/wm8750.c41
-rw-r--r--hw/xen_platform.c38
-rw-r--r--hw/xgmac.c433
-rw-r--r--hw/xilinx_axidma.c31
-rw-r--r--hw/xilinx_axienet.c39
-rw-r--r--hw/xilinx_ethlite.c35
-rw-r--r--hw/xilinx_intc.c29
-rw-r--r--hw/xilinx_timer.c31
-rw-r--r--hw/xilinx_uartlite.c19
-rw-r--r--hw/xio3130_downstream.c63
-rw-r--r--hw/xio3130_upstream.c57
-rw-r--r--hw/z2.c60
-rw-r--r--hw/zaurus.c31
294 files changed, 16283 insertions, 7096 deletions
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 41a1a820e0..791a5572bb 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -154,29 +154,39 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev)
return 0;
}
-static PCIDeviceInfo virtio_9p_info = {
- .qdev.name = "virtio-9p-pci",
- .qdev.size = sizeof(VirtIOPCIProxy),
- .init = virtio_9p_init_pci,
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = 0x1009,
- .revision = VIRTIO_PCI_ABI_VERSION,
- .class_id = 0x2,
- .qdev.props = (Property[]) {
- DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
- VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
- DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
- DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
- DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = virtio_pci_reset,
+static Property virtio_9p_properties[] = {
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+ DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_9p_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_9p_init_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = 0x1009;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = 0x2;
+ dc->props = virtio_9p_properties;
+ dc->reset = virtio_pci_reset;
+}
+
+static TypeInfo virtio_9p_info = {
+ .name = "virtio-9p-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_9p_class_init,
};
static void virtio_9p_register_devices(void)
{
- pci_qdev_register(&virtio_9p_info);
+ type_register_static(&virtio_9p_info);
virtio_9p_set_fd_limit();
}
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e138c4..19de12b4b4 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
#include "sysbus.h"
/* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
*/
-#define GIC_NIRQ 96
#define NCPU 4
static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
MemoryRegion ptimer_iomem;
MemoryRegion container;
DeviceState *mptimer;
+ uint32_t num_irq;
} a9mp_priv_state;
static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
}
- gic_init(&s->gic, s->num_cpu);
+ gic_init(&s->gic, s->num_cpu, s->num_irq);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -208,21 +208,39 @@ static const VMStateDescription vmstate_a9mp_priv = {
}
};
-static SysBusDeviceInfo a9mp_priv_info = {
- .init = a9mp_priv_init,
- .qdev.name = "a9mpcore_priv",
- .qdev.size = sizeof(a9mp_priv_state),
- .qdev.vmsd = &vmstate_a9mp_priv,
- .qdev.reset = a9mp_priv_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property a9mp_priv_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+ /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+ * IRQ lines (with another 32 internal). We default to 64+32, which
+ * is the number provided by the Cortex-A9MP test chip in the
+ * Realview PBX-A9 and Versatile Express A9 development boards.
+ * Other boards may differ and should set this property appropriately.
+ */
+ DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void a9mp_priv_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = a9mp_priv_init;
+ dc->props = a9mp_priv_properties;
+ dc->vmsd = &vmstate_a9mp_priv;
+ dc->reset = a9mp_priv_reset;
+}
+
+static TypeInfo a9mp_priv_info = {
+ .name = "a9mpcore_priv",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(a9mp_priv_state),
+ .class_init = a9mp_priv_class_init,
};
static void a9mp_register_devices(void)
{
- sysbus_register_withprop(&a9mp_priv_info);
+ type_register_static(&a9mp_priv_info);
}
device_init(a9mp_register_devices)
diff --git a/hw/ac97.c b/hw/ac97.c
index 03be99b08a..7bf9171487 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1175,17 +1175,17 @@ static const VMStateDescription vmstate_ac97_bm_regs = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
- VMSTATE_UINT32(bdbar, AC97BusMasterRegs),
- VMSTATE_UINT8(civ, AC97BusMasterRegs),
- VMSTATE_UINT8(lvi, AC97BusMasterRegs),
- VMSTATE_UINT16(sr, AC97BusMasterRegs),
- VMSTATE_UINT16(picb, AC97BusMasterRegs),
- VMSTATE_UINT8(piv, AC97BusMasterRegs),
- VMSTATE_UINT8(cr, AC97BusMasterRegs),
- VMSTATE_UINT32(bd_valid, AC97BusMasterRegs),
- VMSTATE_UINT32(bd.addr, AC97BusMasterRegs),
- VMSTATE_UINT32(bd.ctl_len, AC97BusMasterRegs),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (bdbar, AC97BusMasterRegs),
+ VMSTATE_UINT8 (civ, AC97BusMasterRegs),
+ VMSTATE_UINT8 (lvi, AC97BusMasterRegs),
+ VMSTATE_UINT16 (sr, AC97BusMasterRegs),
+ VMSTATE_UINT16 (picb, AC97BusMasterRegs),
+ VMSTATE_UINT8 (piv, AC97BusMasterRegs),
+ VMSTATE_UINT8 (cr, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd_valid, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd.addr, AC97BusMasterRegs),
+ VMSTATE_UINT32 (bd.ctl_len, AC97BusMasterRegs),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1224,15 +1224,15 @@ static const VMStateDescription vmstate_ac97 = {
.minimum_version_id_old = 2,
.post_load = ac97_post_load,
.fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(dev, AC97LinkState),
- VMSTATE_UINT32(glob_cnt, AC97LinkState),
- VMSTATE_UINT32(glob_sta, AC97LinkState),
- VMSTATE_UINT32(cas, AC97LinkState),
- VMSTATE_STRUCT_ARRAY(bm_regs, AC97LinkState, 3, 1,
- vmstate_ac97_bm_regs, AC97BusMasterRegs),
- VMSTATE_BUFFER(mixer_data, AC97LinkState),
- VMSTATE_UNUSED_TEST(is_version_2, 3),
- VMSTATE_END_OF_LIST()
+ VMSTATE_PCI_DEVICE (dev, AC97LinkState),
+ VMSTATE_UINT32 (glob_cnt, AC97LinkState),
+ VMSTATE_UINT32 (glob_sta, AC97LinkState),
+ VMSTATE_UINT32 (cas, AC97LinkState),
+ VMSTATE_STRUCT_ARRAY (bm_regs, AC97LinkState, 3, 1,
+ vmstate_ac97_bm_regs, AC97BusMasterRegs),
+ VMSTATE_BUFFER (mixer_data, AC97LinkState),
+ VMSTATE_UNUSED_TEST (is_version_2, 3),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1243,7 +1243,7 @@ static const MemoryRegionPortio nam_portio[] = {
{ 0, 256 * 1, 1, .write = nam_writeb, },
{ 0, 256 * 2, 2, .write = nam_writew, },
{ 0, 256 * 4, 4, .write = nam_writel, },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static const MemoryRegionOps ac97_io_nam_ops = {
@@ -1257,7 +1257,7 @@ static const MemoryRegionPortio nabm_portio[] = {
{ 0, 64 * 1, 1, .write = nabm_writeb, },
{ 0, 64 * 2, 2, .write = nabm_writew, },
{ 0, 64 * 4, 4, .write = nabm_writel, },
- PORTIO_END_OF_LIST()
+ PORTIO_END_OF_LIST ()
};
static const MemoryRegionOps ac97_io_nabm_ops = {
@@ -1344,26 +1344,37 @@ int ac97_init (PCIBus *bus)
return 0;
}
-static PCIDeviceInfo ac97_info = {
- .qdev.name = "AC97",
- .qdev.desc = "Intel 82801AA AC97 Audio",
- .qdev.size = sizeof (AC97LinkState),
- .qdev.vmsd = &vmstate_ac97,
- .init = ac97_initfn,
- .exit = ac97_exitfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801AA_5,
- .revision = 0x01,
- .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ac97_properties[] = {
+ DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0),
+ DEFINE_PROP_END_OF_LIST (),
+};
+
+static void ac97_class_init (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
+
+ k->init = ac97_initfn;
+ k->exit = ac97_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ dc->desc = "Intel 82801AA AC97 Audio";
+ dc->vmsd = &vmstate_ac97;
+ dc->props = ac97_properties;
+}
+
+static TypeInfo ac97_info = {
+ .name = "AC97",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof (AC97LinkState),
+ .class_init = ac97_class_init,
};
static void ac97_register (void)
{
- pci_qdev_register (&ac97_info);
+ type_register_static (&ac97_info);
}
device_init (ac97_register);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index bdc55a1eaa..21484aec42 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -280,11 +280,11 @@ static void piix4_update_hotplug(PIIX4PMState *s)
s->pci0_hotplug_enable = ~0;
QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
- PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
- PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *pdev = PCI_DEVICE(qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
int slot = PCI_SLOT(pdev->devfn);
- if (info->no_hotplug) {
+ if (pc->no_hotplug) {
s->pci0_hotplug_enable &= ~(1 << slot);
}
}
@@ -396,28 +396,39 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
return s->smb.smbus;
}
-static PCIDeviceInfo piix4_pm_info = {
- .qdev.name = "PIIX4_PM",
- .qdev.desc = "PM",
- .qdev.size = sizeof(PIIX4PMState),
- .qdev.vmsd = &vmstate_acpi,
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = piix4_pm_initfn,
- .config_write = pm_write_config,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371AB_3,
- .revision = 0x03,
- .class_id = PCI_CLASS_BRIDGE_OTHER,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property piix4_pm_properties[] = {
+ DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void piix4_pm_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = piix4_pm_initfn;
+ k->config_write = pm_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+ dc->desc = "PM";
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_acpi;
+ dc->props = piix4_pm_properties;
+}
+
+static TypeInfo piix4_pm_info = {
+ .name = "PIIX4_PM",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX4PMState),
+ .class_init = piix4_pm_class_init,
};
static void piix4_pm_register(void)
{
- pci_qdev_register(&piix4_pm_info);
+ type_register_static(&piix4_pm_info);
}
device_init(piix4_pm_register);
@@ -485,14 +496,12 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
{
BusState *bus = opaque;
DeviceState *qdev, *next;
- PCIDevice *dev;
- PCIDeviceInfo *info;
int slot = ffs(val) - 1;
QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
- dev = DO_UPCAST(PCIDevice, qdev, qdev);
- info = container_of(qdev->info, PCIDeviceInfo, qdev);
- if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
+ PCIDevice *dev = PCI_DEVICE(qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+ if (PCI_SLOT(dev->devfn) == slot && !pc->no_hotplug) {
qdev_free(qdev);
}
}
@@ -553,7 +562,7 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
{
int slot = PCI_SLOT(dev->devfn);
PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
- DO_UPCAST(PCIDevice, qdev, qdev));
+ PCI_DEVICE(qdev));
/* Don't send event when device is enabled during qemu machine creation:
* it is present on boot, no hotplug event is necessary. We do send an
diff --git a/hw/adlib.c b/hw/adlib.c
index dd8b1888cf..d39cd97384 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -164,7 +164,7 @@ static void timer_handler (int c, double interval_Sec)
s->ticking[n] = 1;
#ifdef DEBUG
- interval = get_ticks_per_sec() * interval_Sec;
+ interval = get_ticks_per_sec () * interval_Sec;
exp = qemu_get_clock_ns (vm_clock) + interval;
s->exp[n] = exp;
#endif
diff --git a/hw/ads7846.c b/hw/ads7846.c
index de3f7af127..3cfdecbe5c 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -153,16 +153,24 @@ static int ads7846_init(SSISlave *dev)
return 0;
}
-static SSISlaveInfo ads7846_info = {
- .qdev.name ="ads7846",
- .qdev.size = sizeof(ADS7846State),
- .init = ads7846_init,
- .transfer = ads7846_transfer
+static void ads7846_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = ads7846_init;
+ k->transfer = ads7846_transfer;
+}
+
+static TypeInfo ads7846_info = {
+ .name = "ads7846",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(ADS7846State),
+ .class_init = ads7846_class_init,
};
static void ads7846_register_devices(void)
{
- ssi_register_slave(&ads7846_info);
+ type_register_static(&ads7846_info);
}
device_init(ads7846_register_devices)
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
index e9757028af..673557781e 100644
--- a/hw/alpha_pci.c
+++ b/hw/alpha_pci.c
@@ -121,10 +121,8 @@ void alpha_pci_vga_setup(PCIBus *pci_bus)
pci_cirrus_vga_init(pci_bus);
return;
case VGA_VMWARE:
- if (pci_vmsvga_init(pci_bus)) {
- return;
- }
- break;
+ pci_vmsvga_init(pci_bus);
+ return;
}
/* If VGA is enabled at all, and one of the above didn't work, then
fallback to Standard VGA. */
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 7d924a3f08..736c28a3a9 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -808,15 +808,24 @@ static int typhoon_pcihost_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo typhoon_pcihost_info = {
- .init = typhoon_pcihost_init,
- .qdev.name = "typhoon-pcihost",
- .qdev.size = sizeof(TyphoonState),
- .qdev.no_user = 1
+static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = typhoon_pcihost_init;
+ dc->no_user = 1;
+}
+
+static TypeInfo typhoon_pcihost_info = {
+ .name = "typhoon-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TyphoonState),
+ .class_init = typhoon_pcihost_class_init,
};
static void typhoon_register(void)
{
- sysbus_register_withprop(&typhoon_pcihost_info);
+ type_register_static(&typhoon_pcihost_info);
}
device_init(typhoon_register);
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 3a1b111455..c7aaa72d07 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -350,7 +350,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
sysbus_connect_irq(s, i, pic[i]);
}
- pci_create_simple(d->bus, 0, "pbm");
+ pci_create_simple(d->bus, 0, "pbm-pci");
/* APB secondary busses */
pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
@@ -436,42 +436,68 @@ static int pbm_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo pbm_pci_host_info = {
- .qdev.name = "pbm",
- .qdev.size = sizeof(PCIDevice),
- .init = pbm_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_SUN,
- .device_id = PCI_DEVICE_ID_SUN_SABRE,
- .class_id = PCI_CLASS_BRIDGE_HOST,
- .is_bridge = 1,
+static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pbm_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_SUN;
+ k->device_id = PCI_DEVICE_ID_SUN_SABRE;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ k->is_bridge = 1;
+}
+
+static TypeInfo pbm_pci_host_info = {
+ .name = "pbm-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = pbm_pci_host_class_init,
};
-static SysBusDeviceInfo pbm_host_info = {
- .qdev.name = "pbm",
- .qdev.size = sizeof(APBState),
- .qdev.reset = pci_pbm_reset,
- .init = pci_pbm_init_device,
+static void pbm_host_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pci_pbm_init_device;
+ dc->reset = pci_pbm_reset;
+}
+
+static TypeInfo pbm_host_info = {
+ .name = "pbm",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(APBState),
+ .class_init = pbm_host_class_init,
};
-static PCIDeviceInfo pbm_pci_bridge_info = {
- .qdev.name = "pbm-bridge",
- .qdev.size = sizeof(PCIBridge),
- .qdev.vmsd = &vmstate_pci_device,
- .qdev.reset = pci_bridge_reset,
- .init = apb_pci_bridge_initfn,
- .exit = pci_bridge_exitfn,
- .vendor_id = PCI_VENDOR_ID_SUN,
- .device_id = PCI_DEVICE_ID_SUN_SIMBA,
- .revision = 0x11,
- .config_write = pci_bridge_write_config,
- .is_bridge = 1,
+static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = apb_pci_bridge_initfn;
+ k->exit = pci_bridge_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_SUN;
+ k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
+ k->revision = 0x11;
+ k->config_write = pci_bridge_write_config;
+ k->is_bridge = 1;
+ dc->reset = pci_bridge_reset;
+ dc->vmsd = &vmstate_pci_device;
+}
+
+static TypeInfo pbm_pci_bridge_info = {
+ .name = "pbm-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIBridge),
+ .class_init = pbm_pci_bridge_class_init,
};
static void pbm_register_devices(void)
{
- sysbus_register_withprop(&pbm_host_info);
- pci_qdev_register(&pbm_pci_host_info);
- pci_qdev_register(&pbm_pci_bridge_info);
+ type_register_static(&pbm_host_info);
+ type_register_static(&pbm_pci_host_info);
+ type_register_static(&pbm_pci_bridge_info);
}
device_init(pbm_register_devices)
diff --git a/hw/apic.c b/hw/apic.c
index 9d0f460b58..086c544bf3 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -16,53 +16,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
-#include "hw.h"
+#include "apic_internal.h"
#include "apic.h"
#include "ioapic.h"
-#include "qemu-timer.h"
#include "host-utils.h"
-#include "sysbus.h"
#include "trace.h"
#include "pc.h"
-/* APIC Local Vector Table */
-#define APIC_LVT_TIMER 0
-#define APIC_LVT_THERMAL 1
-#define APIC_LVT_PERFORM 2
-#define APIC_LVT_LINT0 3
-#define APIC_LVT_LINT1 4
-#define APIC_LVT_ERROR 5
-#define APIC_LVT_NB 6
-
-/* APIC delivery modes */
-#define APIC_DM_FIXED 0
-#define APIC_DM_LOWPRI 1
-#define APIC_DM_SMI 2
-#define APIC_DM_NMI 4
-#define APIC_DM_INIT 5
-#define APIC_DM_SIPI 6
-#define APIC_DM_EXTINT 7
-
-/* APIC destination mode */
-#define APIC_DESTMODE_FLAT 0xf
-#define APIC_DESTMODE_CLUSTER 1
-
-#define APIC_TRIGGER_EDGE 0
-#define APIC_TRIGGER_LEVEL 1
-
-#define APIC_LVT_TIMER_PERIODIC (1<<17)
-#define APIC_LVT_MASKED (1<<16)
-#define APIC_LVT_LEVEL_TRIGGER (1<<15)
-#define APIC_LVT_REMOTE_IRR (1<<14)
-#define APIC_INPUT_POLARITY (1<<13)
-#define APIC_SEND_PENDING (1<<12)
-
-#define ESR_ILLEGAL_ADDRESS (1 << 7)
-
-#define APIC_SV_DIRECTED_IO (1<<12)
-#define APIC_SV_ENABLE (1<<8)
-
-#define MAX_APICS 255
#define MAX_APIC_WORDS 8
/* Intel APIC constants: from include/asm/msidef.h */
@@ -75,43 +35,10 @@
#define MSI_ADDR_DEST_ID_SHIFT 12
#define MSI_ADDR_DEST_ID_MASK 0x00ffff0
-#define MSI_ADDR_SIZE 0x100000
-
-typedef struct APICState APICState;
-
-struct APICState {
- SysBusDevice busdev;
- MemoryRegion io_memory;
- void *cpu_env;
- uint32_t apicbase;
- uint8_t id;
- uint8_t arb_id;
- uint8_t tpr;
- uint32_t spurious_vec;
- uint8_t log_dest;
- uint8_t dest_mode;
- uint32_t isr[8]; /* in service register */
- uint32_t tmr[8]; /* trigger mode register */
- uint32_t irr[8]; /* interrupt request register */
- uint32_t lvt[APIC_LVT_NB];
- uint32_t esr; /* error register */
- uint32_t icr[2];
-
- uint32_t divide_conf;
- int count_shift;
- uint32_t initial_count;
- int64_t initial_count_load_time, next_time;
- uint32_t idx;
- QEMUTimer *timer;
- int sipi_vector;
- int wait_for_sipi;
-};
-
-static APICState *local_apics[MAX_APICS + 1];
-static int apic_irq_delivered;
+static APICCommonState *local_apics[MAX_APICS + 1];
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
-static void apic_update_irq(APICState *s);
+static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
+static void apic_update_irq(APICCommonState *s);
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
uint8_t dest, uint8_t dest_mode);
@@ -151,7 +78,7 @@ static inline int get_bit(uint32_t *tab, int index)
return !!(tab[i] & mask);
}
-static void apic_local_deliver(APICState *s, int vector)
+static void apic_local_deliver(APICCommonState *s, int vector)
{
uint32_t lvt = s->lvt[vector];
int trigger_mode;
@@ -185,7 +112,7 @@ static void apic_local_deliver(APICState *s, int vector)
void apic_deliver_pic_intr(DeviceState *d, int level)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
if (level) {
apic_local_deliver(s, APIC_LVT_LINT0);
@@ -205,6 +132,11 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
}
}
+static void apic_external_nmi(APICCommonState *s)
+{
+ apic_local_deliver(s, APIC_LVT_LINT1);
+}
+
#define foreach_apic(apic, deliver_bitmask, code) \
{\
int __i, __j, __mask;\
@@ -227,7 +159,7 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
uint8_t delivery_mode, uint8_t vector_num,
uint8_t trigger_mode)
{
- APICState *apic_iter;
+ APICCommonState *apic_iter;
switch (delivery_mode) {
case APIC_DM_LOWPRI:
@@ -293,14 +225,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
}
-void cpu_set_apic_base(DeviceState *d, uint64_t val)
+static void apic_set_base(APICCommonState *s, uint64_t val)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
-
- trace_cpu_set_apic_base(val);
-
- if (!s)
- return;
s->apicbase = (val & 0xfffff000) |
(s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
/* if disabled, cannot be enabled again */
@@ -311,32 +237,12 @@ void cpu_set_apic_base(DeviceState *d, uint64_t val)
}
}
-uint64_t cpu_get_apic_base(DeviceState *d)
-{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
-
- trace_cpu_get_apic_base(s ? (uint64_t)s->apicbase: 0);
-
- return s ? s->apicbase : 0;
-}
-
-void cpu_set_apic_tpr(DeviceState *d, uint8_t val)
+static void apic_set_tpr(APICCommonState *s, uint8_t val)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
-
- if (!s)
- return;
s->tpr = (val & 0x0f) << 4;
apic_update_irq(s);
}
-uint8_t cpu_get_apic_tpr(DeviceState *d)
-{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
-
- return s ? s->tpr >> 4 : 0;
-}
-
/* return -1 if no bit is set */
static int get_highest_priority_int(uint32_t *tab)
{
@@ -349,7 +255,7 @@ static int get_highest_priority_int(uint32_t *tab)
return -1;
}
-static int apic_get_ppr(APICState *s)
+static int apic_get_ppr(APICCommonState *s)
{
int tpr, isrv, ppr;
@@ -365,7 +271,7 @@ static int apic_get_ppr(APICState *s)
return ppr;
}
-static int apic_get_arb_pri(APICState *s)
+static int apic_get_arb_pri(APICCommonState *s)
{
/* XXX: arbitration */
return 0;
@@ -377,7 +283,7 @@ static int apic_get_arb_pri(APICState *s)
* 0 - no interrupt,
* >0 - interrupt number
*/
-static int apic_irq_pending(APICState *s)
+static int apic_irq_pending(APICCommonState *s)
{
int irrv, ppr;
irrv = get_highest_priority_int(s->irr);
@@ -393,7 +299,7 @@ static int apic_irq_pending(APICState *s)
}
/* signal the CPU if an irq is pending */
-static void apic_update_irq(APICState *s)
+static void apic_update_irq(APICCommonState *s)
{
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
@@ -406,25 +312,9 @@ static void apic_update_irq(APICState *s)
}
}
-void apic_reset_irq_delivered(void)
+static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode)
{
- trace_apic_reset_irq_delivered(apic_irq_delivered);
-
- apic_irq_delivered = 0;
-}
-
-int apic_get_irq_delivered(void)
-{
- trace_apic_get_irq_delivered(apic_irq_delivered);
-
- return apic_irq_delivered;
-}
-
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
-{
- apic_irq_delivered += !get_bit(s->irr, vector_num);
-
- trace_apic_set_irq(apic_irq_delivered);
+ apic_report_irq_delivered(!get_bit(s->irr, vector_num));
set_bit(s->irr, vector_num);
if (trigger_mode)
@@ -434,7 +324,7 @@ static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
apic_update_irq(s);
}
-static void apic_eoi(APICState *s)
+static void apic_eoi(APICCommonState *s)
{
int isrv;
isrv = get_highest_priority_int(s->isr);
@@ -449,7 +339,7 @@ static void apic_eoi(APICState *s)
static int apic_find_dest(uint8_t dest)
{
- APICState *apic = local_apics[dest];
+ APICCommonState *apic = local_apics[dest];
int i;
if (apic && apic->id == dest)
@@ -469,7 +359,7 @@ static int apic_find_dest(uint8_t dest)
static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
uint8_t dest, uint8_t dest_mode)
{
- APICState *apic_iter;
+ APICCommonState *apic_iter;
int i;
if (dest_mode == 0) {
@@ -503,34 +393,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
}
}
-void apic_init_reset(DeviceState *d)
-{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
- int i;
-
- if (!s)
- return;
-
- s->tpr = 0;
- s->spurious_vec = 0xff;
- s->log_dest = 0;
- s->dest_mode = 0xf;
- memset(s->isr, 0, sizeof(s->isr));
- memset(s->tmr, 0, sizeof(s->tmr));
- memset(s->irr, 0, sizeof(s->irr));
- for(i = 0; i < APIC_LVT_NB; i++)
- s->lvt[i] = 1 << 16; /* mask LVT */
- s->esr = 0;
- memset(s->icr, 0, sizeof(s->icr));
- s->divide_conf = 0;
- s->count_shift = 0;
- s->initial_count = 0;
- s->initial_count_load_time = 0;
- s->next_time = 0;
- s->wait_for_sipi = 1;
-}
-
-static void apic_startup(APICState *s, int vector_num)
+static void apic_startup(APICCommonState *s, int vector_num)
{
s->sipi_vector = vector_num;
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
@@ -538,7 +401,7 @@ static void apic_startup(APICState *s, int vector_num)
void apic_sipi(DeviceState *d)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
@@ -552,10 +415,10 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
uint8_t delivery_mode, uint8_t vector_num,
uint8_t trigger_mode)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
uint32_t deliver_bitmask[MAX_APIC_WORDS];
int dest_shorthand = (s->icr[0] >> 18) & 3;
- APICState *apic_iter;
+ APICCommonState *apic_iter;
switch (dest_shorthand) {
case 0:
@@ -598,7 +461,7 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
int apic_get_interrupt(DeviceState *d)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
int intno;
/* if the APIC is installed or enabled, we let the 8259 handle the
@@ -623,7 +486,7 @@ int apic_get_interrupt(DeviceState *d)
int apic_accept_pic_intr(DeviceState *d)
{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
uint32_t lvt0;
if (!s)
@@ -638,7 +501,7 @@ int apic_accept_pic_intr(DeviceState *d)
return 0;
}
-static uint32_t apic_get_current_count(APICState *s)
+static uint32_t apic_get_current_count(APICCommonState *s)
{
int64_t d;
uint32_t val;
@@ -656,34 +519,18 @@ static uint32_t apic_get_current_count(APICState *s)
return val;
}
-static void apic_timer_update(APICState *s, int64_t current_time)
+static void apic_timer_update(APICCommonState *s, int64_t current_time)
{
- int64_t next_time, d;
-
- if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
- d = (current_time - s->initial_count_load_time) >>
- s->count_shift;
- if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
- if (!s->initial_count)
- goto no_timer;
- d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
- } else {
- if (d >= s->initial_count)
- goto no_timer;
- d = (uint64_t)s->initial_count + 1;
- }
- next_time = s->initial_count_load_time + (d << s->count_shift);
- qemu_mod_timer(s->timer, next_time);
- s->next_time = next_time;
+ if (apic_next_timer(s, current_time)) {
+ qemu_mod_timer(s->timer, s->next_time);
} else {
- no_timer:
qemu_del_timer(s->timer);
}
}
static void apic_timer(void *opaque)
{
- APICState *s = opaque;
+ APICCommonState *s = opaque;
apic_local_deliver(s, APIC_LVT_TIMER);
apic_timer_update(s, s->next_time);
@@ -710,7 +557,7 @@ static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
{
DeviceState *d;
- APICState *s;
+ APICCommonState *s;
uint32_t val;
int index;
@@ -718,7 +565,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
if (!d) {
return 0;
}
- s = DO_UPCAST(APICState, busdev.qdev, d);
+ s = DO_UPCAST(APICCommonState, busdev.qdev, d);
index = (addr >> 4) & 0xff;
switch(index) {
@@ -801,7 +648,7 @@ static void apic_send_msi(target_phys_addr_t addr, uint32_t data)
static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
DeviceState *d;
- APICState *s;
+ APICCommonState *s;
int index = (addr >> 4) & 0xff;
if (addr > 0xfff || !index) {
/* MSI and MMIO APIC are at the same memory location,
@@ -817,7 +664,7 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
if (!d) {
return;
}
- s = DO_UPCAST(APICState, busdev.qdev, d);
+ s = DO_UPCAST(APICCommonState, busdev.qdev, d);
trace_apic_mem_writel(addr, val);
@@ -890,93 +737,12 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
}
}
-/* This function is only used for old state version 1 and 2 */
-static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
+static void apic_post_load(APICCommonState *s)
{
- APICState *s = opaque;
- int i;
-
- if (version_id > 2)
- return -EINVAL;
-
- /* XXX: what if the base changes? (registered memory regions) */
- qemu_get_be32s(f, &s->apicbase);
- qemu_get_8s(f, &s->id);
- qemu_get_8s(f, &s->arb_id);
- qemu_get_8s(f, &s->tpr);
- qemu_get_be32s(f, &s->spurious_vec);
- qemu_get_8s(f, &s->log_dest);
- qemu_get_8s(f, &s->dest_mode);
- for (i = 0; i < 8; i++) {
- qemu_get_be32s(f, &s->isr[i]);
- qemu_get_be32s(f, &s->tmr[i]);
- qemu_get_be32s(f, &s->irr[i]);
- }
- for (i = 0; i < APIC_LVT_NB; i++) {
- qemu_get_be32s(f, &s->lvt[i]);
- }
- qemu_get_be32s(f, &s->esr);
- qemu_get_be32s(f, &s->icr[0]);
- qemu_get_be32s(f, &s->icr[1]);
- qemu_get_be32s(f, &s->divide_conf);
- s->count_shift=qemu_get_be32(f);
- qemu_get_be32s(f, &s->initial_count);
- s->initial_count_load_time=qemu_get_be64(f);
- s->next_time=qemu_get_be64(f);
-
- if (version_id >= 2)
- qemu_get_timer(f, s->timer);
- return 0;
-}
-
-static const VMStateDescription vmstate_apic = {
- .name = "apic",
- .version_id = 3,
- .minimum_version_id = 3,
- .minimum_version_id_old = 1,
- .load_state_old = apic_load_old,
- .fields = (VMStateField []) {
- VMSTATE_UINT32(apicbase, APICState),
- VMSTATE_UINT8(id, APICState),
- VMSTATE_UINT8(arb_id, APICState),
- VMSTATE_UINT8(tpr, APICState),
- VMSTATE_UINT32(spurious_vec, APICState),
- VMSTATE_UINT8(log_dest, APICState),
- VMSTATE_UINT8(dest_mode, APICState),
- VMSTATE_UINT32_ARRAY(isr, APICState, 8),
- VMSTATE_UINT32_ARRAY(tmr, APICState, 8),
- VMSTATE_UINT32_ARRAY(irr, APICState, 8),
- VMSTATE_UINT32_ARRAY(lvt, APICState, APIC_LVT_NB),
- VMSTATE_UINT32(esr, APICState),
- VMSTATE_UINT32_ARRAY(icr, APICState, 2),
- VMSTATE_UINT32(divide_conf, APICState),
- VMSTATE_INT32(count_shift, APICState),
- VMSTATE_UINT32(initial_count, APICState),
- VMSTATE_INT64(initial_count_load_time, APICState),
- VMSTATE_INT64(next_time, APICState),
- VMSTATE_TIMER(timer, APICState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void apic_reset(DeviceState *d)
-{
- APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
- int bsp;
-
- bsp = cpu_is_bsp(s->cpu_env);
- s->apicbase = 0xfee00000 |
- (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
-
- apic_init_reset(d);
-
- if (bsp) {
- /*
- * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
- * time typically by BIOS, so PIC interrupt can be delivered to the
- * processor when local APIC is enabled.
- */
- s->lvt[APIC_LVT_LINT0] = 0x700;
+ if (s->timer_expiry != -1) {
+ qemu_mod_timer(s->timer, s->timer_expiry);
+ } else {
+ qemu_del_timer(s->timer);
}
}
@@ -988,41 +754,36 @@ static const MemoryRegionOps apic_io_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int apic_init1(SysBusDevice *dev)
+static void apic_init(APICCommonState *s)
{
- APICState *s = FROM_SYSBUS(APICState, dev);
- static int last_apic_idx;
-
- if (last_apic_idx >= MAX_APICS) {
- return -1;
- }
- memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic",
- MSI_ADDR_SIZE);
- sysbus_init_mmio(dev, &s->io_memory);
+ memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi",
+ MSI_SPACE_SIZE);
s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
- s->idx = last_apic_idx++;
local_apics[s->idx] = s;
- return 0;
}
-static SysBusDeviceInfo apic_info = {
- .init = apic_init1,
- .qdev.name = "apic",
- .qdev.size = sizeof(APICState),
- .qdev.vmsd = &vmstate_apic,
- .qdev.reset = apic_reset,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("id", APICState, id, -1),
- DEFINE_PROP_PTR("cpu_env", APICState, cpu_env),
- DEFINE_PROP_END_OF_LIST(),
- }
+static void apic_class_init(ObjectClass *klass, void *data)
+{
+ APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+ k->init = apic_init;
+ k->set_base = apic_set_base;
+ k->set_tpr = apic_set_tpr;
+ k->external_nmi = apic_external_nmi;
+ k->post_load = apic_post_load;
+}
+
+static TypeInfo apic_info = {
+ .name = "apic",
+ .instance_size = sizeof(APICCommonState),
+ .parent = TYPE_APIC_COMMON,
+ .class_init = apic_class_init,
};
static void apic_register_devices(void)
{
- sysbus_register_withprop(&apic_info);
+ type_register_static(&apic_info);
}
device_init(apic_register_devices)
diff --git a/hw/apic.h b/hw/apic.h
index a5c910fe0a..a62d83ba9f 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -8,6 +8,7 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
uint8_t vector_num, uint8_t trigger_mode);
int apic_accept_pic_intr(DeviceState *s);
void apic_deliver_pic_intr(DeviceState *s, int level);
+void apic_deliver_nmi(DeviceState *d);
int apic_get_interrupt(DeviceState *s);
void apic_reset_irq_delivered(void);
int apic_get_irq_delivered(void);
diff --git a/hw/apic_common.c b/hw/apic_common.c
new file mode 100644
index 0000000000..26991b4516
--- /dev/null
+++ b/hw/apic_common.c
@@ -0,0 +1,321 @@
+/*
+ * APIC support - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+#include "apic.h"
+#include "apic_internal.h"
+#include "trace.h"
+
+static int apic_irq_delivered;
+
+void cpu_set_apic_base(DeviceState *d, uint64_t val)
+{
+ trace_cpu_set_apic_base(val);
+
+ if (d) {
+ APICCommonState *s = APIC_COMMON(d);
+ APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+ info->set_base(s, val);
+ }
+}
+
+uint64_t cpu_get_apic_base(DeviceState *d)
+{
+ if (d) {
+ APICCommonState *s = APIC_COMMON(d);
+ trace_cpu_get_apic_base((uint64_t)s->apicbase);
+ return s->apicbase;
+ } else {
+ trace_cpu_get_apic_base(0);
+ return 0;
+ }
+}
+
+void cpu_set_apic_tpr(DeviceState *d, uint8_t val)
+{
+ APICCommonState *s;
+ APICCommonClass *info;
+
+ if (!d) {
+ return;
+ }
+
+ s = APIC_COMMON(d);
+ info = APIC_COMMON_GET_CLASS(s);
+
+ info->set_tpr(s, val);
+}
+
+uint8_t cpu_get_apic_tpr(DeviceState *d)
+{
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+
+ return s ? s->tpr >> 4 : 0;
+}
+
+void apic_report_irq_delivered(int delivered)
+{
+ apic_irq_delivered += delivered;
+
+ trace_apic_report_irq_delivered(apic_irq_delivered);
+}
+
+void apic_reset_irq_delivered(void)
+{
+ trace_apic_reset_irq_delivered(apic_irq_delivered);
+
+ apic_irq_delivered = 0;
+}
+
+int apic_get_irq_delivered(void)
+{
+ trace_apic_get_irq_delivered(apic_irq_delivered);
+
+ return apic_irq_delivered;
+}
+
+void apic_deliver_nmi(DeviceState *d)
+{
+ APICCommonState *s = APIC_COMMON(d);
+ APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+
+ info->external_nmi(s);
+}
+
+bool apic_next_timer(APICCommonState *s, int64_t current_time)
+{
+ int64_t d;
+
+ /* We need to store the timer state separately to support APIC
+ * implementations that maintain a non-QEMU timer, e.g. inside the
+ * host kernel. This open-coded state allows us to migrate between
+ * both models. */
+ s->timer_expiry = -1;
+
+ if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED) {
+ return false;
+ }
+
+ d = (current_time - s->initial_count_load_time) >> s->count_shift;
+
+ if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
+ if (!s->initial_count) {
+ return false;
+ }
+ d = ((d / ((uint64_t)s->initial_count + 1)) + 1) *
+ ((uint64_t)s->initial_count + 1);
+ } else {
+ if (d >= s->initial_count) {
+ return false;
+ }
+ d = (uint64_t)s->initial_count + 1;
+ }
+ s->next_time = s->initial_count_load_time + (d << s->count_shift);
+ s->timer_expiry = s->next_time;
+ return true;
+}
+
+void apic_init_reset(DeviceState *d)
+{
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ int i;
+
+ if (!s) {
+ return;
+ }
+ s->tpr = 0;
+ s->spurious_vec = 0xff;
+ s->log_dest = 0;
+ s->dest_mode = 0xf;
+ memset(s->isr, 0, sizeof(s->isr));
+ memset(s->tmr, 0, sizeof(s->tmr));
+ memset(s->irr, 0, sizeof(s->irr));
+ for (i = 0; i < APIC_LVT_NB; i++) {
+ s->lvt[i] = APIC_LVT_MASKED;
+ }
+ s->esr = 0;
+ memset(s->icr, 0, sizeof(s->icr));
+ s->divide_conf = 0;
+ s->count_shift = 0;
+ s->initial_count = 0;
+ s->initial_count_load_time = 0;
+ s->next_time = 0;
+ s->wait_for_sipi = 1;
+
+ if (s->timer) {
+ qemu_del_timer(s->timer);
+ }
+ s->timer_expiry = -1;
+}
+
+static void apic_reset_common(DeviceState *d)
+{
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ bool bsp;
+
+ bsp = cpu_is_bsp(s->cpu_env);
+ s->apicbase = 0xfee00000 |
+ (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
+
+ apic_init_reset(d);
+
+ if (bsp) {
+ /*
+ * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
+ * time typically by BIOS, so PIC interrupt can be delivered to the
+ * processor when local APIC is enabled.
+ */
+ s->lvt[APIC_LVT_LINT0] = 0x700;
+ }
+}
+
+/* This function is only used for old state version 1 and 2 */
+static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
+{
+ APICCommonState *s = opaque;
+ int i;
+
+ if (version_id > 2) {
+ return -EINVAL;
+ }
+
+ /* XXX: what if the base changes? (registered memory regions) */
+ qemu_get_be32s(f, &s->apicbase);
+ qemu_get_8s(f, &s->id);
+ qemu_get_8s(f, &s->arb_id);
+ qemu_get_8s(f, &s->tpr);
+ qemu_get_be32s(f, &s->spurious_vec);
+ qemu_get_8s(f, &s->log_dest);
+ qemu_get_8s(f, &s->dest_mode);
+ for (i = 0; i < 8; i++) {
+ qemu_get_be32s(f, &s->isr[i]);
+ qemu_get_be32s(f, &s->tmr[i]);
+ qemu_get_be32s(f, &s->irr[i]);
+ }
+ for (i = 0; i < APIC_LVT_NB; i++) {
+ qemu_get_be32s(f, &s->lvt[i]);
+ }
+ qemu_get_be32s(f, &s->esr);
+ qemu_get_be32s(f, &s->icr[0]);
+ qemu_get_be32s(f, &s->icr[1]);
+ qemu_get_be32s(f, &s->divide_conf);
+ s->count_shift = qemu_get_be32(f);
+ qemu_get_be32s(f, &s->initial_count);
+ s->initial_count_load_time = qemu_get_be64(f);
+ s->next_time = qemu_get_be64(f);
+
+ if (version_id >= 2) {
+ qemu_get_timer(f, s->timer);
+ }
+ return 0;
+}
+
+static int apic_init_common(SysBusDevice *dev)
+{
+ APICCommonState *s = APIC_COMMON(dev);
+ APICCommonClass *info;
+ static int apic_no;
+
+ if (apic_no >= MAX_APICS) {
+ return -1;
+ }
+ s->idx = apic_no++;
+
+ info = APIC_COMMON_GET_CLASS(s);
+ info->init(s);
+
+ sysbus_init_mmio(&s->busdev, &s->io_memory);
+ return 0;
+}
+
+static int apic_dispatch_post_load(void *opaque, int version_id)
+{
+ APICCommonState *s = APIC_COMMON(opaque);
+ APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
+
+ if (info->post_load) {
+ info->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_apic_common = {
+ .name = "apic",
+ .version_id = 3,
+ .minimum_version_id = 3,
+ .minimum_version_id_old = 1,
+ .load_state_old = apic_load_old,
+ .post_load = apic_dispatch_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(apicbase, APICCommonState),
+ VMSTATE_UINT8(id, APICCommonState),
+ VMSTATE_UINT8(arb_id, APICCommonState),
+ VMSTATE_UINT8(tpr, APICCommonState),
+ VMSTATE_UINT32(spurious_vec, APICCommonState),
+ VMSTATE_UINT8(log_dest, APICCommonState),
+ VMSTATE_UINT8(dest_mode, APICCommonState),
+ VMSTATE_UINT32_ARRAY(isr, APICCommonState, 8),
+ VMSTATE_UINT32_ARRAY(tmr, APICCommonState, 8),
+ VMSTATE_UINT32_ARRAY(irr, APICCommonState, 8),
+ VMSTATE_UINT32_ARRAY(lvt, APICCommonState, APIC_LVT_NB),
+ VMSTATE_UINT32(esr, APICCommonState),
+ VMSTATE_UINT32_ARRAY(icr, APICCommonState, 2),
+ VMSTATE_UINT32(divide_conf, APICCommonState),
+ VMSTATE_INT32(count_shift, APICCommonState),
+ VMSTATE_UINT32(initial_count, APICCommonState),
+ VMSTATE_INT64(initial_count_load_time, APICCommonState),
+ VMSTATE_INT64(next_time, APICCommonState),
+ VMSTATE_INT64(timer_expiry,
+ APICCommonState), /* open-coded timer state */
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property apic_properties_common[] = {
+ DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
+ DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void apic_common_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_apic_common;
+ dc->reset = apic_reset_common;
+ dc->no_user = 1;
+ dc->props = apic_properties_common;
+ sc->init = apic_init_common;
+}
+
+static TypeInfo apic_common_type = {
+ .name = TYPE_APIC_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(APICCommonState),
+ .class_size = sizeof(APICCommonClass),
+ .class_init = apic_common_class_init,
+ .abstract = true,
+};
+
+static void register_devices(void)
+{
+ type_register_static(&apic_common_type);
+}
+
+device_init(register_devices);
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
new file mode 100644
index 0000000000..0cab010717
--- /dev/null
+++ b/hw/apic_internal.h
@@ -0,0 +1,122 @@
+/*
+ * APIC support - internal interfaces
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+#ifndef QEMU_APIC_INTERNAL_H
+#define QEMU_APIC_INTERNAL_H
+
+#include "memory.h"
+#include "sysbus.h"
+#include "qemu-timer.h"
+
+/* APIC Local Vector Table */
+#define APIC_LVT_TIMER 0
+#define APIC_LVT_THERMAL 1
+#define APIC_LVT_PERFORM 2
+#define APIC_LVT_LINT0 3
+#define APIC_LVT_LINT1 4
+#define APIC_LVT_ERROR 5
+#define APIC_LVT_NB 6
+
+/* APIC delivery modes */
+#define APIC_DM_FIXED 0
+#define APIC_DM_LOWPRI 1
+#define APIC_DM_SMI 2
+#define APIC_DM_NMI 4
+#define APIC_DM_INIT 5
+#define APIC_DM_SIPI 6
+#define APIC_DM_EXTINT 7
+
+/* APIC destination mode */
+#define APIC_DESTMODE_FLAT 0xf
+#define APIC_DESTMODE_CLUSTER 1
+
+#define APIC_TRIGGER_EDGE 0
+#define APIC_TRIGGER_LEVEL 1
+
+#define APIC_LVT_TIMER_PERIODIC (1<<17)
+#define APIC_LVT_MASKED (1<<16)
+#define APIC_LVT_LEVEL_TRIGGER (1<<15)
+#define APIC_LVT_REMOTE_IRR (1<<14)
+#define APIC_INPUT_POLARITY (1<<13)
+#define APIC_SEND_PENDING (1<<12)
+
+#define ESR_ILLEGAL_ADDRESS (1 << 7)
+
+#define APIC_SV_DIRECTED_IO (1<<12)
+#define APIC_SV_ENABLE (1<<8)
+
+#define MAX_APICS 255
+
+#define MSI_SPACE_SIZE 0x100000
+
+typedef struct APICCommonState APICCommonState;
+
+#define TYPE_APIC_COMMON "apic-common"
+#define APIC_COMMON(obj) \
+ OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC_COMMON)
+#define APIC_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(APICCommonClass, (klass), TYPE_APIC_COMMON)
+#define APIC_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(APICCommonClass, (obj), TYPE_APIC_COMMON)
+
+typedef struct APICCommonClass
+{
+ SysBusDeviceClass parent_class;
+
+ void (*init)(APICCommonState *s);
+ void (*set_base)(APICCommonState *s, uint64_t val);
+ void (*set_tpr)(APICCommonState *s, uint8_t val);
+ void (*external_nmi)(APICCommonState *s);
+ void (*post_load)(APICCommonState *s);
+} APICCommonClass;
+
+struct APICCommonState {
+ SysBusDevice busdev;
+ MemoryRegion io_memory;
+ void *cpu_env;
+ uint32_t apicbase;
+ uint8_t id;
+ uint8_t arb_id;
+ uint8_t tpr;
+ uint32_t spurious_vec;
+ uint8_t log_dest;
+ uint8_t dest_mode;
+ uint32_t isr[8]; /* in service register */
+ uint32_t tmr[8]; /* trigger mode register */
+ uint32_t irr[8]; /* interrupt request register */
+ uint32_t lvt[APIC_LVT_NB];
+ uint32_t esr; /* error register */
+ uint32_t icr[2];
+
+ uint32_t divide_conf;
+ int count_shift;
+ uint32_t initial_count;
+ int64_t initial_count_load_time;
+ int64_t next_time;
+ int idx;
+ QEMUTimer *timer;
+ int64_t timer_expiry;
+ int sipi_vector;
+ int wait_for_sipi;
+};
+
+void apic_report_irq_delivered(int delivered);
+bool apic_next_timer(APICCommonState *s, int64_t current_time);
+
+#endif /* !QEMU_APIC_INTERNAL_H */
diff --git a/hw/applesmc.c b/hw/applesmc.c
index c47b592747..b06487f70d 100644
--- a/hw/applesmc.c
+++ b/hw/applesmc.c
@@ -220,22 +220,32 @@ static int applesmc_isa_init(ISADevice *dev)
return 0;
}
-static ISADeviceInfo applesmc_isa_info = {
- .qdev.name = "isa-applesmc",
- .qdev.size = sizeof(struct AppleSMCStatus),
- .qdev.reset = qdev_applesmc_isa_reset,
- .init = applesmc_isa_init,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", struct AppleSMCStatus, iobase,
- APPLESMC_DEFAULT_IOBASE),
- DEFINE_PROP_STRING("osk", struct AppleSMCStatus, osk),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property applesmc_isa_properties[] = {
+ DEFINE_PROP_HEX32("iobase", struct AppleSMCStatus, iobase,
+ APPLESMC_DEFAULT_IOBASE),
+ DEFINE_PROP_STRING("osk", struct AppleSMCStatus, osk),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = applesmc_isa_init;
+ dc->reset = qdev_applesmc_isa_reset;
+ dc->props = applesmc_isa_properties;
+}
+
+static TypeInfo applesmc_isa_info = {
+ .name = "isa-applesmc",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(struct AppleSMCStatus),
+ .class_init = qdev_applesmc_class_init,
};
static void applesmc_register_devices(void)
{
- isa_qdev_register(&applesmc_isa_info);
+ type_register_static(&applesmc_isa_info);
}
device_init(applesmc_register_devices)
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b02e..5e5204bbf5 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -30,12 +30,29 @@ struct arm_boot_info {
const char *kernel_cmdline;
const char *initrd_filename;
target_phys_addr_t loader_start;
+ /* multicore boards that use the default secondary core boot functions
+ * need to put the address of the secondary boot code, the boot reg,
+ * and the GIC address in the next 3 values, respectively. boards that
+ * have their own boot functions can use these values as they want.
+ */
target_phys_addr_t smp_loader_start;
target_phys_addr_t smp_bootreg_addr;
target_phys_addr_t smp_priv_base;
int nb_cpus;
int board_id;
int (*atag_board)(const struct arm_boot_info *info, void *p);
+ /* multicore boards that use the default secondary core boot functions
+ * can ignore these two function calls. If the default functions won't
+ * work, then write_secondary_boot() should write a suitable blob of
+ * code mimicing the secondary CPU startup process used by the board's
+ * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
+ * perform any necessary CPU reset handling and set the PC for thei
+ * secondary CPUs to point at this boot blob.
+ */
+ void (*write_secondary_boot)(CPUState *env,
+ const struct arm_boot_info *info);
+ void (*secondary_cpu_reset_hook)(CPUState *env,
+ const struct arm_boot_info *info);
/* Used internally by arm_boot.c */
int is_linux;
target_phys_addr_t initrd_size;
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e58b..3c0839c4b4 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
#include "sysbus.h"
#include "qemu-timer.h"
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
- (+ 32 internal). However my test chip only exposes/reports 32.
- More importantly Linux falls over if more than 32 are present! */
-#define GIC_NIRQ 64
-
#define NCPU 4
static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
MemoryRegion iomem;
MemoryRegion container;
DeviceState *mptimer;
+ uint32_t num_irq;
} mpcore_priv_state;
/* Per-CPU private memory mapped IO. */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
{
mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
- gic_init(&s->gic, s->num_cpu);
+ gic_init(&s->gic, s->num_cpu, s->num_irq);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
qdev_init_nofail(s->mptimer);
@@ -205,30 +201,61 @@ static int realview_mpcore_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo mpcore_rirq_info = {
- .init = realview_mpcore_init,
- .qdev.name = "realview_mpcore",
- .qdev.size = sizeof(mpcore_rirq_state),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property mpcore_rirq_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+ /* The ARM11 MPCORE TRM says the on-chip controller may have
+ * anything from 0 to 224 external interrupt IRQ lines (with another
+ * 32 internal). We default to 32+32, which is the number provided by
+ * the ARM11 MPCore test chip in the Realview Versatile Express
+ * coretile. Other boards may differ and should set this property
+ * appropriately. Some Linux kernels may not boot if the hardware
+ * has more IRQ lines than the kernel expects.
+ */
+ DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo mpcore_priv_info = {
- .init = mpcore_priv_init,
- .qdev.name = "arm11mpcore_priv",
- .qdev.size = sizeof(mpcore_priv_state),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = realview_mpcore_init;
+ dc->props = mpcore_rirq_properties;
+}
+
+static TypeInfo mpcore_rirq_info = {
+ .name = "realview_mpcore",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mpcore_rirq_state),
+ .class_init = mpcore_rirq_class_init,
+};
+
+static Property mpcore_priv_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mpcore_priv_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mpcore_priv_init;
+ dc->props = mpcore_priv_properties;
+}
+
+static TypeInfo mpcore_priv_info = {
+ .name = "arm11mpcore_priv",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mpcore_priv_state),
+ .class_init = mpcore_priv_class_init,
};
static void arm11mpcore_register_devices(void)
{
- sysbus_register_withprop(&mpcore_rirq_info);
- sysbus_register_withprop(&mpcore_priv_info);
+ type_register_static(&mpcore_rirq_info);
+ type_register_static(&mpcore_priv_info);
}
device_init(arm11mpcore_register_devices)
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8eb9..5f163fda02 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -20,16 +20,28 @@
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static uint32_t bootloader[] = {
0xe3a00000, /* mov r0, #0 */
- 0xe3a01000, /* mov r1, #0x?? */
- 0xe3811c00, /* orr r1, r1, #0x??00 */
- 0xe59f2000, /* ldr r2, [pc, #0] */
- 0xe59ff000, /* ldr pc, [pc, #0] */
+ 0xe59f1004, /* ldr r1, [pc, #4] */
+ 0xe59f2004, /* ldr r2, [pc, #4] */
+ 0xe59ff004, /* ldr pc, [pc, #4] */
+ 0, /* Board ID */
0, /* Address of kernel args. Set by integratorcp_init. */
0 /* Kernel entry point. Set by integratorcp_init. */
};
-/* Entry point for secondary CPUs. Enable interrupt controller and
- Issue WFI until start address is written to system controller. */
+/* Handling for secondary CPU boot in a multicore system.
+ * Unlike the uniprocessor/primary CPU boot, this is platform
+ * dependent. The default code here is based on the secondary
+ * CPU boot protocol used on realview/vexpress boards, with
+ * some parameterisation to increase its flexibility.
+ * QEMU platform models for which this code is not appropriate
+ * should override write_secondary_boot and secondary_cpu_reset_hook
+ * instead.
+ *
+ * This code enables the interrupt controllers for the secondary
+ * CPUs and then puts all the secondary CPUs into a loop waiting
+ * for an interprocessor interrupt and polling a configurable
+ * location for the kernel secondary CPU entry point.
+ */
static uint32_t smpboot[] = {
0xe59f201c, /* ldr r2, privbase */
0xe59f001c, /* ldr r0, startaddr */
@@ -44,6 +56,26 @@ static uint32_t smpboot[] = {
0 /* bootreg: Boot register address is held here */
};
+static void default_write_secondary(CPUState *env,
+ const struct arm_boot_info *info)
+{
+ int n;
+ smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+ smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
+ for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+ smpboot[n] = tswap32(smpboot[n]);
+ }
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+ info->smp_loader_start);
+}
+
+static void default_reset_secondary(CPUState *env,
+ const struct arm_boot_info *info)
+{
+ stl_phys_notdirty(info->smp_bootreg_addr, 0);
+ env->regs[15] = info->smp_loader_start;
+}
+
#define WRITE_WORD(p, value) do { \
stl_phys_notdirty(p, value); \
p += 4; \
@@ -197,8 +229,7 @@ static void do_cpu_reset(void *opaque)
info->loader_start);
}
} else {
- stl_phys_notdirty(info->smp_bootreg_addr, 0);
- env->regs[15] = info->smp_loader_start;
+ info->secondary_cpu_reset_hook(env, info);
}
}
}
@@ -220,6 +251,13 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
exit(1);
}
+ if (!info->secondary_cpu_reset_hook) {
+ info->secondary_cpu_reset_hook = default_reset_secondary;
+ }
+ if (!info->write_secondary_boot) {
+ info->write_secondary_boot = default_write_secondary;
+ }
+
if (info->nb_cpus == 0)
info->nb_cpus = 1;
@@ -263,8 +301,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
} else {
initrd_size = 0;
}
- bootloader[1] |= info->board_id & 0xff;
- bootloader[2] |= (info->board_id >> 8) & 0xff;
+ bootloader[4] = info->board_id;
bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
bootloader[6] = entry;
for (n = 0; n < sizeof(bootloader) / 4; n++) {
@@ -273,13 +310,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
info->loader_start);
if (info->nb_cpus > 1) {
- smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
- smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
- for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
- smpboot[n] = tswap32(smpboot[n]);
- }
- rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
- info->smp_loader_start);
+ info->write_secondary_boot(env, info);
}
info->initrd_size = initrd_size;
}
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf59fb..cf582a5a14 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
controller, MPCore distributed interrupt controller and ARMv7-M
Nested Vectored Interrupt Controller. */
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
//#define DEBUG_GIC
#ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
int enabled;
int cpu_enabled[NCPU];
- gic_irq_state irq_state[GIC_NIRQ];
+ gic_irq_state irq_state[GIC_MAXIRQ];
#ifndef NVIC
- int irq_target[GIC_NIRQ];
+ int irq_target[GIC_MAXIRQ];
#endif
int priority1[32][NCPU];
- int priority2[GIC_NIRQ - 32];
- int last_active[GIC_NIRQ][NCPU];
+ int priority2[GIC_MAXIRQ - 32];
+ int last_active[GIC_MAXIRQ][NCPU];
int priority_mask[NCPU];
int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
struct gic_state *backref[NCPU];
MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
#endif
+ uint32_t num_irq;
} gic_state;
/* TODO: Many places that call this routine could be optimized. */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
}
best_prio = 0x100;
best_irq = 1023;
- for (irq = 0; irq < GIC_NIRQ; irq++) {
+ for (irq = 0; irq < s->num_irq; irq++) {
if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
int update = 0;
int cm = 1 << cpu;
DPRINTF("EOI %d\n", irq);
- if (irq >= GIC_NIRQ) {
+ if (irq >= s->num_irq) {
/* This handles two cases:
* 1. If software writes the ID of a spurious interrupt [ie 1023]
* to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
if (offset == 0)
return s->enabled;
if (offset == 4)
- return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+ return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
if (offset < 0x08)
return 0;
if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
else
irq = (offset - 0x180) * 8;
irq += GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
res = 0;
for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
else
irq = (offset - 0x280) * 8;
irq += GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
res = 0;
mask = (irq < 32) ? cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
} else if (offset < 0x400) {
/* Interrupt Active. */
irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
res = 0;
mask = (irq < 32) ? cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
} else if (offset < 0x800) {
/* Interrupt Priority. */
irq = (offset - 0x400) + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
res = GIC_GET_PRIORITY(irq, cpu);
#ifndef NVIC
} else if (offset < 0xc00) {
/* Interrupt CPU Target. */
irq = (offset - 0x800) + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq >= 29 && irq <= 31) {
res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
res = 0;
for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0x180) {
/* Interrupt Set Enable. */
irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0x200) {
/* Interrupt Clear Enable. */
irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0x280) {
/* Interrupt Set Pending. */
irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0x300) {
/* Interrupt Clear Pending. */
irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
for (i = 0; i < 8; i++) {
/* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0x800) {
/* Interrupt Priority. */
irq = (offset - 0x400) + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 32) {
s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0xc00) {
/* Interrupt CPU Target. */
irq = (offset - 0x800) + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 29)
value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
} else if (offset < 0xf00) {
/* Interrupt Configuration. */
irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
- if (irq >= GIC_NIRQ)
+ if (irq >= s->num_irq)
goto bad_reg;
if (irq < 32)
value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
static void gic_reset(gic_state *s)
{
int i;
- memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+ memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < NUM_CPU(s); i++) {
s->priority_mask[i] = 0xf0;
s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->cpu_enabled[i]);
for (j = 0; j < 32; j++)
qemu_put_be32(f, s->priority1[j][i]);
- for (j = 0; j < GIC_NIRQ; j++)
+ for (j = 0; j < s->num_irq; j++)
qemu_put_be32(f, s->last_active[j][i]);
qemu_put_be32(f, s->priority_mask[i]);
qemu_put_be32(f, s->running_irq[i]);
qemu_put_be32(f, s->running_priority[i]);
qemu_put_be32(f, s->current_pending[i]);
}
- for (i = 0; i < GIC_NIRQ - 32; i++) {
+ for (i = 0; i < s->num_irq - 32; i++) {
qemu_put_be32(f, s->priority2[i]);
}
- for (i = 0; i < GIC_NIRQ; i++) {
+ for (i = 0; i < s->num_irq; i++) {
#ifndef NVIC
qemu_put_be32(f, s->irq_target[i]);
#endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
s->cpu_enabled[i] = qemu_get_be32(f);
for (j = 0; j < 32; j++)
s->priority1[j][i] = qemu_get_be32(f);
- for (j = 0; j < GIC_NIRQ; j++)
+ for (j = 0; j < s->num_irq; j++)
s->last_active[j][i] = qemu_get_be32(f);
s->priority_mask[i] = qemu_get_be32(f);
s->running_irq[i] = qemu_get_be32(f);
s->running_priority[i] = qemu_get_be32(f);
s->current_pending[i] = qemu_get_be32(f);
}
- for (i = 0; i < GIC_NIRQ - 32; i++) {
+ for (i = 0; i < s->num_irq - 32; i++) {
s->priority2[i] = qemu_get_be32(f);
}
- for (i = 0; i < GIC_NIRQ; i++) {
+ for (i = 0; i < s->num_irq; i++) {
#ifndef NVIC
s->irq_target[i] = qemu_get_be32(f);
#endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
}
#if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
#else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
#endif
{
int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
#if NCPU > 1
s->num_cpu = num_cpu;
#endif
- qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+ s->num_irq = num_irq + GIC_BASE_IRQ;
+ if (s->num_irq > GIC_MAXIRQ) {
+ hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+ num_irq, GIC_MAXIRQ);
+ }
+ qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
for (i = 0; i < NUM_CPU(s); i++) {
sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
}
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
index 2faed39f0f..ba26abc6f4 100644
--- a/hw/arm_l2x0.c
+++ b/hw/arm_l2x0.c
@@ -160,22 +160,33 @@ static int l2x0_priv_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo l2x0_info = {
- .init = l2x0_priv_init,
- .qdev.name = "l2x0",
- .qdev.size = sizeof(l2x0_state),
- .qdev.vmsd = &vmstate_l2x0,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = l2x0_priv_reset,
+static Property l2x0_properties[] = {
+ DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void l2x0_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = l2x0_priv_init;
+ dc->vmsd = &vmstate_l2x0;
+ dc->no_user = 1;
+ dc->props = l2x0_properties;
+ dc->reset = l2x0_priv_reset;
+}
+
+static TypeInfo l2x0_info = {
+ .name = "l2x0",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(l2x0_state),
+ .class_init = l2x0_class_init,
};
static void l2x0_register_device(void)
{
- sysbus_register_withprop(&l2x0_info);
+ type_register_static(&l2x0_info);
}
device_init(l2x0_register_device)
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 455a0aa55a..5a02365b6f 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -311,22 +311,33 @@ static const VMStateDescription vmstate_arm_mptimer = {
}
};
-static SysBusDeviceInfo arm_mptimer_info = {
- .init = arm_mptimer_init,
- .qdev.name = "arm_mptimer",
- .qdev.size = sizeof(arm_mptimer_state),
- .qdev.vmsd = &vmstate_arm_mptimer,
- .qdev.reset = arm_mptimer_reset,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num-cpu", arm_mptimer_state, num_cpu, 0),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property arm_mptimer_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", arm_mptimer_state, num_cpu, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void arm_mptimer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = arm_mptimer_init;
+ dc->vmsd = &vmstate_arm_mptimer;
+ dc->reset = arm_mptimer_reset;
+ dc->no_user = 1;
+ dc->props = arm_mptimer_properties;
+}
+
+static TypeInfo arm_mptimer_info = {
+ .name = "arm_mptimer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(arm_mptimer_state),
+ .class_init = arm_mptimer_class_init,
};
static void arm_mptimer_register_devices(void)
{
- sysbus_register_withprop(&arm_mptimer_info);
+ type_register_static(&arm_mptimer_info);
}
device_init(arm_mptimer_register_devices)
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 4b88648780..9d257994c0 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -401,22 +401,33 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id, uint32_t proc_id)
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.vmsd = &vmstate_arm_sysctl,
- .qdev.reset = arm_sysctl_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
- DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property arm_sysctl_properties[] = {
+ DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
+ DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_sysctl_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = arm_sysctl_init1;
+ dc->reset = arm_sysctl_reset;
+ dc->vmsd = &vmstate_arm_sysctl;
+ dc->props = arm_sysctl_properties;
+}
+
+static TypeInfo arm_sysctl_info = {
+ .name = "realview_sysctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(arm_sysctl_state),
+ .class_init = arm_sysctl_class_init,
};
static void arm_sysctl_register_devices(void)
{
- sysbus_register_withprop(&arm_sysctl_info);
+ type_register_static(&arm_sysctl_info);
}
device_init(arm_sysctl_register_devices)
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 1902f1a7b9..1019d41b3e 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -273,11 +273,8 @@ static int sp804_init(SysBusDevice *dev)
qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
sysbus_init_irq(dev, &s->irq);
- /* The timers are configurable between 32kHz and 1MHz
- * defaulting to 1MHz but overrideable as individual properties */
s->timer[0] = arm_timer_init(s->freq0);
s->timer[1] = arm_timer_init(s->freq1);
-
s->timer[0]->irq = qi[0];
s->timer[1]->irq = qi[1];
memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
@@ -286,17 +283,6 @@ static int sp804_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo sp804_info = {
- .init = sp804_init,
- .qdev.name = "sp804",
- .qdev.size = sizeof(sp804_state),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
- DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
- DEFINE_PROP_END_OF_LIST(),
- }
-};
-
/* Integrator/CP timer module. */
typedef struct {
@@ -361,10 +347,46 @@ static int icp_pit_init(SysBusDevice *dev)
return 0;
}
+static void icp_pit_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = icp_pit_init;
+}
+
+static TypeInfo icp_pit_info = {
+ .name = "integrator_pit",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(icp_pit_state),
+ .class_init = icp_pit_class_init,
+};
+
+static Property sp804_properties[] = {
+ DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
+ DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sp804_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *k = DEVICE_CLASS(klass);
+
+ sdc->init = sp804_init;
+ k->props = sp804_properties;
+}
+
+static TypeInfo sp804_info = {
+ .name = "sp804",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(sp804_state),
+ .class_init = sp804_class_init,
+};
+
static void arm_timer_register_devices(void)
{
- sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);
- sysbus_register_withprop(&sp804_info);
+ type_register_static(&icp_pit_info);
+ type_register_static(&sp804_info);
}
device_init(arm_timer_register_devices)
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 5c7a9502c6..de3d7e0828 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -245,19 +245,30 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
return pic;
}
-static SysBusDeviceInfo bitband_info = {
- .init = bitband_init,
- .qdev.name = "ARM,bitband-memory",
- .qdev.size = sizeof(BitBandState),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("base", BitBandState, base, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property bitband_properties[] = {
+ DEFINE_PROP_UINT32("base", BitBandState, base, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bitband_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = bitband_init;
+ dc->props = bitband_properties;
+}
+
+static TypeInfo bitband_info = {
+ .name = "ARM,bitband-memory",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BitBandState),
+ .class_init = bitband_class_init,
};
static void armv7m_register_devices(void)
{
- sysbus_register_withprop(&bitband_info);
+ type_register_static(&bitband_info);
}
device_init(armv7m_register_devices)
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c50dc..1ed0abc3e7 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
#include "arm-misc.h"
#include "exec-memory.h"
-/* 32 internal lines (16 used for system exceptions) plus 64 external
- interrupt lines. */
-#define GIC_NIRQ 96
#define NCPU 1
#define NVIC 1
@@ -41,6 +38,7 @@ typedef struct {
int64_t tick;
QEMUTimer *timer;
} systick;
+ uint32_t num_irq;
} nvic_state;
/* qemu timers run at 1GHz. We want something closer to 1MHz. */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
switch (offset) {
case 4: /* Interrupt Control Type. */
- return (GIC_NIRQ / 32) - 1;
+ return (s->num_irq / 32) - 1;
case 0x10: /* SysTick Control and Status. */
val = s->systick.control;
s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
if (s->gic.current_pending[0] != 1023)
val |= (s->gic.current_pending[0] << 12);
/* ISRPENDING */
- for (irq = 32; irq < GIC_NIRQ; irq++) {
+ for (irq = 32; irq < s->num_irq; irq++) {
if (s->gic.irq_state[irq].pending) {
val |= (1 << 22);
break;
@@ -384,16 +382,44 @@ static int armv7m_nvic_init(SysBusDevice *dev)
{
nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
- gic_init(&s->gic);
+ /* note that for the M profile gic_init() takes the number of external
+ * interrupt lines only.
+ */
+ gic_init(&s->gic, s->num_irq);
memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
- vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
return 0;
}
+static Property armv7m_nvic_properties[] = {
+ /* The ARM v7m may have anything from 0 to 496 external interrupt
+ * IRQ lines. We default to 64. Other boards may differ and should
+ * set this property appropriately.
+ */
+ DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = armv7m_nvic_init;
+ dc->vmsd = &vmstate_nvic;
+ dc->props = armv7m_nvic_properties;
+}
+
+static TypeInfo armv7m_nvic_info = {
+ .name = "armv7m_nvic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(nvic_state),
+ .class_init = armv7m_nvic_class_init,
+};
+
static void armv7m_nvic_register_devices(void)
{
- sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+ type_register_static(&armv7m_nvic_info);
}
device_init(armv7m_nvic_register_devices)
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 93fb2ed2c8..c9c11823af 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -221,16 +221,25 @@ static int gpio_i2c_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo gpio_i2c_info = {
- .init = gpio_i2c_init,
- .qdev.name = "gpio_i2c",
- .qdev.desc = "Virtual GPIO to I2C bridge",
- .qdev.size = sizeof(GPIOI2CState),
+static void gpio_i2c_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = gpio_i2c_init;
+ dc->desc = "Virtual GPIO to I2C bridge";
+}
+
+static TypeInfo gpio_i2c_info = {
+ .name = "gpio_i2c",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GPIOI2CState),
+ .class_init = gpio_i2c_class_init,
};
static void bitbang_i2c_register(void)
{
- sysbus_register_withprop(&gpio_i2c_info);
+ type_register_static(&gpio_i2c_info);
}
device_init(bitbang_i2c_register)
diff --git a/hw/boards.h b/hw/boards.h
index 716fd7b1a6..f6d3784cf1 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -22,7 +22,6 @@ typedef struct QEMUMachine {
unsigned int no_serial:1,
no_parallel:1,
use_virtcon:1,
- no_vga:1,
no_floppy:1,
no_cdrom:1,
no_sdcard:1;
diff --git a/hw/bonito.c b/hw/bonito.c
index f2c78377bb..7350a4f9ec 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -766,30 +766,47 @@ PCIBus *bonito_init(qemu_irq *pic)
return b;
}
-static PCIDeviceInfo bonito_info = {
- .qdev.name = "Bonito",
- .qdev.desc = "Host bridge",
- .qdev.size = sizeof(PCIBonitoState),
- .qdev.vmsd = &vmstate_bonito,
- .qdev.no_user = 1,
- .init = bonito_initfn,
- /*Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined"*/
- .vendor_id = 0xdf53,
- .device_id = 0x00d5,
- .revision = 0x01,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void bonito_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = bonito_initfn;
+ k->vendor_id = 0xdf53;
+ k->device_id = 0x00d5;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ dc->desc = "Host bridge";
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_bonito;
+}
+
+static TypeInfo bonito_info = {
+ .name = "Bonito",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIBonitoState),
+ .class_init = bonito_class_init,
};
-static SysBusDeviceInfo bonito_pcihost_info = {
- .init = bonito_pcihost_initfn,
- .qdev.name = "Bonito-pcihost",
- .qdev.size = sizeof(BonitoState),
- .qdev.no_user = 1,
+static void bonito_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = bonito_pcihost_initfn;
+ dc->no_user = 1;
+}
+
+static TypeInfo bonito_pcihost_info = {
+ .name = "Bonito-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BonitoState),
+ .class_init = bonito_pcihost_class_init,
};
static void bonito_register(void)
{
- sysbus_register_withprop(&bonito_pcihost_info);
- pci_qdev_register(&bonito_info);
+ type_register_static(&bonito_pcihost_info);
+ type_register_static(&bonito_info);
}
device_init(bonito_register);
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 2d2ebce852..9510ed4d94 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -564,29 +564,39 @@ static int emulated_exitfn(CCIDCardState *base)
return 0;
}
-static CCIDCardInfo emulated_card_info = {
- .qdev.name = EMULATED_DEV_NAME,
- .qdev.desc = "emulated smartcard",
- .qdev.size = sizeof(EmulatedState),
- .initfn = emulated_initfn,
- .exitfn = emulated_exitfn,
- .get_atr = emulated_get_atr,
- .apdu_from_guest = emulated_apdu_from_guest,
- .qdev.unplug = qdev_simple_unplug_cb,
- .qdev.props = (Property[]) {
- DEFINE_PROP_STRING("backend", EmulatedState, backend_str),
- DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
- DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
- DEFINE_PROP_STRING("cert3", EmulatedState, cert3),
- DEFINE_PROP_STRING("db", EmulatedState, db),
- DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property emulated_card_properties[] = {
+ DEFINE_PROP_STRING("backend", EmulatedState, backend_str),
+ DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
+ DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
+ DEFINE_PROP_STRING("cert3", EmulatedState, cert3),
+ DEFINE_PROP_STRING("db", EmulatedState, db),
+ DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void emulated_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ CCIDCardClass *cc = CCID_CARD_CLASS(klass);
+
+ cc->initfn = emulated_initfn;
+ cc->exitfn = emulated_exitfn;
+ cc->get_atr = emulated_get_atr;
+ cc->apdu_from_guest = emulated_apdu_from_guest;
+ dc->desc = "emulated smartcard";
+ dc->props = emulated_card_properties;
+}
+
+static TypeInfo emulated_card_info = {
+ .name = EMULATED_DEV_NAME,
+ .parent = TYPE_CCID_CARD,
+ .instance_size = sizeof(EmulatedState),
+ .class_init = emulated_class_initfn,
};
static void ccid_card_emulated_register_devices(void)
{
- ccid_card_qdev_register(&emulated_card_info);
+ type_register_static(&emulated_card_info);
}
device_init(ccid_card_emulated_register_devices)
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 9f51c6cb05..a7006ca035 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -316,25 +316,36 @@ static VMStateDescription passthru_vmstate = {
}
};
-static CCIDCardInfo passthru_card_info = {
- .qdev.name = PASSTHRU_DEV_NAME,
- .qdev.desc = "passthrough smartcard",
- .qdev.size = sizeof(PassthruState),
- .qdev.vmsd = &passthru_vmstate,
- .initfn = passthru_initfn,
- .exitfn = passthru_exitfn,
- .get_atr = passthru_get_atr,
- .apdu_from_guest = passthru_apdu_from_guest,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", PassthruState, cs),
- DEFINE_PROP_UINT8("debug", PassthruState, debug, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property passthru_card_properties[] = {
+ DEFINE_PROP_CHR("chardev", PassthruState, cs),
+ DEFINE_PROP_UINT8("debug", PassthruState, debug, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void passthru_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ CCIDCardClass *cc = CCID_CARD_CLASS(klass);
+
+ cc->initfn = passthru_initfn;
+ cc->exitfn = passthru_exitfn;
+ cc->get_atr = passthru_get_atr;
+ cc->apdu_from_guest = passthru_apdu_from_guest;
+ dc->desc = "passthrough smartcard";
+ dc->vmsd = &passthru_vmstate;
+ dc->props = passthru_card_properties;
+}
+
+static TypeInfo passthru_card_info = {
+ .name = PASSTHRU_DEV_NAME,
+ .parent = TYPE_CCID_CARD,
+ .instance_size = sizeof(PassthruState),
+ .class_init = passthru_class_initfn,
};
static void ccid_card_passthru_register_devices(void)
{
- ccid_card_qdev_register(&passthru_card_info);
+ type_register_static(&passthru_card_info);
}
device_init(ccid_card_passthru_register_devices)
diff --git a/hw/ccid.h b/hw/ccid.h
index 9e3abe1b4c..6adc745a6d 100644
--- a/hw/ccid.h
+++ b/hw/ccid.h
@@ -15,26 +15,34 @@
typedef struct CCIDCardState CCIDCardState;
typedef struct CCIDCardInfo CCIDCardInfo;
-/*
- * state of the CCID Card device (i.e. hw/ccid-card-*.c)
- */
-struct CCIDCardState {
- DeviceState qdev;
- uint32_t slot; /* For future use with multiple slot reader. */
-};
+#define TYPE_CCID_CARD "ccid-card"
+#define CCID_CARD(obj) \
+ OBJECT_CHECK(CCIDCardState, (obj), TYPE_CCID_CARD)
+#define CCID_CARD_CLASS(klass) \
+ OBJECT_CLASS_CHECK(CCIDCardClass, (klass), TYPE_CCID_CARD)
+#define CCID_CARD_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(CCIDCardClass, (obj), TYPE_CCID_CARD)
/*
* callbacks to be used by the CCID device (hw/usb-ccid.c) to call
* into the smartcard device (hw/ccid-card-*.c)
*/
-struct CCIDCardInfo {
- DeviceInfo qdev;
+typedef struct CCIDCardClass {
+ DeviceClass parent_class;
const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
void (*apdu_from_guest)(CCIDCardState *card,
const uint8_t *apdu,
uint32_t len);
int (*exitfn)(CCIDCardState *card);
int (*initfn)(CCIDCardState *card);
+} CCIDCardClass;
+
+/*
+ * state of the CCID Card device (i.e. hw/ccid-card-*.c)
+ */
+struct CCIDCardState {
+ DeviceState qdev;
+ uint32_t slot; /* For future use with multiple slot reader. */
};
/*
@@ -46,7 +54,6 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card,
void ccid_card_card_removed(CCIDCardState *card);
void ccid_card_card_inserted(CCIDCardState *card);
void ccid_card_card_error(CCIDCardState *card, uint64_t error);
-void ccid_card_qdev_register(CCIDCardInfo *card);
/*
* support guest visible insertion/removal of ccid devices based on actual
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index f7b1d3d785..a8e8ab7660 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -250,6 +250,11 @@ typedef struct PCICirrusVGAState {
CirrusVGAState cirrus_vga;
} PCICirrusVGAState;
+typedef struct ISACirrusVGAState {
+ ISADevice dev;
+ CirrusVGAState cirrus_vga;
+} ISACirrusVGAState;
+
static uint8_t rop_to_index[256];
/***************************************
@@ -613,11 +618,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
for (y = 0; y < lines; y++) {
off_cur = off_begin;
off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
- off_cur &= TARGET_PAGE_MASK;
- while (off_cur < off_cur_end) {
- memory_region_set_dirty(&s->vga.vram, off_cur);
- off_cur += TARGET_PAGE_SIZE;
- }
+ memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
off_begin += off_pitch;
}
}
@@ -1895,8 +1896,6 @@ static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
*
* write mode 4/5
*
- * assume TARGET_PAGE_SIZE >= 16
- *
***************************************/
static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
@@ -1918,8 +1917,7 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
val <<= 1;
dst++;
}
- memory_region_set_dirty(&s->vga.vram, offset);
- memory_region_set_dirty(&s->vga.vram, offset + 7);
+ memory_region_set_dirty(&s->vga.vram, offset, 8);
}
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@@ -1943,8 +1941,7 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
val <<= 1;
dst += 2;
}
- memory_region_set_dirty(&s->vga.vram, offset);
- memory_region_set_dirty(&s->vga.vram, offset + 15);
+ memory_region_set_dirty(&s->vga.vram, offset, 16);
}
/***************************************
@@ -2034,7 +2031,8 @@ static void cirrus_vga_mem_write(void *opaque,
mode = s->vga.gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
*(s->vga.vram_ptr + bank_offset) = mem_value;
- memory_region_set_dirty(&s->vga.vram, bank_offset);
+ memory_region_set_dirty(&s->vga.vram, bank_offset,
+ sizeof(mem_value));
} else {
if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@@ -2166,6 +2164,15 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
}
}
+#define DEPTH 8
+#include "cirrus_vga_template.h"
+
+#define DEPTH 16
+#include "cirrus_vga_template.h"
+
+#define DEPTH 32
+#include "cirrus_vga_template.h"
+
static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
{
CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
@@ -2306,7 +2313,7 @@ static void cirrus_linear_write(void *opaque, target_phys_addr_t addr,
mode = s->vga.gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
*(s->vga.vram_ptr + addr) = (uint8_t) val;
- memory_region_set_dirty(&s->vga.vram, addr);
+ memory_region_set_dirty(&s->vga.vram, addr, 1);
} else {
if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
@@ -2883,24 +2890,45 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
*
***************************************/
-DeviceState *isa_cirrus_vga_init(MemoryRegion *system_memory)
+static int vga_initfn(ISADevice *dev)
{
- CirrusVGAState *s;
-
- s = g_malloc0(sizeof(CirrusVGAState));
-
- vga_common_init(&s->vga, VGA_RAM_SIZE);
- cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0, system_memory);
- s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
- s->vga.screen_dump, s->vga.text_update,
- &s->vga);
- vmstate_register(NULL, 0, &vmstate_cirrus_vga, s);
+ ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev);
+ VGACommonState *s = &d->cirrus_vga.vga;
+
+ vga_common_init(s, VGA_RAM_SIZE);
+ cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
+ isa_address_space(dev));
+ s->ds = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update,
+ s);
rom_add_vga(VGABIOS_CIRRUS_FILENAME);
/* XXX ISA-LFB support */
/* FIXME not qdev yet */
- return NULL;
+ return 0;
+}
+
+static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
+{
+ ISADeviceClass *k = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_cirrus_vga;
+ k->init = vga_initfn;
}
+static TypeInfo isa_cirrus_vga_info = {
+ .name = "isa-cirrus-vga",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISACirrusVGAState),
+ .class_init = isa_cirrus_vga_class_init,
+};
+
+static void isa_cirrus_vga_register(void)
+{
+ type_register_static(&isa_cirrus_vga_info);
+}
+device_init(isa_cirrus_vga_register)
+
/***************************************
*
* PCI bus support
@@ -2911,8 +2939,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
{
PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
CirrusVGAState *s = &d->cirrus_vga;
- PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, dev->qdev.info);
- int16_t device_id = info->device_id;
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+ int16_t device_id = pc->device_id;
/* setup VGA */
vga_common_init(&s->vga, VGA_RAM_SIZE);
@@ -2946,21 +2974,30 @@ DeviceState *pci_cirrus_vga_init(PCIBus *bus)
return &pci_create_simple(bus, -1, "cirrus-vga")->qdev;
}
-static PCIDeviceInfo cirrus_vga_info = {
- .qdev.name = "cirrus-vga",
- .qdev.desc = "Cirrus CLGD 54xx VGA",
- .qdev.size = sizeof(PCICirrusVGAState),
- .qdev.vmsd = &vmstate_pci_cirrus_vga,
- .no_hotplug = 1,
- .init = pci_cirrus_vga_initfn,
- .romfile = VGABIOS_CIRRUS_FILENAME,
- .vendor_id = PCI_VENDOR_ID_CIRRUS,
- .device_id = CIRRUS_ID_CLGD5446,
- .class_id = PCI_CLASS_DISPLAY_VGA,
+static void cirrus_vga_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = pci_cirrus_vga_initfn;
+ k->romfile = VGABIOS_CIRRUS_FILENAME;
+ k->vendor_id = PCI_VENDOR_ID_CIRRUS;
+ k->device_id = CIRRUS_ID_CLGD5446;
+ k->class_id = PCI_CLASS_DISPLAY_VGA;
+ dc->desc = "Cirrus CLGD 54xx VGA";
+ dc->vmsd = &vmstate_pci_cirrus_vga;
+}
+
+static TypeInfo cirrus_vga_info = {
+ .name = "cirrus-vga",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCICirrusVGAState),
+ .class_init = cirrus_vga_class_init,
};
static void cirrus_vga_register(void)
{
- pci_qdev_register(&cirrus_vga_info);
+ type_register_static(&cirrus_vga_info);
}
device_init(cirrus_vga_register);
diff --git a/hw/cirrus_vga_template.h b/hw/cirrus_vga_template.h
new file mode 100644
index 0000000000..3b28280588
--- /dev/null
+++ b/hw/cirrus_vga_template.h
@@ -0,0 +1,102 @@
+/*
+ * QEMU Cirrus VGA Emulator templates
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if DEPTH == 8
+#define BPP 1
+#elif DEPTH == 15 || DEPTH == 16
+#define BPP 2
+#elif DEPTH == 32
+#define BPP 4
+#else
+#error unsupported depth
+#endif
+
+static void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
+ const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0,
+ unsigned int color1,
+ unsigned int color_xor)
+{
+ const uint8_t *plane0, *plane1;
+ int x, b0, b1;
+ uint8_t *d;
+
+ d = d1;
+ plane0 = src1;
+ plane1 = src1 + poffset;
+ for (x = 0; x < w; x++) {
+ b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
+ b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
+#if DEPTH == 8
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ d[0] ^= color_xor;
+ break;
+ case 2:
+ d[0] = color0;
+ break;
+ case 3:
+ d[0] = color1;
+ break;
+ }
+#elif DEPTH == 16
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint16_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint16_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint16_t *)d)[0] = color1;
+ break;
+ }
+#elif DEPTH == 32
+ switch (b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint32_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint32_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint32_t *)d)[0] = color1;
+ break;
+ }
+#else
+#error unsupported depth
+#endif
+ d += BPP;
+ }
+}
+
+#undef DEPTH
+#undef BPP
diff --git a/hw/container.c b/hw/container.c
deleted file mode 100644
index 9cbf3992c4..0000000000
--- a/hw/container.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "sysbus.h"
-
-static int container_initfn(SysBusDevice *dev)
-{
- return 0;
-}
-
-static SysBusDeviceInfo container_info = {
- .init = container_initfn,
- .qdev.name = "container",
- .qdev.size = sizeof(SysBusDevice),
- .qdev.no_user = 1,
-};
-
-static void container_init(void)
-{
- sysbus_register_withprop(&container_info);
-}
-
-device_init(container_init);
diff --git a/hw/cs4231.c b/hw/cs4231.c
index 2dfb708fe7..c0badbff5c 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -151,20 +151,31 @@ static int cs4231_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo cs4231_info = {
- .init = cs4231_init1,
- .qdev.name = "SUNW,CS4231",
- .qdev.size = sizeof(CSState),
- .qdev.vmsd = &vmstate_cs4231,
- .qdev.reset = cs_reset,
- .qdev.props = (Property[]) {
- {.name = NULL}
- }
+static Property cs4231_properties[] = {
+ {.name = NULL},
+};
+
+static void cs4231_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = cs4231_init1;
+ dc->reset = cs_reset;
+ dc->vmsd = &vmstate_cs4231;
+ dc->props = cs4231_properties;
+}
+
+static TypeInfo cs4231_info = {
+ .name = "SUNW,CS4231",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(CSState),
+ .class_init = cs4231_class_init,
};
static void cs4231_register_devices(void)
{
- sysbus_register_withprop(&cs4231_info);
+ type_register_static(&cs4231_info);
}
device_init(cs4231_register_devices)
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index dc77a3aa15..ad04ad667c 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -622,13 +622,13 @@ static const VMStateDescription vmstate_cs4231a = {
.pre_load = cs4231a_pre_load,
.post_load = cs4231a_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
- VMSTATE_BUFFER(dregs, CSState),
- VMSTATE_INT32(dma_running, CSState),
- VMSTATE_INT32(audio_free, CSState),
- VMSTATE_INT32(transferred, CSState),
- VMSTATE_INT32(aci_counter, CSState),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32_ARRAY (regs, CSState, CS_REGS),
+ VMSTATE_BUFFER (dregs, CSState),
+ VMSTATE_INT32 (dma_running, CSState),
+ VMSTATE_INT32 (audio_free, CSState),
+ VMSTATE_INT32 (transferred, CSState),
+ VMSTATE_INT32 (aci_counter, CSState),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -665,22 +665,32 @@ int cs4231a_init (ISABus *bus)
return 0;
}
-static ISADeviceInfo cs4231a_info = {
- .qdev.name = "cs4231a",
- .qdev.desc = "Crystal Semiconductor CS4231A",
- .qdev.size = sizeof (CSState),
- .qdev.vmsd = &vmstate_cs4231a,
- .init = cs4231a_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32 ("iobase", CSState, port, 0x534),
- DEFINE_PROP_UINT32 ("irq", CSState, irq, 9),
- DEFINE_PROP_UINT32 ("dma", CSState, dma, 3),
- DEFINE_PROP_END_OF_LIST (),
- },
+static Property cs4231a_properties[] = {
+ DEFINE_PROP_HEX32 ("iobase", CSState, port, 0x534),
+ DEFINE_PROP_UINT32 ("irq", CSState, irq, 9),
+ DEFINE_PROP_UINT32 ("dma", CSState, dma, 3),
+ DEFINE_PROP_END_OF_LIST (),
+};
+
+static void cs4231a_class_initfn (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
+ ic->init = cs4231a_initfn;
+ dc->desc = "Crystal Semiconductor CS4231A";
+ dc->vmsd = &vmstate_cs4231a;
+ dc->props = cs4231a_properties;
+}
+
+static TypeInfo cs4231a_info = {
+ .name = "cs4231a",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof (CSState),
+ .class_init = cs4231a_class_initfn,
};
static void cs4231a_register (void)
{
- isa_qdev_register (&cs4231a_info);
+ type_register_static (&cs4231a_info);
}
device_init (cs4231a_register)
diff --git a/hw/debugcon.c b/hw/debugcon.c
index c9ee6d90b0..3903b2605d 100644
--- a/hw/debugcon.c
+++ b/hw/debugcon.c
@@ -87,21 +87,31 @@ static int debugcon_isa_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo debugcon_isa_info = {
- .qdev.name = "isa-debugcon",
- .qdev.size = sizeof(ISADebugconState),
- .init = debugcon_isa_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", ISADebugconState, iobase, 0xe9),
- DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
- DEFINE_PROP_HEX32("readback", ISADebugconState, state.readback, 0xe9),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property debugcon_isa_properties[] = {
+ DEFINE_PROP_HEX32("iobase", ISADebugconState, iobase, 0xe9),
+ DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
+ DEFINE_PROP_HEX32("readback", ISADebugconState, state.readback, 0xe9),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = debugcon_isa_initfn;
+ dc->props = debugcon_isa_properties;
+}
+
+static TypeInfo debugcon_isa_info = {
+ .name = "isa-debugcon",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISADebugconState),
+ .class_init = debugcon_isa_class_initfn,
};
static void debugcon_register_devices(void)
{
- isa_qdev_register(&debugcon_isa_info);
+ type_register_static(&debugcon_isa_info);
}
device_init(debugcon_register_devices)
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 08d4e06697..a40fbcf3e5 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -50,18 +50,27 @@ static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
return irq_num;
}
-static PCIDeviceInfo dec_21154_pci_bridge_info = {
- .qdev.name = "dec-21154-p2p-bridge",
- .qdev.desc = "DEC 21154 PCI-PCI bridge",
- .qdev.size = sizeof(PCIBridge),
- .qdev.vmsd = &vmstate_pci_device,
- .qdev.reset = pci_bridge_reset,
- .init = pci_bridge_initfn,
- .exit = pci_bridge_exitfn,
- .vendor_id = PCI_VENDOR_ID_DEC,
- .device_id = PCI_DEVICE_ID_DEC_21154,
- .config_write = pci_bridge_write_config,
- .is_bridge = 1,
+static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_bridge_initfn;
+ k->exit = pci_bridge_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_DEC;
+ k->device_id = PCI_DEVICE_ID_DEC_21154;
+ k->config_write = pci_bridge_write_config;
+ k->is_bridge = 1;
+ dc->desc = "DEC 21154 PCI-PCI bridge";
+ dc->reset = pci_bridge_reset;
+ dc->vmsd = &vmstate_pci_device;
+}
+
+static TypeInfo dec_21154_pci_bridge_info = {
+ .name = "dec-21154-p2p-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIBridge),
+ .class_init = dec_21154_pci_bridge_class_init,
};
PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
@@ -77,7 +86,7 @@ PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
return pci_bridge_get_sec_bus(br);
}
-static int pci_dec_21154_init_device(SysBusDevice *dev)
+static int pci_dec_21154_device_init(SysBusDevice *dev)
{
DECState *s;
@@ -98,23 +107,44 @@ static int dec_21154_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo dec_21154_pci_host_info = {
- .qdev.name = "dec-21154",
- .qdev.size = sizeof(PCIDevice),
- .init = dec_21154_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_DEC,
- .device_id = PCI_DEVICE_ID_DEC_21154,
- .revision = 0x02,
- .class_id = PCI_CLASS_BRIDGE_PCI,
- .is_bridge = 1,
+static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = dec_21154_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_DEC;
+ k->device_id = PCI_DEVICE_ID_DEC_21154;
+ k->revision = 0x02;
+ k->class_id = PCI_CLASS_BRIDGE_PCI;
+ k->is_bridge = 1;
+}
+
+static TypeInfo dec_21154_pci_host_info = {
+ .name = "dec-21154",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = dec_21154_pci_host_class_init,
+};
+
+static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pci_dec_21154_device_init;
+}
+
+static TypeInfo pci_dec_21154_device_info = {
+ .name = "dec-21154-sysbus",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(DECState),
+ .class_init = pci_dec_21154_device_class_init,
};
static void dec_register_devices(void)
{
- sysbus_register_dev("dec-21154", sizeof(DECState),
- pci_dec_21154_init_device);
- pci_qdev_register(&dec_21154_pci_host_info);
- pci_qdev_register(&dec_21154_pci_bridge_info);
+ type_register_static(&pci_dec_21154_device_info);
+ type_register_static(&dec_21154_pci_host_info);
+ type_register_static(&dec_21154_pci_bridge_info);
}
device_init(dec_register_devices)
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 7aa0832266..539bcebae0 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -134,21 +134,32 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo nvram_sysbus_info = {
- .qdev.name = "ds1225y",
- .qdev.size = sizeof(SysBusNvRamState),
- .qdev.vmsd = &vmstate_nvram,
- .init = nvram_sysbus_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000),
- DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property nvram_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("size", SysBusNvRamState, nvram.chip_size, 0x2000),
+ DEFINE_PROP_STRING("filename", SysBusNvRamState, nvram.filename),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = nvram_sysbus_initfn;
+ dc->vmsd = &vmstate_nvram;
+ dc->props = nvram_sysbus_properties;
+}
+
+static TypeInfo nvram_sysbus_info = {
+ .name = "ds1225y",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusNvRamState),
+ .class_init = nvram_sysbus_class_init,
};
static void nvram_register(void)
{
- sysbus_register_withprop(&nvram_sysbus_info);
+ type_register_static(&nvram_sysbus_info);
}
device_init(nvram_register)
diff --git a/hw/ds1338.c b/hw/ds1338.c
index f754cb7cea..b137e13379 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -13,7 +13,7 @@
#include "i2c.h"
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
time_t offset;
struct tm now;
uint8_t nvram[56];
@@ -21,7 +21,7 @@ typedef struct {
int addr_byte;
} DS1338State;
-static void ds1338_event(i2c_slave *i2c, enum i2c_event event)
+static void ds1338_event(I2CSlave *i2c, enum i2c_event event)
{
DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
@@ -51,7 +51,7 @@ static void ds1338_event(i2c_slave *i2c, enum i2c_event event)
}
}
-static int ds1338_recv(i2c_slave *i2c)
+static int ds1338_recv(I2CSlave *i2c)
{
DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
uint8_t res;
@@ -61,7 +61,7 @@ static int ds1338_recv(i2c_slave *i2c)
return res;
}
-static int ds1338_send(i2c_slave *i2c, uint8_t data)
+static int ds1338_send(I2CSlave *i2c, uint8_t data)
{
DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
if (s->addr_byte) {
@@ -113,23 +113,31 @@ static int ds1338_send(i2c_slave *i2c, uint8_t data)
return 0;
}
-static int ds1338_init(i2c_slave *i2c)
+static int ds1338_init(I2CSlave *i2c)
{
return 0;
}
-static I2CSlaveInfo ds1338_info = {
- .qdev.name = "ds1338",
- .qdev.size = sizeof(DS1338State),
- .init = ds1338_init,
- .event = ds1338_event,
- .recv = ds1338_recv,
- .send = ds1338_send,
+static void ds1338_class_init(ObjectClass *klass, void *data)
+{
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = ds1338_init;
+ k->event = ds1338_event;
+ k->recv = ds1338_recv;
+ k->send = ds1338_send;
+}
+
+static TypeInfo ds1338_info = {
+ .name = "ds1338",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(DS1338State),
+ .class_init = ds1338_class_init,
};
static void ds1338_register_devices(void)
{
- i2c_register_slave(&ds1338_info);
+ type_register_static(&ds1338_info);
}
device_init(ds1338_register_devices)
diff --git a/hw/e1000.c b/hw/e1000.c
index a29c944df4..751f79d5ff 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -466,6 +466,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
bytes = split_size;
if (tp->size + bytes > msh)
bytes = msh - tp->size;
+
+ bytes = MIN(sizeof(tp->data) - tp->size, bytes);
pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes);
if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
memmove(tp->header, tp->data, hdr);
@@ -481,6 +483,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
// context descriptor TSE is not set, while data descriptor TSE is set
DBGOUT(TXERR, "TCP segmentaion Error\n");
} else {
+ split_size = MIN(sizeof(tp->data) - tp->size, split_size);
pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size);
tp->size += split_size;
}
@@ -1130,6 +1133,11 @@ static void e1000_reset(void *opaque)
memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
d->rxbuf_min_shift = 1;
memset(&d->tx, 0, sizeof d->tx);
+
+ if (d->nic->nc.link_down) {
+ d->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+ d->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ }
}
static NetClientInfo net_e1000_info = {
@@ -1174,7 +1182,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
- d->dev.qdev.info->name, d->dev.qdev.id, d);
+ object_get_typename(OBJECT(d)), d->dev.qdev.id, d);
qemu_format_nic_info_str(&d->nic->nc, macaddr);
@@ -1189,28 +1197,39 @@ static void qdev_e1000_reset(DeviceState *dev)
e1000_reset(d);
}
-static PCIDeviceInfo e1000_info = {
- .qdev.name = "e1000",
- .qdev.desc = "Intel Gigabit Ethernet",
- .qdev.size = sizeof(E1000State),
- .qdev.reset = qdev_e1000_reset,
- .qdev.vmsd = &vmstate_e1000,
- .init = pci_e1000_init,
- .exit = pci_e1000_uninit,
- .romfile = "pxe-e1000.rom",
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = E1000_DEVID,
- .revision = 0x03,
- .class_id = PCI_CLASS_NETWORK_ETHERNET,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(E1000State, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property e1000_properties[] = {
+ DEFINE_NIC_PROPERTIES(E1000State, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void e1000_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_e1000_init;
+ k->exit = pci_e1000_uninit;
+ k->romfile = "pxe-e1000.rom";
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = E1000_DEVID;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ dc->desc = "Intel Gigabit Ethernet";
+ dc->reset = qdev_e1000_reset;
+ dc->vmsd = &vmstate_e1000;
+ dc->props = e1000_properties;
+}
+
+static TypeInfo e1000_info = {
+ .name = "e1000",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(E1000State),
+ .class_init = e1000_class_init,
};
static void e1000_register_devices(void)
{
- pci_qdev_register(&e1000_info);
+ type_register_static(&e1000_info);
}
device_init(e1000_register_devices)
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index 774346543a..1cf2090c1f 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -308,22 +308,33 @@ static int ecc_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo ecc_info = {
- .init = ecc_init1,
- .qdev.name = "eccmemctl",
- .qdev.size = sizeof(ECCState),
- .qdev.vmsd = &vmstate_ecc,
- .qdev.reset = ecc_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("version", ECCState, version, -1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ecc_properties[] = {
+ DEFINE_PROP_HEX32("version", ECCState, version, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ecc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = ecc_init1;
+ dc->reset = ecc_reset;
+ dc->vmsd = &vmstate_ecc;
+ dc->props = ecc_properties;
+}
+
+static TypeInfo ecc_info = {
+ .name = "eccmemctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ECCState),
+ .class_init = ecc_class_init,
};
static void ecc_register_devices(void)
{
- sysbus_register_withprop(&ecc_info);
+ type_register_static(&ecc_info);
}
device_init(ecc_register_devices)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6a162f607f..843610c933 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -128,7 +128,13 @@
#define DRVR_INT 0x0200 /* Driver generated interrupt. */
typedef struct {
- PCIDeviceInfo pci;
+ const char *name;
+ const char *desc;
+ uint16_t device_id;
+ uint8_t revision;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_id;
+
uint32_t device;
uint8_t stats_size;
bool has_extended_tcb_support;
@@ -318,6 +324,8 @@ static const uint16_t eepro100_mdi_mask[] = {
#define POLYNOMIAL 0x04c11db6
+static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
+
/* From FreeBSD */
/* XXX: optimize */
static unsigned compute_mcast_idx(const uint8_t * ep)
@@ -487,8 +495,9 @@ static void eepro100_fcp_interrupt(EEPRO100State * s)
}
#endif
-static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
+static void e100_pci_reset(EEPRO100State * s)
{
+ E100PCIDeviceInfo *info = eepro100_get_class(s);
uint32_t device = s->device;
uint8_t *pci_conf = s->dev.config;
@@ -508,8 +517,8 @@ static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
/* Maximum Latency */
pci_set_byte(pci_conf + PCI_MAX_LAT, 0x18);
- s->stats_size = e100_device->stats_size;
- s->has_extended_tcb_support = e100_device->has_extended_tcb_support;
+ s->stats_size = info->stats_size;
+ s->has_extended_tcb_support = info->has_extended_tcb_support;
switch (device) {
case i82550:
@@ -558,7 +567,7 @@ static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
}
assert(s->stats_size > 0 && s->stats_size <= sizeof(s->statistics));
- if (e100_device->power_management) {
+ if (info->power_management) {
/* Power Management Capabilities */
int cfg_offset = 0xdc;
int r = pci_add_capability(&s->dev, PCI_CAP_ID_PM,
@@ -1847,14 +1856,13 @@ static NetClientInfo net_eepro100_info = {
static int e100_nic_init(PCIDevice *pci_dev)
{
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
- E100PCIDeviceInfo *e100_device = DO_UPCAST(E100PCIDeviceInfo, pci.qdev,
- pci_dev->qdev.info);
+ E100PCIDeviceInfo *info = eepro100_get_class(s);
TRACE(OTHER, logout("\n"));
- s->device = e100_device->device;
+ s->device = info->device;
- e100_pci_reset(s, e100_device);
+ e100_pci_reset(s);
/* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
* i82559 and later support 64 or 256 word EEPROM. */
@@ -1878,7 +1886,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
nic_reset(s);
s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
- pci_dev->qdev.info->name, pci_dev->qdev.id, s);
+ object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
TRACE(OTHER, logout("%s\n", s->nic->nc.info_str));
@@ -1897,156 +1905,203 @@ static int e100_nic_init(PCIDevice *pci_dev)
static E100PCIDeviceInfo e100_devices[] = {
{
- .pci.qdev.name = "i82550",
- .pci.qdev.desc = "Intel i82550 Ethernet",
+ .name = "i82550",
+ .desc = "Intel i82550 Ethernet",
.device = i82550,
/* TODO: check device id. */
- .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* Revision ID: 0x0c, 0x0d, 0x0e. */
- .pci.revision = 0x0e,
+ .revision = 0x0e,
/* TODO: check size of statistical counters. */
.stats_size = 80,
/* TODO: check extended tcb support. */
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82551",
- .pci.qdev.desc = "Intel i82551 Ethernet",
+ .name = "i82551",
+ .desc = "Intel i82551 Ethernet",
.device = i82551,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* Revision ID: 0x0f, 0x10. */
- .pci.revision = 0x0f,
+ .revision = 0x0f,
/* TODO: check size of statistical counters. */
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82557a",
- .pci.qdev.desc = "Intel i82557A Ethernet",
+ .name = "i82557a",
+ .desc = "Intel i82557A Ethernet",
.device = i82557A,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x01,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x01,
.power_management = false,
},{
- .pci.qdev.name = "i82557b",
- .pci.qdev.desc = "Intel i82557B Ethernet",
+ .name = "i82557b",
+ .desc = "Intel i82557B Ethernet",
.device = i82557B,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x02,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x02,
.power_management = false,
},{
- .pci.qdev.name = "i82557c",
- .pci.qdev.desc = "Intel i82557C Ethernet",
+ .name = "i82557c",
+ .desc = "Intel i82557C Ethernet",
.device = i82557C,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x03,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x03,
.power_management = false,
},{
- .pci.qdev.name = "i82558a",
- .pci.qdev.desc = "Intel i82558A Ethernet",
+ .name = "i82558a",
+ .desc = "Intel i82558A Ethernet",
.device = i82558A,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x04,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x04,
.stats_size = 76,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82558b",
- .pci.qdev.desc = "Intel i82558B Ethernet",
+ .name = "i82558b",
+ .desc = "Intel i82558B Ethernet",
.device = i82558B,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x05,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x05,
.stats_size = 76,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82559a",
- .pci.qdev.desc = "Intel i82559A Ethernet",
+ .name = "i82559a",
+ .desc = "Intel i82559A Ethernet",
.device = i82559A,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x06,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x06,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82559b",
- .pci.qdev.desc = "Intel i82559B Ethernet",
+ .name = "i82559b",
+ .desc = "Intel i82559B Ethernet",
.device = i82559B,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
- .pci.revision = 0x07,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
+ .revision = 0x07,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82559c",
- .pci.qdev.desc = "Intel i82559C Ethernet",
+ .name = "i82559c",
+ .desc = "Intel i82559C Ethernet",
.device = i82559C,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
+ .device_id = PCI_DEVICE_ID_INTEL_82557,
#if 0
- .pci.revision = 0x08,
+ .revision = 0x08,
#endif
/* TODO: Windows wants revision id 0x0c. */
- .pci.revision = 0x0c,
+ .revision = 0x0c,
#if EEPROM_SIZE > 0
- .pci.subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
- .pci.subsystem_id = 0x0040,
+ .subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
+ .subsystem_id = 0x0040,
#endif
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82559er",
- .pci.qdev.desc = "Intel i82559ER Ethernet",
+ .name = "i82559er",
+ .desc = "Intel i82559ER Ethernet",
.device = i82559ER,
- .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
- .pci.revision = 0x09,
+ .device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .revision = 0x09,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
- .pci.qdev.name = "i82562",
- .pci.qdev.desc = "Intel i82562 Ethernet",
+ .name = "i82562",
+ .desc = "Intel i82562 Ethernet",
.device = i82562,
/* TODO: check device id. */
- .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
+ .device_id = PCI_DEVICE_ID_INTEL_82551IT,
/* TODO: wrong revision id. */
- .pci.revision = 0x0e,
+ .revision = 0x0e,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
},{
/* Toshiba Tecra 8200. */
- .pci.qdev.name = "i82801",
- .pci.qdev.desc = "Intel i82801 Ethernet",
+ .name = "i82801",
+ .desc = "Intel i82801 Ethernet",
.device = i82801,
- .pci.device_id = 0x2449,
- .pci.revision = 0x03,
+ .device_id = 0x2449,
+ .revision = 0x03,
.stats_size = 80,
.has_extended_tcb_support = true,
.power_management = true,
}
};
+static E100PCIDeviceInfo *eepro100_get_class_by_name(const char *typename)
+{
+ E100PCIDeviceInfo *info = NULL;
+ int i;
+
+ /* This is admittedly awkward but also temporary. QOM allows for
+ * parameterized typing and for subclassing both of which would suitable
+ * handle what's going on here. But class_data is already being used as
+ * a stop-gap hack to allow incremental qdev conversion so we cannot use it
+ * right now. Once we merge the final QOM series, we can come back here and
+ * do this in a much more elegant fashion.
+ */
+ for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
+ if (strcmp(e100_devices[i].name, typename) == 0) {
+ info = &e100_devices[i];
+ break;
+ }
+ }
+ assert(info != NULL);
+
+ return info;
+}
+
+static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
+{
+ return eepro100_get_class_by_name(object_get_typename(OBJECT(s)));
+}
+
static Property e100_properties[] = {
DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
DEFINE_PROP_END_OF_LIST(),
};
+static void eepro100_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ E100PCIDeviceInfo *info;
+
+ info = eepro100_get_class_by_name(object_class_get_name(klass));
+
+ dc->props = e100_properties;
+ dc->desc = info->desc;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ k->romfile = "pxe-eepro100.rom";
+ k->init = e100_nic_init;
+ k->exit = pci_nic_uninit;
+ k->device_id = info->device_id;
+ k->revision = info->revision;
+ k->subsystem_vendor_id = info->subsystem_vendor_id;
+ k->subsystem_id = info->subsystem_id;
+}
+
static void eepro100_register_devices(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
- PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
- /* We use the same rom file for all device ids.
- QEMU fixes the device id during rom load. */
- pci_dev->vendor_id = PCI_VENDOR_ID_INTEL;
- pci_dev->class_id = PCI_CLASS_NETWORK_ETHERNET;
- pci_dev->romfile = "pxe-eepro100.rom";
- pci_dev->init = e100_nic_init;
- pci_dev->exit = pci_nic_uninit;
- pci_dev->qdev.props = e100_properties;
- pci_dev->qdev.size = sizeof(EEPRO100State);
- pci_qdev_register(pci_dev);
+ TypeInfo type_info = {};
+ E100PCIDeviceInfo *info = &e100_devices[i];
+
+ type_info.name = info->name;
+ type_info.parent = TYPE_PCI_DEVICE;
+ type_info.class_init = eepro100_class_init;
+ type_info.instance_size = sizeof(EEPRO100State);
+
+ type_register(&type_info);
}
}
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 8b734f2c9f..1bc181555f 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -76,15 +76,23 @@ static int empty_slot_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo empty_slot_info = {
- .init = empty_slot_init1,
- .qdev.name = "empty_slot",
- .qdev.size = sizeof(EmptySlot),
+static void empty_slot_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = empty_slot_init1;
+}
+
+static TypeInfo empty_slot_info = {
+ .name = "empty_slot",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(EmptySlot),
+ .class_init = empty_slot_class_init,
};
static void empty_slot_register_devices(void)
{
- sysbus_register_withprop(&empty_slot_info);
+ type_register_static(&empty_slot_info);
}
device_init(empty_slot_register_devices);
diff --git a/hw/es1370.c b/hw/es1370.c
index 6a3ba55f6f..e377c48e49 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -914,7 +914,7 @@ static const MemoryRegionPortio es1370_portio[] = {
{ 0, 0x40 * 4, 1, .read = es1370_readb, },
{ 0, 0x40 * 2, 2, .read = es1370_readw, },
{ 0, 0x40, 4, .read = es1370_readl, },
- PORTIO_END_OF_LIST()
+ PORTIO_END_OF_LIST ()
};
static const MemoryRegionOps es1370_io_ops = {
@@ -928,12 +928,12 @@ static const VMStateDescription vmstate_es1370_channel = {
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
- VMSTATE_UINT32(shift, struct chan),
- VMSTATE_UINT32(leftover, struct chan),
- VMSTATE_UINT32(scount, struct chan),
- VMSTATE_UINT32(frame_addr, struct chan),
- VMSTATE_UINT32(frame_cnt, struct chan),
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (shift, struct chan),
+ VMSTATE_UINT32 (leftover, struct chan),
+ VMSTATE_UINT32 (scount, struct chan),
+ VMSTATE_UINT32 (frame_addr, struct chan),
+ VMSTATE_UINT32 (frame_cnt, struct chan),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -973,15 +973,15 @@ static const VMStateDescription vmstate_es1370 = {
.minimum_version_id_old = 2,
.post_load = es1370_post_load,
.fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(dev, ES1370State),
- VMSTATE_STRUCT_ARRAY(chan, ES1370State, NB_CHANNELS, 2,
- vmstate_es1370_channel, struct chan),
- VMSTATE_UINT32(ctl, ES1370State),
- VMSTATE_UINT32(status, ES1370State),
- VMSTATE_UINT32(mempage, ES1370State),
- VMSTATE_UINT32(codec, ES1370State),
- VMSTATE_UINT32(sctl, ES1370State),
- VMSTATE_END_OF_LIST()
+ VMSTATE_PCI_DEVICE (dev, ES1370State),
+ VMSTATE_STRUCT_ARRAY (chan, ES1370State, NB_CHANNELS, 2,
+ vmstate_es1370_channel, struct chan),
+ VMSTATE_UINT32 (ctl, ES1370State),
+ VMSTATE_UINT32 (status, ES1370State),
+ VMSTATE_UINT32 (mempage, ES1370State),
+ VMSTATE_UINT32 (codec, ES1370State),
+ VMSTATE_UINT32 (sctl, ES1370State),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1017,7 +1017,7 @@ static int es1370_initfn (PCIDevice *dev)
return 0;
}
-static int es1370_exitfn(PCIDevice *dev)
+static int es1370_exitfn (PCIDevice *dev)
{
ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
@@ -1031,28 +1031,32 @@ int es1370_init (PCIBus *bus)
return 0;
}
-static PCIDeviceInfo es1370_info = {
- .qdev.name = "ES1370",
- .qdev.desc = "ENSONIQ AudioPCI ES1370",
- .qdev.size = sizeof (ES1370State),
- .qdev.vmsd = &vmstate_es1370,
- .init = es1370_initfn,
- .exit = es1370_exitfn,
- .vendor_id = PCI_VENDOR_ID_ENSONIQ,
- .device_id = PCI_DEVICE_ID_ENSONIQ_ES1370,
- .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
-#if 1
- .subsystem_vendor_id = 0x4942,
- .subsystem_id = 0x4c4c,
-#else
- .subsystem_vendor_id = 0x1274,
- .subsystem_id = 0x1371,
-#endif
+static void es1370_class_init (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
+
+ k->init = es1370_initfn;
+ k->exit = es1370_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_ENSONIQ;
+ k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370;
+ k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ k->subsystem_vendor_id = 0x4942;
+ k->subsystem_id = 0x4c4c;
+ dc->desc = "ENSONIQ AudioPCI ES1370";
+ dc->vmsd = &vmstate_es1370;
+}
+
+static TypeInfo es1370_info = {
+ .name = "ES1370",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof (ES1370State),
+ .class_init = es1370_class_init,
};
static void es1370_register (void)
{
- pci_qdev_register (&es1370_info);
+ type_register_static (&es1370_info);
}
device_init (es1370_register);
diff --git a/hw/escc.c b/hw/escc.c
index 81204a633d..9fe282f7b8 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -901,28 +901,39 @@ static int escc_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo escc_info = {
- .init = escc_init1,
- .qdev.name = "escc",
- .qdev.size = sizeof(SerialState),
- .qdev.vmsd = &vmstate_escc,
- .qdev.reset = escc_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("frequency", SerialState, frequency, 0),
- DEFINE_PROP_UINT32("it_shift", SerialState, it_shift, 0),
- DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
- DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
- DEFINE_PROP_UINT32("chnBtype", SerialState, chn[0].type, 0),
- DEFINE_PROP_UINT32("chnAtype", SerialState, chn[1].type, 0),
- DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr),
- DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property escc_properties[] = {
+ DEFINE_PROP_UINT32("frequency", SerialState, frequency, 0),
+ DEFINE_PROP_UINT32("it_shift", SerialState, it_shift, 0),
+ DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
+ DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0),
+ DEFINE_PROP_UINT32("chnBtype", SerialState, chn[0].type, 0),
+ DEFINE_PROP_UINT32("chnAtype", SerialState, chn[1].type, 0),
+ DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr),
+ DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void escc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = escc_init1;
+ dc->reset = escc_reset;
+ dc->vmsd = &vmstate_escc;
+ dc->props = escc_properties;
+}
+
+static TypeInfo escc_info = {
+ .name = "escc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SerialState),
+ .class_init = escc_class_init,
};
static void escc_register_devices(void)
{
- sysbus_register_withprop(&escc_info);
+ type_register_static(&escc_info);
}
device_init(escc_register_devices)
diff --git a/hw/esp.c b/hw/esp.c
index 9551c7846b..2f44386233 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -753,20 +753,31 @@ static int esp_init1(SysBusDevice *dev)
return scsi_bus_legacy_handle_cmdline(&s->bus);
}
-static SysBusDeviceInfo esp_info = {
- .init = esp_init1,
- .qdev.name = "esp",
- .qdev.size = sizeof(ESPState),
- .qdev.vmsd = &vmstate_esp,
- .qdev.reset = esp_hard_reset,
- .qdev.props = (Property[]) {
- {.name = NULL}
- }
+static Property esp_properties[] = {
+ {.name = NULL},
+};
+
+static void esp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = esp_init1;
+ dc->reset = esp_hard_reset;
+ dc->vmsd = &vmstate_esp;
+ dc->props = esp_properties;
+}
+
+static TypeInfo esp_info = {
+ .name = "esp",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ESPState),
+ .class_init = esp_class_init,
};
static void esp_register_devices(void)
{
- sysbus_register_withprop(&esp_info);
+ type_register_static(&esp_info);
}
device_init(esp_register_devices)
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 5afa55fb29..aefd5778ab 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -605,7 +605,7 @@ static int fs_eth_init(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(s)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
tdk_init(&s->phy);
@@ -613,22 +613,33 @@ static int fs_eth_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo etraxfs_eth_info = {
- .init = fs_eth_init,
- .qdev.name = "etraxfs-eth",
- .qdev.size = sizeof(struct fs_eth),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("phyaddr", struct fs_eth, phyaddr, 1),
- DEFINE_PROP_PTR("dma_out", struct fs_eth, vdma_out),
- DEFINE_PROP_PTR("dma_in", struct fs_eth, vdma_in),
- DEFINE_NIC_PROPERTIES(struct fs_eth, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property etraxfs_eth_properties[] = {
+ DEFINE_PROP_UINT32("phyaddr", struct fs_eth, phyaddr, 1),
+ DEFINE_PROP_PTR("dma_out", struct fs_eth, vdma_out),
+ DEFINE_PROP_PTR("dma_in", struct fs_eth, vdma_in),
+ DEFINE_NIC_PROPERTIES(struct fs_eth, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void etraxfs_eth_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = fs_eth_init;
+ dc->props = etraxfs_eth_properties;
+}
+
+static TypeInfo etraxfs_eth_info = {
+ .name = "etraxfs-eth",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct fs_eth),
+ .class_init = etraxfs_eth_class_init,
};
static void etraxfs_eth_register(void)
{
- sysbus_register_withprop(&etraxfs_eth_info);
+ type_register_static(&etraxfs_eth_info);
}
device_init(etraxfs_eth_register)
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 993d6a8885..33541fcc61 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -151,19 +151,30 @@ static int etraxfs_pic_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo etraxfs_pic_info = {
- .init = etraxfs_pic_init,
- .qdev.name = "etraxfs,pic",
- .qdev.size = sizeof(struct etrax_pic),
- .qdev.props = (Property[]) {
- DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property etraxfs_pic_properties[] = {
+ DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = etraxfs_pic_init;
+ dc->props = etraxfs_pic_properties;
+}
+
+static TypeInfo etraxfs_pic_info = {
+ .name = "etraxfs,pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct etrax_pic),
+ .class_init = etraxfs_pic_class_init,
};
static void etraxfs_pic_register(void)
{
- sysbus_register_withprop(&etraxfs_pic_info);
+ type_register_static(&etraxfs_pic_info);
}
device_init(etraxfs_pic_register)
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 2623dab9d4..567cb8cc2d 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -216,7 +216,7 @@ static int etraxfs_ser_init(SysBusDevice *dev)
memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
if (s->chr)
qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
@@ -224,16 +224,25 @@ static int etraxfs_ser_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo etraxfs_ser_info = {
- .init = etraxfs_ser_init,
- .qdev.name = "etraxfs,serial",
- .qdev.size = sizeof(struct etrax_serial),
- .qdev.reset = etraxfs_ser_reset,
+static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = etraxfs_ser_init;
+ dc->reset = etraxfs_ser_reset;
+}
+
+static TypeInfo etraxfs_ser_info = {
+ .name = "etraxfs,serial",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct etrax_serial),
+ .class_init = etraxfs_ser_class_init,
};
static void etraxfs_serial_register(void)
{
- sysbus_register_withprop(&etraxfs_ser_info);
+ type_register_static(&etraxfs_ser_info);
}
device_init(etraxfs_serial_register)
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index 2dfdb3063e..b71c5ee9d5 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -329,10 +329,23 @@ static int etraxfs_timer_init(SysBusDevice *dev)
return 0;
}
+static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = etraxfs_timer_init;
+}
+
+static TypeInfo etraxfs_timer_info = {
+ .name = "etraxfs,timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof (struct etrax_timer),
+ .class_init = etraxfs_timer_class_init,
+};
+
static void etraxfs_timer_register(void)
{
- sysbus_register_dev("etraxfs,timer", sizeof (struct etrax_timer),
- etraxfs_timer_init);
+ type_register_static(&etraxfs_timer_info);
}
device_init(etraxfs_timer_register)
diff --git a/hw/fdc.c b/hw/fdc.c
index 70aa5c7b56..f575a2c9f5 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1959,21 +1959,31 @@ static const VMStateDescription vmstate_isa_fdc ={
}
};
-static ISADeviceInfo isa_fdc_info = {
- .init = isabus_fdc_init1,
- .qdev.name = "isa-fdc",
- .qdev.fw_name = "fdc",
- .qdev.size = sizeof(FDCtrlISABus),
- .qdev.no_user = 1,
- .qdev.vmsd = &vmstate_isa_fdc,
- .qdev.reset = fdctrl_external_reset_isa,
- .qdev.props = (Property[]) {
- DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
- DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
- DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
- DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property isa_fdc_properties[] = {
+ DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
+ DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
+ DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
+ DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void isabus_fdc_class_init1(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = isabus_fdc_init1;
+ dc->fw_name = "fdc";
+ dc->no_user = 1;
+ dc->reset = fdctrl_external_reset_isa;
+ dc->vmsd = &vmstate_isa_fdc;
+ dc->props = isa_fdc_properties;
+}
+
+static TypeInfo isa_fdc_info = {
+ .name = "isa-fdc",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(FDCtrlISABus),
+ .class_init = isabus_fdc_class_init1,
};
static const VMStateDescription vmstate_sysbus_fdc ={
@@ -1986,36 +1996,58 @@ static const VMStateDescription vmstate_sysbus_fdc ={
}
};
-static SysBusDeviceInfo sysbus_fdc_info = {
- .init = sysbus_fdc_init1,
- .qdev.name = "sysbus-fdc",
- .qdev.size = sizeof(FDCtrlSysBus),
- .qdev.vmsd = &vmstate_sysbus_fdc,
- .qdev.reset = fdctrl_external_reset_sysbus,
- .qdev.props = (Property[]) {
- DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs),
- DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property sysbus_fdc_properties[] = {
+ DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs),
+ DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo sun4m_fdc_info = {
- .init = sun4m_fdc_init1,
- .qdev.name = "SUNW,fdtwo",
- .qdev.size = sizeof(FDCtrlSysBus),
- .qdev.vmsd = &vmstate_sysbus_fdc,
- .qdev.reset = fdctrl_external_reset_sysbus,
- .qdev.props = (Property[]) {
- DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs),
- DEFINE_PROP_END_OF_LIST(),
- },
+static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sysbus_fdc_init1;
+ dc->reset = fdctrl_external_reset_sysbus;
+ dc->vmsd = &vmstate_sysbus_fdc;
+ dc->props = sysbus_fdc_properties;
+}
+
+static TypeInfo sysbus_fdc_info = {
+ .name = "sysbus-fdc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FDCtrlSysBus),
+ .class_init = sysbus_fdc_class_init,
+};
+
+static Property sun4m_fdc_properties[] = {
+ DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sun4m_fdc_init1;
+ dc->reset = fdctrl_external_reset_sysbus;
+ dc->vmsd = &vmstate_sysbus_fdc;
+ dc->props = sun4m_fdc_properties;
+}
+
+static TypeInfo sun4m_fdc_info = {
+ .name = "SUNW,fdtwo",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FDCtrlSysBus),
+ .class_init = sun4m_fdc_class_init,
};
static void fdc_register_devices(void)
{
- isa_qdev_register(&isa_fdc_info);
- sysbus_register_withprop(&sysbus_fdc_info);
- sysbus_register_withprop(&sun4m_fdc_info);
+ type_register_static(&isa_fdc_info);
+ type_register_static(&sysbus_fdc_info);
+ type_register_static(&sun4m_fdc_info);
}
device_init(fdc_register_devices)
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 6bf48dc046..ea122fb266 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -87,15 +87,8 @@ void framebuffer_update_display(
dest += i * dest_row_pitch;
for (; i < rows; i++) {
- target_phys_addr_t dirty_offset;
- dirty = 0;
- dirty_offset = 0;
- while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
- dirty |= memory_region_get_dirty(mem, addr + dirty_offset,
+ dirty = memory_region_get_dirty(mem, addr, addr + src_width,
DIRTY_MEMORY_VGA);
- dirty_offset += TARGET_PAGE_SIZE;
- }
-
if (dirty || invalidate) {
fn(opaque, dest, src, cols, dest_col_pitch);
if (first == -1)
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index f9535328f0..6b2f7d1986 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -531,23 +531,34 @@ static int fw_cfg_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo fw_cfg_info = {
- .init = fw_cfg_init1,
- .qdev.name = "fw_cfg",
- .qdev.size = sizeof(FWCfgState),
- .qdev.vmsd = &vmstate_fw_cfg,
- .qdev.reset = fw_cfg_reset,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
- DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property fw_cfg_properties[] = {
+ DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
+ DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void fw_cfg_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = fw_cfg_init1;
+ dc->no_user = 1;
+ dc->reset = fw_cfg_reset;
+ dc->vmsd = &vmstate_fw_cfg;
+ dc->props = fw_cfg_properties;
+}
+
+static TypeInfo fw_cfg_info = {
+ .name = "fw_cfg",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FWCfgState),
+ .class_init = fw_cfg_class_init,
};
static void fw_cfg_register_devices(void)
{
- sysbus_register_withprop(&fw_cfg_info);
+ type_register_static(&fw_cfg_info);
}
device_init(fw_cfg_register_devices)
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 33ec149e0f..66d0044c06 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -62,7 +62,8 @@ typedef struct G364State {
static inline int check_dirty(G364State *s, ram_addr_t page)
{
- return memory_region_get_dirty(&s->mem_vram, page, DIRTY_MEMORY_VGA);
+ return memory_region_get_dirty(&s->mem_vram, page, G364_PAGE_SIZE,
+ DIRTY_MEMORY_VGA);
}
static inline void reset_dirty(G364State *s,
@@ -268,12 +269,9 @@ static void g364fb_update_display(void *opaque)
static inline void g364fb_invalidate_display(void *opaque)
{
G364State *s = opaque;
- int i;
s->blanked = 0;
- for (i = 0; i < s->vram_size; i += G364_PAGE_SIZE) {
- memory_region_set_dirty(&s->mem_vram, i);
- }
+ memory_region_set_dirty(&s->mem_vram, 0, s->vram_size);
}
static void g364fb_reset(G364State *s)
@@ -385,7 +383,7 @@ static void g364fb_update_depth(G364State *s)
static void g364_invalidate_cursor_position(G364State *s)
{
- int ymin, ymax, start, end, i;
+ int ymin, ymax, start, end;
/* invalidate only near the cursor */
ymin = s->cursor_position & 0xfff;
@@ -393,9 +391,7 @@ static void g364_invalidate_cursor_position(G364State *s)
start = ymin * ds_get_linesize(s->ds);
end = (ymax + 1) * ds_get_linesize(s->ds);
- for (i = start; i < end; i += G364_PAGE_SIZE) {
- memory_region_set_dirty(&s->mem_vram, i);
- }
+ memory_region_set_dirty(&s->mem_vram, start, end - start);
}
static void g364fb_ctrl_write(void *opaque,
@@ -553,23 +549,34 @@ static void g364fb_sysbus_reset(DeviceState *d)
g364fb_reset(&s->g364);
}
-static SysBusDeviceInfo g364fb_sysbus_info = {
- .init = g364fb_sysbus_init,
- .qdev.name = "sysbus-g364",
- .qdev.desc = "G364 framebuffer",
- .qdev.size = sizeof(G364SysBusState),
- .qdev.vmsd = &vmstate_g364fb,
- .qdev.reset = g364fb_sysbus_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("vram_size", G364SysBusState, g364.vram_size,
- 8 * 1024 * 1024),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property g364fb_sysbus_properties[] = {
+ DEFINE_PROP_HEX32("vram_size", G364SysBusState, g364.vram_size,
+ 8 * 1024 * 1024),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = g364fb_sysbus_init;
+ dc->desc = "G364 framebuffer";
+ dc->reset = g364fb_sysbus_reset;
+ dc->vmsd = &vmstate_g364fb;
+ dc->props = g364fb_sysbus_properties;
+}
+
+static TypeInfo g364fb_sysbus_info = {
+ .name = "sysbus-g364",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(G364SysBusState),
+ .class_init = g364fb_sysbus_class_init,
};
static void g364fb_register(void)
{
- sysbus_register_withprop(&g364fb_sysbus_info);
+ type_register_static(&g364fb_sysbus_info);
}
device_init(g364fb_register);
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 1e529fb5d0..8122baf482 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -71,7 +71,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
SysBusDevice *s;
GrackleState *d;
- dev = qdev_create(NULL, "grackle");
+ dev = qdev_create(NULL, "grackle-pcihost");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
d = FROM_SYSBUS(GrackleState, s);
@@ -121,21 +121,46 @@ static int grackle_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo grackle_pci_host_info = {
- .qdev.name = "grackle",
- .qdev.size = sizeof(PCIDevice),
- .init = grackle_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_MOTOROLA,
- .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
- .revision = 0x00,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void grackle_pci_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = grackle_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+ k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ dc->no_user = 1;
+}
+
+static TypeInfo grackle_pci_info = {
+ .name = "grackle",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = grackle_pci_class_init,
+};
+
+static void pci_grackle_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = pci_grackle_init_device;
+ dc->no_user = 1;
+}
+
+static TypeInfo grackle_pci_host_info = {
+ .name = "grackle-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GrackleState),
+ .class_init = pci_grackle_class_init,
};
static void grackle_register_devices(void)
{
- sysbus_register_dev("grackle", sizeof(GrackleState),
- pci_grackle_init_device);
- pci_qdev_register(&grackle_pci_host_info);
+ type_register_static(&grackle_pci_info);
+ type_register_static(&grackle_pci_host_info);
}
device_init(grackle_register_devices)
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index f8a64e1644..89de2d85ae 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -24,7 +24,6 @@
#include "sysbus.h"
#include "qemu-char.h"
-#include "ptimer.h"
#include "trace.h"
@@ -66,6 +65,8 @@
#define SCALER_OFFSET 0x0C /* not supported */
#define FIFO_DEBUG_OFFSET 0x10 /* not supported */
+#define FIFO_LENGTH 1024
+
typedef struct UART {
SysBusDevice busdev;
MemoryRegion iomem;
@@ -77,21 +78,67 @@ typedef struct UART {
uint32_t receive;
uint32_t status;
uint32_t control;
+
+ /* FIFO */
+ char buffer[FIFO_LENGTH];
+ int len;
+ int current;
} UART;
+static int uart_data_to_read(UART *uart)
+{
+ return uart->current < uart->len;
+}
+
+static char uart_pop(UART *uart)
+{
+ char ret;
+
+ if (uart->len == 0) {
+ uart->status &= ~UART_DATA_READY;
+ return 0;
+ }
+
+ ret = uart->buffer[uart->current++];
+
+ if (uart->current >= uart->len) {
+ /* Flush */
+ uart->len = 0;
+ uart->current = 0;
+ }
+
+ if (!uart_data_to_read(uart)) {
+ uart->status &= ~UART_DATA_READY;
+ }
+
+ return ret;
+}
+
+static void uart_add_to_fifo(UART *uart,
+ const uint8_t *buffer,
+ int length)
+{
+ if (uart->len + length > FIFO_LENGTH) {
+ abort();
+ }
+ memcpy(uart->buffer + uart->len, buffer, length);
+ uart->len += length;
+}
+
static int grlib_apbuart_can_receive(void *opaque)
{
UART *uart = opaque;
- return !!(uart->status & UART_DATA_READY);
+ return FIFO_LENGTH - uart->len;
}
static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
{
UART *uart = opaque;
- uart->receive = *buf;
- uart->status |= UART_DATA_READY;
+ uart_add_to_fifo(uart, buf, size);
+
+ uart->status |= UART_DATA_READY;
if (uart->control & UART_RECEIVE_INTERRUPT) {
qemu_irq_pulse(uart->irq);
@@ -103,9 +150,39 @@ static void grlib_apbuart_event(void *opaque, int event)
trace_grlib_apbuart_event(event);
}
-static void
-grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
- uint64_t value, unsigned size)
+
+static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
+{
+ UART *uart = opaque;
+
+ addr &= 0xff;
+
+ /* Unit registers */
+ switch (addr) {
+ case DATA_OFFSET:
+ case DATA_OFFSET + 3: /* when only one byte read */
+ return uart_pop(uart);
+
+ case STATUS_OFFSET:
+ /* Read Only */
+ return uart->status;
+
+ case CONTROL_OFFSET:
+ return uart->control;
+
+ case SCALER_OFFSET:
+ /* Not supported */
+ return 0;
+
+ default:
+ trace_grlib_apbuart_readl_unknown(addr);
+ return 0;
+ }
+}
+
+static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
{
UART *uart = opaque;
unsigned char c = 0;
@@ -115,6 +192,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
/* Unit registers */
switch (addr) {
case DATA_OFFSET:
+ case DATA_OFFSET + 3: /* When only one byte write */
c = value & 0xFF;
qemu_chr_fe_write(uart->chr, &c, 1);
return;
@@ -124,7 +202,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
return;
case CONTROL_OFFSET:
- /* Not supported */
+ uart->control = value;
return;
case SCALER_OFFSET:
@@ -138,21 +216,15 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
trace_grlib_apbuart_writel_unknown(addr, value);
}
-static bool grlib_apbuart_accepts(void *opaque, target_phys_addr_t addr,
- unsigned size, bool is_write)
-{
- return is_write && size == 4;
-}
-
static const MemoryRegionOps grlib_apbuart_ops = {
- .write = grlib_apbuart_write,
- .valid.accepts = grlib_apbuart_accepts,
+ .write = grlib_apbuart_write,
+ .read = grlib_apbuart_read,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static int grlib_apbuart_init(SysBusDevice *dev)
{
- UART *uart = FROM_SYSBUS(typeof(*uart), dev);
+ UART *uart = FROM_SYSBUS(typeof(*uart), dev);
qemu_chr_add_handlers(uart->chr,
grlib_apbuart_can_receive,
@@ -170,19 +242,30 @@ static int grlib_apbuart_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo grlib_gptimer_info = {
- .init = grlib_apbuart_init,
- .qdev.name = "grlib,apbuart",
- .qdev.size = sizeof(UART),
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chrdev", UART, chr),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property grlib_gptimer_properties[] = {
+ DEFINE_PROP_CHR("chrdev", UART, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = grlib_apbuart_init;
+ dc->props = grlib_gptimer_properties;
+}
+
+static TypeInfo grlib_gptimer_info = {
+ .name = "grlib,apbuart",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(UART),
+ .class_init = grlib_gptimer_class_init,
};
static void grlib_gptimer_register(void)
{
- sysbus_register_withprop(&grlib_gptimer_info);
+ type_register_static(&grlib_gptimer_info);
}
device_init(grlib_gptimer_register)
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 9c98a830d7..fb0b236746 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -372,22 +372,33 @@ static int grlib_gptimer_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo grlib_gptimer_info = {
- .init = grlib_gptimer_init,
- .qdev.name = "grlib,gptimer",
- .qdev.reset = grlib_gptimer_reset,
- .qdev.size = sizeof(GPTimerUnit),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz, 40000000),
- DEFINE_PROP_UINT32("irq-line", GPTimerUnit, irq_line, 8),
- DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property grlib_gptimer_properties[] = {
+ DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz, 40000000),
+ DEFINE_PROP_UINT32("irq-line", GPTimerUnit, irq_line, 8),
+ DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = grlib_gptimer_init;
+ dc->reset = grlib_gptimer_reset;
+ dc->props = grlib_gptimer_properties;
+}
+
+static TypeInfo grlib_gptimer_info = {
+ .name = "grlib,gptimer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GPTimerUnit),
+ .class_init = grlib_gptimer_class_init,
};
static void grlib_gptimer_register(void)
{
- sysbus_register_withprop(&grlib_gptimer_info);
+ type_register_static(&grlib_gptimer_info);
}
device_init(grlib_gptimer_register)
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index 28725563c0..1e5ad826f5 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -354,21 +354,32 @@ static int grlib_irqmp_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo grlib_irqmp_info = {
- .init = grlib_irqmp_init,
- .qdev.name = "grlib,irqmp",
- .qdev.reset = grlib_irqmp_reset,
- .qdev.size = sizeof(IRQMP),
- .qdev.props = (Property[]) {
- DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in),
- DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property grlib_irqmp_properties[] = {
+ DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in),
+ DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = grlib_irqmp_init;
+ dc->reset = grlib_irqmp_reset;
+ dc->props = grlib_irqmp_properties;
+}
+
+static TypeInfo grlib_irqmp_info = {
+ .name = "grlib,irqmp",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IRQMP),
+ .class_init = grlib_irqmp_class_init,
};
static void grlib_irqmp_register(void)
{
- sysbus_register_withprop(&grlib_irqmp_info);
+ type_register_static(&grlib_irqmp_info);
}
device_init(grlib_irqmp_register)
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 432683acea..e8cd59c3a4 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1136,21 +1136,42 @@ static int gt64120_pci_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo gt64120_pci_info = {
- .qdev.name = "gt64120_pci",
- .qdev.size = sizeof(PCIDevice),
- .init = gt64120_pci_init,
- .vendor_id = PCI_VENDOR_ID_MARVELL,
- .device_id = PCI_DEVICE_ID_MARVELL_GT6412X,
- .revision = 0x10,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void gt64120_pci_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = gt64120_pci_init;
+ k->vendor_id = PCI_VENDOR_ID_MARVELL;
+ k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X;
+ k->revision = 0x10;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static TypeInfo gt64120_pci_info = {
+ .name = "gt64120_pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = gt64120_pci_class_init,
+};
+
+static void gt64120_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = gt64120_init;
+}
+
+static TypeInfo gt64120_info = {
+ .name = "gt64120",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GT64120State),
+ .class_init = gt64120_class_init,
};
static void gt64120_pci_register_devices(void)
{
- sysbus_register_dev("gt64120", sizeof(GT64120State),
- gt64120_init);
- pci_qdev_register(&gt64120_pci_info);
+ type_register_static(&gt64120_info);
+ type_register_static(&gt64120_pci_info);
}
device_init(gt64120_pci_register_devices)
diff --git a/hw/gus.c b/hw/gus.c
index ab872d8dc5..20547075ec 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -221,14 +221,14 @@ static const VMStateDescription vmstate_gus = {
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField []) {
- VMSTATE_INT32(pos, GUSState),
- VMSTATE_INT32(left, GUSState),
- VMSTATE_INT32(shift, GUSState),
- VMSTATE_INT32(irqs, GUSState),
- VMSTATE_INT32(samples, GUSState),
- VMSTATE_INT64(last_ticks, GUSState),
- VMSTATE_BUFFER(himem, GUSState),
- VMSTATE_END_OF_LIST()
+ VMSTATE_INT32 (pos, GUSState),
+ VMSTATE_INT32 (left, GUSState),
+ VMSTATE_INT32 (shift, GUSState),
+ VMSTATE_INT32 (irqs, GUSState),
+ VMSTATE_INT32 (samples, GUSState),
+ VMSTATE_INT64 (last_ticks, GUSState),
+ VMSTATE_BUFFER (himem, GUSState),
+ VMSTATE_END_OF_LIST ()
}
};
@@ -239,13 +239,13 @@ static const MemoryRegionPortio gus_portio_list1[] = {
{0x006, 10, 2, .read = gus_readw, .write = gus_writew },
{0x100, 8, 1, .read = gus_readb, .write = gus_writeb },
{0x100, 8, 2, .read = gus_readw, .write = gus_writew },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static const MemoryRegionPortio gus_portio_list2[] = {
{0, 1, 1, .read = gus_readb },
{0, 1, 2, .read = gus_readw },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
static int gus_initfn (ISADevice *dev)
@@ -299,23 +299,33 @@ int GUS_init (ISABus *bus)
return 0;
}
-static ISADeviceInfo gus_info = {
- .qdev.name = "gus",
- .qdev.desc = "Gravis Ultrasound GF1",
- .qdev.size = sizeof (GUSState),
- .qdev.vmsd = &vmstate_gus,
- .init = gus_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100),
- DEFINE_PROP_HEX32 ("iobase", GUSState, port, 0x240),
- DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7),
- DEFINE_PROP_UINT32 ("dma", GUSState, emu.gusdma, 3),
- DEFINE_PROP_END_OF_LIST (),
- },
+static Property gus_properties[] = {
+ DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100),
+ DEFINE_PROP_HEX32 ("iobase", GUSState, port, 0x240),
+ DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7),
+ DEFINE_PROP_UINT32 ("dma", GUSState, emu.gusdma, 3),
+ DEFINE_PROP_END_OF_LIST (),
+};
+
+static void gus_class_initfn (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
+ ic->init = gus_initfn;
+ dc->desc = "Gravis Ultrasound GF1";
+ dc->vmsd = &vmstate_gus;
+ dc->props = gus_properties;
+}
+
+static TypeInfo gus_info = {
+ .name = "gus",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof (GUSState),
+ .class_init = gus_class_initfn,
};
static void gus_register (void)
{
- isa_qdev_register (&gus_info);
+ type_register_static (&gus_info);
}
device_init (gus_register)
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 9b089e65b4..152f8e6f13 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -777,7 +777,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
uint32_t i, type;
a->desc = desc;
- a->name = a->hda.qdev.info->name;
+ a->name = object_get_typename(OBJECT(a));
dprint(a, 1, "%s: cad %d\n", __FUNCTION__, a->hda.cad);
AUD_register_card("hda", &a->card);
@@ -906,33 +906,51 @@ static int hda_audio_init_duplex(HDACodecDevice *hda)
return hda_audio_init(hda, &duplex);
}
-static HDACodecDeviceInfo hda_audio_info_output = {
- .qdev.name = "hda-output",
- .qdev.desc = "HDA Audio Codec, output-only",
- .qdev.size = sizeof(HDAAudioState),
- .qdev.vmsd = &vmstate_hda_audio,
- .qdev.props = hda_audio_properties,
- .init = hda_audio_init_output,
- .exit = hda_audio_exit,
- .command = hda_audio_command,
- .stream = hda_audio_stream,
+static void hda_audio_output_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
+
+ k->init = hda_audio_init_output;
+ k->exit = hda_audio_exit;
+ k->command = hda_audio_command;
+ k->stream = hda_audio_stream;
+ dc->desc = "HDA Audio Codec, output-only";
+ dc->vmsd = &vmstate_hda_audio;
+ dc->props = hda_audio_properties;
+}
+
+static TypeInfo hda_audio_output_info = {
+ .name = "hda-output",
+ .parent = TYPE_HDA_CODEC_DEVICE,
+ .instance_size = sizeof(HDAAudioState),
+ .class_init = hda_audio_output_class_init,
};
-static HDACodecDeviceInfo hda_audio_info_duplex = {
- .qdev.name = "hda-duplex",
- .qdev.desc = "HDA Audio Codec, duplex",
- .qdev.size = sizeof(HDAAudioState),
- .qdev.vmsd = &vmstate_hda_audio,
- .qdev.props = hda_audio_properties,
- .init = hda_audio_init_duplex,
- .exit = hda_audio_exit,
- .command = hda_audio_command,
- .stream = hda_audio_stream,
+static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
+
+ k->init = hda_audio_init_duplex;
+ k->exit = hda_audio_exit;
+ k->command = hda_audio_command;
+ k->stream = hda_audio_stream;
+ dc->desc = "HDA Audio Codec, duplex";
+ dc->vmsd = &vmstate_hda_audio;
+ dc->props = hda_audio_properties;
+}
+
+static TypeInfo hda_audio_duplex_info = {
+ .name = "hda-duplex",
+ .parent = TYPE_HDA_CODEC_DEVICE,
+ .instance_size = sizeof(HDAAudioState),
+ .class_init = hda_audio_duplex_class_init,
};
static void hda_audio_register(void)
{
- hda_codec_register(&hda_audio_info_output);
- hda_codec_register(&hda_audio_info_duplex);
+ type_register_static(&hda_audio_output_info);
+ type_register_static(&hda_audio_duplex_info);
}
device_init(hda_audio_register);
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000000..684178ee3e
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,339 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define SMP_BOOT_REG 0x40
+#define GIC_BASE_ADDR 0xfff10000
+
+#define NIRQ_GIC 160
+
+/* Board init. */
+static void highbank_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+
+ env->cp15.c15_config_base_address = GIC_BASE_ADDR;
+}
+
+static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+ int n;
+ uint32_t smpboot[] = {
+ 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
+ 0xe210000f, /* ands r0, r0, #0x0f */
+ 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
+ 0xe0830200, /* add r0, r3, r0, lsl #4 */
+ 0xe59f2018, /* ldr r2, privbase */
+ 0xe3a01001, /* mov r1, #1 */
+ 0xe5821100, /* str r1, [r2, #256] */
+ 0xe320f003, /* wfi */
+ 0xe5901000, /* ldr r1, [r0] */
+ 0xe1110001, /* tst r1, r1 */
+ 0x0afffffb, /* beq <wfi> */
+ 0xe12fff11, /* bx r1 */
+ GIC_BASE_ADDR /* privbase: gic address. */
+ };
+ for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+ smpboot[n] = tswap32(smpboot[n]);
+ }
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+}
+
+static void hb_reset_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+ switch (info->nb_cpus) {
+ case 4:
+ stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
+ case 3:
+ stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
+ case 2:
+ stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
+ env->regs[15] = SMP_BOOT_ADDR;
+ break;
+ default:
+ break;
+ }
+}
+
+#define NUM_REGS 0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+ uint64_t value, unsigned size)
+{
+ uint32_t *regs = opaque;
+
+ if (offset == 0xf00) {
+ if (value == 1 || value == 2) {
+ qemu_system_reset_request();
+ } else if (value == 3) {
+ qemu_system_shutdown_request();
+ }
+ }
+
+ regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
+{
+ uint32_t *regs = opaque;
+ uint32_t value = regs[offset/4];
+
+ if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+ value |= 0x30000000;
+ }
+
+ return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+ .read = hb_regs_read,
+ .write = hb_regs_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+ SysBusDevice busdev;
+ MemoryRegion *iomem;
+ uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+ .name = "highbank-regs",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+ SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+ HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+ s->regs[0x40] = 0x05F20121;
+ s->regs[0x41] = 0x2;
+ s->regs[0x42] = 0x05F30121;
+ s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+ HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+ s->iomem = g_new(MemoryRegion, 1);
+ memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+ 0x1000);
+ sysbus_init_mmio(dev, s->iomem);
+
+ return 0;
+}
+
+static void highbank_regs_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ sbc->init = highbank_regs_init;
+ dc->desc = "Calxeda Highbank registers";
+ dc->vmsd = &vmstate_highbank_regs;
+ dc->reset = highbank_regs_reset;
+}
+
+static TypeInfo highbank_regs_info = {
+ .name = "highbank-regs",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(HighbankRegsState),
+ .class_init = highbank_regs_class_init,
+};
+
+static void highbank_regs_register_device(void)
+{
+ type_register_static(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+/* ram_size must be set to match the upper bound of memory in the
+ * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
+ * normally 0xff900000 or -m 4089. When running this board on a
+ * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
+ * device tree and pass -m 2047 to QEMU.
+ */
+static void highbank_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env = NULL;
+ DeviceState *dev;
+ SysBusDevice *busdev;
+ qemu_irq *irqp;
+ qemu_irq pic[128];
+ int n;
+ qemu_irq cpu_irq[4];
+ MemoryRegion *sysram;
+ MemoryRegion *dram;
+ MemoryRegion *sysmem;
+ char *sysboot_filename;
+
+ if (!cpu_model) {
+ cpu_model = "cortex-a9";
+ }
+
+ for (n = 0; n < smp_cpus; n++) {
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "Unable to find CPU definition\n");
+ exit(1);
+ }
+ irqp = arm_pic_init_cpu(env);
+ cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+ qemu_register_reset(highbank_cpu_reset, env);
+ }
+
+ sysmem = get_system_memory();
+ dram = g_new(MemoryRegion, 1);
+ memory_region_init_ram(dram, "highbank.dram", ram_size);
+ /* SDRAM at address zero. */
+ memory_region_add_subregion(sysmem, 0, dram);
+
+ sysram = g_new(MemoryRegion, 1);
+ memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+ memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+ if (bios_name != NULL) {
+ sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (sysboot_filename != NULL) {
+ uint32_t filesize = get_image_size(sysboot_filename);
+ if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+ hw_error("Unable to load %s\n", bios_name);
+ }
+ } else {
+ hw_error("Unable to find %s\n", bios_name);
+ }
+ }
+
+ dev = qdev_create(NULL, "a9mpcore_priv");
+ qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+ qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
+ for (n = 0; n < smp_cpus; n++) {
+ sysbus_connect_irq(busdev, n, cpu_irq[n]);
+ }
+
+ for (n = 0; n < 128; n++) {
+ pic[n] = qdev_get_gpio_in(dev, n);
+ }
+
+ dev = qdev_create(NULL, "l2x0");
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+ dev = qdev_create(NULL, "sp804");
+ qdev_prop_set_uint32(dev, "freq0", 150000000);
+ qdev_prop_set_uint32(dev, "freq1", 150000000);
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, 0xfff34000);
+ sysbus_connect_irq(busdev, 0, pic[18]);
+ sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+ dev = qdev_create(NULL, "highbank-regs");
+ qdev_init_nofail(dev);
+ busdev = sysbus_from_qdev(dev);
+ sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+ sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+ sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+ sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+ sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+ sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+ sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+ sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+ if (nd_table[0].vlan) {
+ qemu_check_nic_model(&nd_table[0], "xgmac");
+ dev = qdev_create(NULL, "xgmac");
+ qdev_set_nic_properties(dev, &nd_table[0]);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+ qemu_check_nic_model(&nd_table[1], "xgmac");
+ dev = qdev_create(NULL, "xgmac");
+ qdev_set_nic_properties(dev, &nd_table[1]);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+ }
+
+ highbank_binfo.ram_size = ram_size;
+ highbank_binfo.kernel_filename = kernel_filename;
+ highbank_binfo.kernel_cmdline = kernel_cmdline;
+ highbank_binfo.initrd_filename = initrd_filename;
+ /* highbank requires a dtb in order to boot, and the dtb will override
+ * the board ID. The following value is ignored, so set it to -1 to be
+ * clear that the value is meaningless.
+ */
+ highbank_binfo.board_id = -1;
+ highbank_binfo.nb_cpus = smp_cpus;
+ highbank_binfo.loader_start = 0;
+ highbank_binfo.write_secondary_boot = hb_write_secondary;
+ highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+ arm_load_kernel(first_cpu, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+ .name = "highbank",
+ .desc = "Calxeda Highbank (ECX-1000)",
+ .init = highbank_init,
+ .use_scsi = 1,
+ .max_cpus = 4,
+};
+
+static void highbank_machine_init(void)
+{
+ qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
diff --git a/hw/hpet.c b/hw/hpet.c
index 5312df7c3a..b6ace4e696 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -695,23 +695,34 @@ static int hpet_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo hpet_device_info = {
- .qdev.name = "hpet",
- .qdev.size = sizeof(HPETState),
- .qdev.no_user = 1,
- .qdev.vmsd = &vmstate_hpet,
- .qdev.reset = hpet_reset,
- .init = hpet_init,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
- DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property hpet_device_properties[] = {
+ DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+ DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void hpet_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = hpet_init;
+ dc->no_user = 1;
+ dc->reset = hpet_reset;
+ dc->vmsd = &vmstate_hpet;
+ dc->props = hpet_device_properties;
+}
+
+static TypeInfo hpet_device_info = {
+ .name = "hpet",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(HPETState),
+ .class_init = hpet_device_class_init,
};
static void hpet_register_device(void)
{
- sysbus_register_withprop(&hpet_device_info);
+ type_register_static(&hpet_device_info);
}
device_init(hpet_register_device)
diff --git a/hw/i2c.c b/hw/i2c.c
index 9bcf3e1d31..8ae4aaae1d 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -12,8 +12,8 @@
struct i2c_bus
{
BusState qbus;
- i2c_slave *current_dev;
- i2c_slave *dev;
+ I2CSlave *current_dev;
+ I2CSlave *dev;
uint8_t saved_address;
};
@@ -21,7 +21,7 @@ static struct BusInfo i2c_bus_info = {
.name = "I2C",
.size = sizeof(i2c_bus),
.props = (Property[]) {
- DEFINE_PROP_UINT8("address", struct i2c_slave, address, 0),
+ DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
DEFINE_PROP_END_OF_LIST(),
}
};
@@ -66,7 +66,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name)
return bus;
}
-void i2c_set_slave_address(i2c_slave *dev, uint8_t address)
+void i2c_set_slave_address(I2CSlave *dev, uint8_t address)
{
dev->address = address;
}
@@ -82,71 +82,100 @@ int i2c_bus_busy(i2c_bus *bus)
int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
{
DeviceState *qdev;
- i2c_slave *slave = NULL;
+ I2CSlave *slave = NULL;
+ I2CSlaveClass *sc;
QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
- i2c_slave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
+ I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
if (candidate->address == address) {
slave = candidate;
break;
}
}
- if (!slave)
+ if (!slave) {
return 1;
+ }
+ sc = I2C_SLAVE_GET_CLASS(slave);
/* If the bus is already busy, assume this is a repeated
start condition. */
bus->current_dev = slave;
- slave->info->event(slave, recv ? I2C_START_RECV : I2C_START_SEND);
+ if (sc->event) {
+ sc->event(slave, recv ? I2C_START_RECV : I2C_START_SEND);
+ }
return 0;
}
void i2c_end_transfer(i2c_bus *bus)
{
- i2c_slave *dev = bus->current_dev;
+ I2CSlave *dev = bus->current_dev;
+ I2CSlaveClass *sc;
- if (!dev)
+ if (!dev) {
return;
+ }
- dev->info->event(dev, I2C_FINISH);
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->event) {
+ sc->event(dev, I2C_FINISH);
+ }
bus->current_dev = NULL;
}
int i2c_send(i2c_bus *bus, uint8_t data)
{
- i2c_slave *dev = bus->current_dev;
+ I2CSlave *dev = bus->current_dev;
+ I2CSlaveClass *sc;
- if (!dev)
+ if (!dev) {
return -1;
+ }
+
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->send) {
+ return sc->send(dev, data);
+ }
- return dev->info->send(dev, data);
+ return -1;
}
int i2c_recv(i2c_bus *bus)
{
- i2c_slave *dev = bus->current_dev;
+ I2CSlave *dev = bus->current_dev;
+ I2CSlaveClass *sc;
- if (!dev)
+ if (!dev) {
return -1;
+ }
+
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->recv) {
+ return sc->recv(dev);
+ }
- return dev->info->recv(dev);
+ return -1;
}
void i2c_nack(i2c_bus *bus)
{
- i2c_slave *dev = bus->current_dev;
+ I2CSlave *dev = bus->current_dev;
+ I2CSlaveClass *sc;
- if (!dev)
+ if (!dev) {
return;
+ }
- dev->info->event(dev, I2C_NACK);
+ sc = I2C_SLAVE_GET_CLASS(dev);
+ if (sc->event) {
+ sc->event(dev, I2C_NACK);
+ }
}
static int i2c_slave_post_load(void *opaque, int version_id)
{
- i2c_slave *dev = opaque;
+ I2CSlave *dev = opaque;
i2c_bus *bus;
bus = FROM_QBUS(i2c_bus, qdev_get_parent_bus(&dev->qdev));
if (bus->saved_address == dev->address) {
@@ -156,33 +185,23 @@ static int i2c_slave_post_load(void *opaque, int version_id)
}
const VMStateDescription vmstate_i2c_slave = {
- .name = "i2c_slave",
+ .name = "I2CSlave",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.post_load = i2c_slave_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT8(address, i2c_slave),
+ VMSTATE_UINT8(address, I2CSlave),
VMSTATE_END_OF_LIST()
}
};
-static int i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base)
+static int i2c_slave_qdev_init(DeviceState *dev)
{
- I2CSlaveInfo *info = container_of(base, I2CSlaveInfo, qdev);
- i2c_slave *s = I2C_SLAVE_FROM_QDEV(dev);
-
- s->info = info;
+ I2CSlave *s = I2C_SLAVE_FROM_QDEV(dev);
+ I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(s);
- return info->init(s);
-}
-
-void i2c_register_slave(I2CSlaveInfo *info)
-{
- assert(info->qdev.size >= sizeof(i2c_slave));
- info->qdev.init = i2c_slave_qdev_init;
- info->qdev.bus_info = &i2c_bus_info;
- qdev_register(&info->qdev);
+ return sc->init(s);
}
DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr)
@@ -194,3 +213,26 @@ DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr)
qdev_init_nofail(dev);
return dev;
}
+
+static void i2c_slave_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = i2c_slave_qdev_init;
+ k->bus_info = &i2c_bus_info;
+}
+
+static TypeInfo i2c_slave_type_info = {
+ .name = TYPE_I2C_SLAVE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(I2CSlave),
+ .abstract = true,
+ .class_size = sizeof(I2CSlaveClass),
+ .class_init = i2c_slave_class_init,
+};
+
+static void i2c_slave_register_devices(void)
+{
+ type_register_static(&i2c_slave_type_info);
+}
+
+device_init(i2c_slave_register_devices);
diff --git a/hw/i2c.h b/hw/i2c.h
index a3383ff025..0f5682b4b0 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -15,36 +15,43 @@ enum i2c_event {
I2C_NACK /* Masker NACKed a receive byte. */
};
-/* Master to slave. */
-typedef int (*i2c_send_cb)(i2c_slave *s, uint8_t data);
-/* Slave to master. */
-typedef int (*i2c_recv_cb)(i2c_slave *s);
-/* Notify the slave of a bus state change. */
-typedef void (*i2c_event_cb)(i2c_slave *s, enum i2c_event event);
+typedef struct I2CSlave I2CSlave;
-typedef int (*i2c_slave_initfn)(i2c_slave *dev);
+#define TYPE_I2C_SLAVE "i2c-slave"
+#define I2C_SLAVE(obj) \
+ OBJECT_CHECK(I2CSlave, (obj), TYPE_I2C_SLAVE)
+#define I2C_SLAVE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(I2CSlaveClass, (klass), TYPE_I2C_SLAVE)
+#define I2C_SLAVE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE)
-typedef struct {
- DeviceInfo qdev;
+typedef struct I2CSlaveClass
+{
+ DeviceClass parent_class;
/* Callbacks provided by the device. */
- i2c_slave_initfn init;
- i2c_event_cb event;
- i2c_recv_cb recv;
- i2c_send_cb send;
-} I2CSlaveInfo;
+ int (*init)(I2CSlave *dev);
+
+ /* Master to slave. */
+ int (*send)(I2CSlave *s, uint8_t data);
+
+ /* Slave to master. */
+ int (*recv)(I2CSlave *s);
-struct i2c_slave
+ /* Notify the slave of a bus state change. */
+ void (*event)(I2CSlave *s, enum i2c_event event);
+} I2CSlaveClass;
+
+struct I2CSlave
{
DeviceState qdev;
- I2CSlaveInfo *info;
/* Remaining fields for internal use by the I2C code. */
uint8_t address;
};
i2c_bus *i2c_init_bus(DeviceState *parent, const char *name);
-void i2c_set_slave_address(i2c_slave *dev, uint8_t address);
+void i2c_set_slave_address(I2CSlave *dev, uint8_t address);
int i2c_bus_busy(i2c_bus *bus);
int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv);
void i2c_end_transfer(i2c_bus *bus);
@@ -52,11 +59,9 @@ void i2c_nack(i2c_bus *bus);
int i2c_send(i2c_bus *bus, uint8_t data);
int i2c_recv(i2c_bus *bus);
-#define I2C_SLAVE_FROM_QDEV(dev) DO_UPCAST(i2c_slave, qdev, dev)
+#define I2C_SLAVE_FROM_QDEV(dev) DO_UPCAST(I2CSlave, qdev, dev)
#define FROM_I2C_SLAVE(type, dev) DO_UPCAST(type, i2c, dev)
-void i2c_register_slave(I2CSlaveInfo *type);
-
DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr);
/* wm8750.c */
@@ -69,7 +74,7 @@ void wm8750_dac_commit(void *opaque);
void wm8750_set_bclk_in(void *opaque, int new_hz);
/* tmp105.c */
-void tmp105_set(i2c_slave *i2c, int temp);
+void tmp105_set(I2CSlave *i2c, int temp);
/* lm832x.c */
void lm832x_key_event(DeviceState *dev, int key, int state);
@@ -78,10 +83,10 @@ extern const VMStateDescription vmstate_i2c_slave;
#define VMSTATE_I2C_SLAVE(_field, _state) { \
.name = (stringify(_field)), \
- .size = sizeof(i2c_slave), \
+ .size = sizeof(I2CSlave), \
.vmsd = &vmstate_i2c_slave, \
.flags = VMS_STRUCT, \
- .offset = vmstate_offset_value(_state, _field, i2c_slave), \
+ .offset = vmstate_offset_value(_state, _field, I2CSlave), \
}
#endif
diff --git a/hw/i82374.c b/hw/i82374.c
new file mode 100644
index 0000000000..220e8cccb6
--- /dev/null
+++ b/hw/i82374.c
@@ -0,0 +1,165 @@
+/*
+ * QEMU Intel 82374 emulation (Enhanced DMA controller)
+ *
+ * Copyright (c) 2010 Hervé Poussineau
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "isa.h"
+
+//#define DEBUG_I82374
+
+#ifdef DEBUG_I82374
+#define DPRINTF(fmt, ...) \
+do { fprintf(stderr, "i82374: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+do {} while (0)
+#endif
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0)
+
+typedef struct I82374State {
+ uint8_t commands[8];
+} I82374State;
+
+static const VMStateDescription vmstate_i82374 = {
+ .name = "i82374",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(commands, I82374State, 8),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static uint32_t i82374_read_isr(void *opaque, uint32_t nport)
+{
+ uint32_t val = 0;
+
+ BADF("%s: %08x\n", __func__, nport);
+
+ DPRINTF("%s: %08x=%08x\n", __func__, nport, val);
+ return val;
+}
+
+static void i82374_write_command(void *opaque, uint32_t nport, uint32_t data)
+{
+ DPRINTF("%s: %08x=%08x\n", __func__, nport, data);
+
+ if (data != 0x42) {
+ /* Not Stop S/G command */
+ BADF("%s: %08x=%08x\n", __func__, nport, data);
+ }
+}
+
+static uint32_t i82374_read_status(void *opaque, uint32_t nport)
+{
+ uint32_t val = 0;
+
+ BADF("%s: %08x\n", __func__, nport);
+
+ DPRINTF("%s: %08x=%08x\n", __func__, nport, val);
+ return val;
+}
+
+static void i82374_write_descriptor(void *opaque, uint32_t nport, uint32_t data)
+{
+ DPRINTF("%s: %08x=%08x\n", __func__, nport, data);
+
+ BADF("%s: %08x=%08x\n", __func__, nport, data);
+}
+
+static uint32_t i82374_read_descriptor(void *opaque, uint32_t nport)
+{
+ uint32_t val = 0;
+
+ BADF("%s: %08x\n", __func__, nport);
+
+ DPRINTF("%s: %08x=%08x\n", __func__, nport, val);
+ return val;
+}
+
+static void i82374_init(I82374State *s)
+{
+ DMA_init(1, NULL);
+ memset(s->commands, 0, sizeof(s->commands));
+}
+
+typedef struct ISAi82374State {
+ ISADevice dev;
+ uint32_t iobase;
+ I82374State state;
+} ISAi82374State;
+
+static const VMStateDescription vmstate_isa_i82374 = {
+ .name = "isa-i82374",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(state, ISAi82374State, 0, vmstate_i82374, I82374State),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static int i82374_isa_init(ISADevice *dev)
+{
+ ISAi82374State *isa = DO_UPCAST(ISAi82374State, dev, dev);
+ I82374State *s = &isa->state;
+
+ register_ioport_read(isa->iobase + 0x0A, 1, 1, i82374_read_isr, s);
+ register_ioport_write(isa->iobase + 0x10, 8, 1, i82374_write_command, s);
+ register_ioport_read(isa->iobase + 0x18, 8, 1, i82374_read_status, s);
+ register_ioport_write(isa->iobase + 0x20, 0x20, 1, i82374_write_descriptor, s);
+ register_ioport_read(isa->iobase + 0x20, 0x20, 1, i82374_read_descriptor, s);
+
+ i82374_init(s);
+
+ return 0;
+}
+
+static Property i82374_properties[] = {
+ DEFINE_PROP_HEX32("iobase", ISAi82374State, iobase, 0x400),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void i82374_class_init(ObjectClass *klass, void *data)
+{
+ ISADeviceClass *k = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = i82374_isa_init;
+ dc->vmsd = &vmstate_isa_i82374;
+ dc->props = i82374_properties;
+}
+
+static TypeInfo i82374_isa_info = {
+ .name = "i82374",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISAi82374State),
+ .class_init = i82374_class_init,
+};
+
+static void i82374_register_devices(void)
+{
+ type_register_static(&i82374_isa_info);
+}
+
+device_init(i82374_register_devices)
diff --git a/hw/i82378.c b/hw/i82378.c
new file mode 100644
index 0000000000..9c3efe8b95
--- /dev/null
+++ b/hw/i82378.c
@@ -0,0 +1,275 @@
+/*
+ * QEMU Intel i82378 emulation (PCI to ISA bridge)
+ *
+ * Copyright (c) 2010-2011 Hervé Poussineau
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pci.h"
+#include "pc.h"
+
+//#define DEBUG_I82378
+
+#ifdef DEBUG_I82378
+#define DPRINTF(fmt, ...) \
+do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+do {} while (0)
+#endif
+
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
+
+typedef struct I82378State {
+ qemu_irq out[2];
+ qemu_irq *i8259;
+ MemoryRegion io;
+ MemoryRegion mem;
+} I82378State;
+
+typedef struct PCIi82378State {
+ PCIDevice pci_dev;
+ uint32_t isa_io_base;
+ uint32_t isa_mem_base;
+ I82378State state;
+} PCIi82378State;
+
+static const VMStateDescription vmstate_pci_i82378 = {
+ .name = "pci-i82378",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void i82378_io_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned int size)
+{
+ switch (size) {
+ case 1:
+ DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outb(addr, value);
+ break;
+ case 2:
+ DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outw(addr, value);
+ break;
+ case 4:
+ DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outl(addr, value);
+ break;
+ default:
+ abort();
+ }
+}
+
+static uint64_t i82378_io_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ switch (size) {
+ case 1:
+ return cpu_inb(addr);
+ case 2:
+ return cpu_inw(addr);
+ case 4:
+ return cpu_inl(addr);
+ default:
+ abort();
+ }
+}
+
+static const MemoryRegionOps i82378_io_ops = {
+ .read = i82378_io_read,
+ .write = i82378_io_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void i82378_mem_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned int size)
+{
+ switch (size) {
+ case 1:
+ DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outb(addr, value);
+ break;
+ case 2:
+ DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outw(addr, value);
+ break;
+ case 4:
+ DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
+ addr, value);
+ cpu_outl(addr, value);
+ break;
+ default:
+ abort();
+ }
+}
+
+static uint64_t i82378_mem_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
+{
+ DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
+ switch (size) {
+ case 1:
+ return cpu_inb(addr);
+ case 2:
+ return cpu_inw(addr);
+ case 4:
+ return cpu_inl(addr);
+ default:
+ abort();
+ }
+}
+
+static const MemoryRegionOps i82378_mem_ops = {
+ .read = i82378_mem_read,
+ .write = i82378_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void i82378_request_out0_irq(void *opaque, int irq, int level)
+{
+ I82378State *s = opaque;
+ qemu_set_irq(s->out[0], level);
+}
+
+static void i82378_request_pic_irq(void *opaque, int irq, int level)
+{
+ DeviceState *dev = opaque;
+ PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev);
+ PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci);
+
+ qemu_set_irq(s->state.i8259[irq], level);
+}
+
+static void i82378_init(DeviceState *dev, I82378State *s)
+{
+ ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0"));
+ ISADevice *pit;
+ qemu_irq *out0_irq;
+
+ /* This device has:
+ 2 82C59 (irq)
+ 1 82C54 (pit)
+ 2 82C37 (dma)
+ NMI
+ Utility Bus Support Registers
+
+ All devices accept byte access only, except timer
+ */
+
+ qdev_init_gpio_out(dev, s->out, 2);
+ qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
+
+ /* Workaround the fact that i8259 is not qdev'ified... */
+ out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);
+
+ /* 2 82C59 (irq) */
+ s->i8259 = i8259_init(isabus, *out0_irq);
+ isa_bus_irqs(isabus, s->i8259);
+
+ /* 1 82C54 (pit) */
+ pit = pit_init(isabus, 0x40, 0);
+
+ /* speaker */
+ pcspk_init(pit);
+
+ /* 2 82C37 (dma) */
+ DMA_init(1, &s->out[1]);
+ isa_create_simple(isabus, "i82374");
+
+ /* timer */
+ isa_create_simple(isabus, "mc146818rtc");
+}
+
+static int pci_i82378_init(PCIDevice *dev)
+{
+ PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev);
+ I82378State *s = &pci->state;
+ uint8_t *pci_conf;
+
+ pci_conf = dev->config;
+ pci_set_word(pci_conf + PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM);
+
+ pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
+
+ memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000);
+ pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
+
+ memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
+ memory_region_set_coalescing(&s->mem);
+ pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
+
+ /* Make I/O address read only */
+ pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL);
+ pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0);
+ pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base);
+
+ isa_mem_base = pci->isa_mem_base;
+ isa_bus_new(&dev->qdev, pci_address_space_io(dev));
+
+ i82378_init(&dev->qdev, s);
+
+ return 0;
+}
+
+static Property i82378_properties[] = {
+ DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
+ DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void pci_i82378_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = pci_i82378_init;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82378;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+ k->subsystem_vendor_id = 0x0;
+ k->subsystem_id = 0x0;
+ dc->vmsd = &vmstate_pci_i82378;
+ dc->props = i82378_properties;
+}
+
+static TypeInfo pci_i82378_info = {
+ .name = "i82378",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIi82378State),
+ .class_init = pci_i82378_class_init,
+};
+
+static void i82378_register_devices(void)
+{
+ type_register_static(&pci_i82378_info);
+}
+
+device_init(i82378_register_devices)
diff --git a/hw/i8254.c b/hw/i8254.c
index cf9ed2ff25..522fed8809 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -535,22 +535,32 @@ static int pit_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo pit_info = {
- .qdev.name = "isa-pit",
- .qdev.size = sizeof(PITState),
- .qdev.vmsd = &vmstate_pit,
- .qdev.reset = pit_reset,
- .qdev.no_user = 1,
- .init = pit_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("irq", PITState, irq, -1),
- DEFINE_PROP_HEX32("iobase", PITState, iobase, -1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property pit_properties[] = {
+ DEFINE_PROP_UINT32("irq", PITState, irq, -1),
+ DEFINE_PROP_HEX32("iobase", PITState, iobase, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pit_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = pit_initfn;
+ dc->no_user = 1;
+ dc->reset = pit_reset;
+ dc->vmsd = &vmstate_pit;
+ dc->props = pit_properties;
+}
+
+static TypeInfo pit_info = {
+ .name = "isa-pit",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(PITState),
+ .class_init = pit_class_initfn,
};
static void pit_register(void)
{
- isa_qdev_register(&pit_info);
+ type_register_static(&pit_info);
}
device_init(pit_register)
diff --git a/hw/i8259.c b/hw/i8259.c
index 7331e0e61c..7ae53805d7 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -26,6 +26,7 @@
#include "isa.h"
#include "monitor.h"
#include "qemu-timer.h"
+#include "i8259_internal.h"
/* debug PIC */
//#define DEBUG_PIC
@@ -40,33 +41,6 @@
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
-struct PicState {
- ISADevice dev;
- uint8_t last_irr; /* edge detection */
- uint8_t irr; /* interrupt request register */
- uint8_t imr; /* interrupt mask register */
- uint8_t isr; /* interrupt service register */
- uint8_t priority_add; /* highest irq priority */
- uint8_t irq_base;
- uint8_t read_reg_select;
- uint8_t poll;
- uint8_t special_mask;
- uint8_t init_state;
- uint8_t auto_eoi;
- uint8_t rotate_on_auto_eoi;
- uint8_t special_fully_nested_mode;
- uint8_t init4; /* true if 4 byte init */
- uint8_t single_mode; /* true if slave pic is not initialized */
- uint8_t elcr; /* PIIX edge/trigger selection*/
- uint8_t elcr_mask;
- qemu_irq int_out[1];
- uint32_t master; /* reflects /SP input pin */
- uint32_t iobase;
- uint32_t elcr_addr;
- MemoryRegion base_io;
- MemoryRegion elcr_io;
-};
-
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
@@ -76,12 +50,12 @@ static uint64_t irq_count[16];
#ifdef DEBUG_IRQ_LATENCY
static int64_t irq_time[16];
#endif
-PicState *isa_pic;
-static PicState *slave_pic;
+DeviceState *isa_pic;
+static PICCommonState *slave_pic;
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
-static int get_priority(PicState *s, int mask)
+static int get_priority(PICCommonState *s, int mask)
{
int priority;
@@ -96,7 +70,7 @@ static int get_priority(PicState *s, int mask)
}
/* return the pic wanted interrupt. return -1 if none */
-static int pic_get_irq(PicState *s)
+static int pic_get_irq(PICCommonState *s)
{
int mask, cur_priority, priority;
@@ -125,7 +99,7 @@ static int pic_get_irq(PicState *s)
}
/* Update INT output. Must be called every time the output may have changed. */
-static void pic_update_irq(PicState *s)
+static void pic_update_irq(PICCommonState *s)
{
int irq;
@@ -142,7 +116,7 @@ static void pic_update_irq(PicState *s)
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static void pic_set_irq(void *opaque, int irq, int level)
{
- PicState *s = opaque;
+ PICCommonState *s = opaque;
int mask = 1 << irq;
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) || \
@@ -190,7 +164,7 @@ static void pic_set_irq(void *opaque, int irq, int level)
}
/* acknowledge interrupt 'irq' */
-static void pic_intack(PicState *s, int irq)
+static void pic_intack(PICCommonState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi) {
@@ -206,8 +180,9 @@ static void pic_intack(PicState *s, int irq)
pic_update_irq(s);
}
-int pic_read_irq(PicState *s)
+int pic_read_irq(DeviceState *d)
{
+ PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, d);
int irq, irq2, intno;
irq = pic_get_irq(s);
@@ -246,30 +221,15 @@ int pic_read_irq(PicState *s)
return intno;
}
-static void pic_init_reset(PicState *s)
+static void pic_init_reset(PICCommonState *s)
{
- s->last_irr = 0;
- s->irr = 0;
- s->imr = 0;
- s->isr = 0;
- s->priority_add = 0;
- s->irq_base = 0;
- s->read_reg_select = 0;
- s->poll = 0;
- s->special_mask = 0;
- s->init_state = 0;
- s->auto_eoi = 0;
- s->rotate_on_auto_eoi = 0;
- s->special_fully_nested_mode = 0;
- s->init4 = 0;
- s->single_mode = 0;
- /* Note: ELCR is not reset */
+ pic_reset_common(s);
pic_update_irq(s);
}
static void pic_reset(DeviceState *dev)
{
- PicState *s = container_of(dev, PicState, dev.qdev);
+ PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, dev);
pic_init_reset(s);
s->elcr = 0;
@@ -278,7 +238,7 @@ static void pic_reset(DeviceState *dev)
static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
uint64_t val64, unsigned size)
{
- PicState *s = opaque;
+ PICCommonState *s = opaque;
uint32_t addr = addr64;
uint32_t val = val64;
int priority, cmd, irq;
@@ -372,7 +332,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
- PicState *s = opaque;
+ PICCommonState *s = opaque;
int ret;
if (s->poll) {
@@ -399,51 +359,27 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
return ret;
}
-int pic_get_output(PicState *s)
+int pic_get_output(DeviceState *d)
{
+ PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, d);
+
return (pic_get_irq(s) >= 0);
}
static void elcr_ioport_write(void *opaque, target_phys_addr_t addr,
uint64_t val, unsigned size)
{
- PicState *s = opaque;
+ PICCommonState *s = opaque;
s->elcr = val & s->elcr_mask;
}
static uint64_t elcr_ioport_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
- PicState *s = opaque;
+ PICCommonState *s = opaque;
return s->elcr;
}
-static const VMStateDescription vmstate_pic = {
- .name = "i8259",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(last_irr, PicState),
- VMSTATE_UINT8(irr, PicState),
- VMSTATE_UINT8(imr, PicState),
- VMSTATE_UINT8(isr, PicState),
- VMSTATE_UINT8(priority_add, PicState),
- VMSTATE_UINT8(irq_base, PicState),
- VMSTATE_UINT8(read_reg_select, PicState),
- VMSTATE_UINT8(poll, PicState),
- VMSTATE_UINT8(special_mask, PicState),
- VMSTATE_UINT8(init_state, PicState),
- VMSTATE_UINT8(auto_eoi, PicState),
- VMSTATE_UINT8(rotate_on_auto_eoi, PicState),
- VMSTATE_UINT8(special_fully_nested_mode, PicState),
- VMSTATE_UINT8(init4, PicState),
- VMSTATE_UINT8(single_mode, PicState),
- VMSTATE_UINT8(elcr, PicState),
- VMSTATE_END_OF_LIST()
- }
-};
-
static const MemoryRegionOps pic_base_ioport_ops = {
.read = pic_ioport_read,
.write = pic_ioport_write,
@@ -462,36 +398,25 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
},
};
-static int pic_initfn(ISADevice *dev)
+static void pic_init(PICCommonState *s)
{
- PicState *s = DO_UPCAST(PicState, dev, dev);
-
memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
- isa_register_ioport(dev, &s->base_io, s->iobase);
- if (s->elcr_addr != -1) {
- isa_register_ioport(dev, &s->elcr_io, s->elcr_addr);
- }
-
- qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out));
- qdev_init_gpio_in(&dev->qdev, pic_set_irq, 8);
-
- qdev_set_legacy_instance_id(&dev->qdev, s->iobase, 1);
-
- return 0;
+ qdev_init_gpio_out(&s->dev.qdev, s->int_out, ARRAY_SIZE(s->int_out));
+ qdev_init_gpio_in(&s->dev.qdev, pic_set_irq, 8);
}
void pic_info(Monitor *mon)
{
int i;
- PicState *s;
+ PICCommonState *s;
if (!isa_pic) {
return;
}
for (i = 0; i < 2; i++) {
- s = i == 0 ? isa_pic : slave_pic;
+ s = i == 0 ? DO_UPCAST(PICCommonState, dev.qdev, isa_pic) : slave_pic;
monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
"irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
i, s->irr, s->imr, s->isr, s->priority_add,
@@ -526,54 +451,46 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq)
irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
- dev = isa_create(bus, "isa-i8259");
- qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
- qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
- qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
- qdev_prop_set_bit(&dev->qdev, "master", true);
- qdev_init_nofail(&dev->qdev);
+ dev = i8259_init_chip("isa-i8259", bus, true);
qdev_connect_gpio_out(&dev->qdev, 0, parent_irq);
for (i = 0 ; i < 8; i++) {
irq_set[i] = qdev_get_gpio_in(&dev->qdev, i);
}
- isa_pic = DO_UPCAST(PicState, dev, dev);
+ isa_pic = &dev->qdev;
- dev = isa_create(bus, "isa-i8259");
- qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
- qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1);
- qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde);
- qdev_init_nofail(&dev->qdev);
+ dev = i8259_init_chip("isa-i8259", bus, false);
qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]);
for (i = 0 ; i < 8; i++) {
irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i);
}
- slave_pic = DO_UPCAST(PicState, dev, dev);
+ slave_pic = DO_UPCAST(PICCommonState, dev, dev);
return irq_set;
}
-static ISADeviceInfo i8259_info = {
- .qdev.name = "isa-i8259",
- .qdev.size = sizeof(PicState),
- .qdev.vmsd = &vmstate_pic,
- .qdev.reset = pic_reset,
- .qdev.no_user = 1,
- .init = pic_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", PicState, iobase, -1),
- DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr, -1),
- DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask, -1),
- DEFINE_PROP_BIT("master", PicState, master, 0, false),
- DEFINE_PROP_END_OF_LIST(),
- },
+static void i8259_class_init(ObjectClass *klass, void *data)
+{
+ PICCommonClass *k = PIC_COMMON_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = pic_init;
+ dc->reset = pic_reset;
+}
+
+static TypeInfo i8259_info = {
+ .name = "isa-i8259",
+ .instance_size = sizeof(PICCommonState),
+ .parent = TYPE_PIC_COMMON,
+ .class_init = i8259_class_init,
};
static void pic_register(void)
{
- isa_qdev_register(&i8259_info);
+ type_register_static(&i8259_info);
}
+
device_init(pic_register)
diff --git a/hw/i8259_common.c b/hw/i8259_common.c
new file mode 100644
index 0000000000..9f150bc6d0
--- /dev/null
+++ b/hw/i8259_common.c
@@ -0,0 +1,161 @@
+/*
+ * QEMU 8259 - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "pc.h"
+#include "i8259_internal.h"
+
+void pic_reset_common(PICCommonState *s)
+{
+ s->last_irr = 0;
+ s->irr = 0;
+ s->imr = 0;
+ s->isr = 0;
+ s->priority_add = 0;
+ s->irq_base = 0;
+ s->read_reg_select = 0;
+ s->poll = 0;
+ s->special_mask = 0;
+ s->init_state = 0;
+ s->auto_eoi = 0;
+ s->rotate_on_auto_eoi = 0;
+ s->special_fully_nested_mode = 0;
+ s->init4 = 0;
+ s->single_mode = 0;
+ /* Note: ELCR is not reset */
+}
+
+static void pic_dispatch_pre_save(void *opaque)
+{
+ PICCommonState *s = opaque;
+ PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
+
+ if (info->pre_save) {
+ info->pre_save(s);
+ }
+}
+
+static int pic_dispatch_post_load(void *opaque, int version_id)
+{
+ PICCommonState *s = opaque;
+ PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
+
+ if (info->post_load) {
+ info->post_load(s);
+ }
+ return 0;
+}
+
+static int pic_init_common(ISADevice *dev)
+{
+ PICCommonState *s = DO_UPCAST(PICCommonState, dev, dev);
+ PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
+
+ info->init(s);
+
+ isa_register_ioport(NULL, &s->base_io, s->iobase);
+ if (s->elcr_addr != -1) {
+ isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
+ }
+
+ qdev_set_legacy_instance_id(&s->dev.qdev, s->iobase, 1);
+
+ return 0;
+}
+
+ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master)
+{
+ ISADevice *dev;
+
+ dev = isa_create(bus, name);
+ qdev_prop_set_uint32(&dev->qdev, "iobase", master ? 0x20 : 0xa0);
+ qdev_prop_set_uint32(&dev->qdev, "elcr_addr", master ? 0x4d0 : 0x4d1);
+ qdev_prop_set_uint8(&dev->qdev, "elcr_mask", master ? 0xf8 : 0xde);
+ qdev_prop_set_bit(&dev->qdev, "master", master);
+ qdev_init_nofail(&dev->qdev);
+
+ return dev;
+}
+
+static const VMStateDescription vmstate_pic_common = {
+ .name = "i8259",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_save = pic_dispatch_pre_save,
+ .post_load = pic_dispatch_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(last_irr, PICCommonState),
+ VMSTATE_UINT8(irr, PICCommonState),
+ VMSTATE_UINT8(imr, PICCommonState),
+ VMSTATE_UINT8(isr, PICCommonState),
+ VMSTATE_UINT8(priority_add, PICCommonState),
+ VMSTATE_UINT8(irq_base, PICCommonState),
+ VMSTATE_UINT8(read_reg_select, PICCommonState),
+ VMSTATE_UINT8(poll, PICCommonState),
+ VMSTATE_UINT8(special_mask, PICCommonState),
+ VMSTATE_UINT8(init_state, PICCommonState),
+ VMSTATE_UINT8(auto_eoi, PICCommonState),
+ VMSTATE_UINT8(rotate_on_auto_eoi, PICCommonState),
+ VMSTATE_UINT8(special_fully_nested_mode, PICCommonState),
+ VMSTATE_UINT8(init4, PICCommonState),
+ VMSTATE_UINT8(single_mode, PICCommonState),
+ VMSTATE_UINT8(elcr, PICCommonState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property pic_properties_common[] = {
+ DEFINE_PROP_HEX32("iobase", PICCommonState, iobase, -1),
+ DEFINE_PROP_HEX32("elcr_addr", PICCommonState, elcr_addr, -1),
+ DEFINE_PROP_HEX8("elcr_mask", PICCommonState, elcr_mask, -1),
+ DEFINE_PROP_BIT("master", PICCommonState, master, 0, false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pic_common_class_init(ObjectClass *klass, void *data)
+{
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_pic_common;
+ dc->no_user = 1;
+ dc->props = pic_properties_common;
+ ic->init = pic_init_common;
+}
+
+static TypeInfo pic_common_type = {
+ .name = TYPE_PIC_COMMON,
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(PICCommonState),
+ .class_size = sizeof(PICCommonClass),
+ .class_init = pic_common_class_init,
+ .abstract = true,
+};
+
+static void register_devices(void)
+{
+ type_register_static(&pic_common_type);
+}
+
+device_init(register_devices);
diff --git a/hw/i8259_internal.h b/hw/i8259_internal.h
new file mode 100644
index 0000000000..4137b61703
--- /dev/null
+++ b/hw/i8259_internal.h
@@ -0,0 +1,82 @@
+/*
+ * QEMU 8259 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_I8259_INTERNAL_H
+#define QEMU_I8259_INTERNAL_H
+
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+
+typedef struct PICCommonState PICCommonState;
+
+#define TYPE_PIC_COMMON "pic-common"
+#define PIC_COMMON(obj) \
+ OBJECT_CHECK(PICCommon, (obj), TYPE_PIC_COMMON)
+#define PIC_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PICCommonClass, (klass), TYPE_PIC_COMMON)
+#define PIC_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PICCommonClass, (obj), TYPE_PIC_COMMON)
+
+typedef struct PICCommonClass
+{
+ ISADeviceClass parent_class;
+ void (*init)(PICCommonState *s);
+ void (*pre_save)(PICCommonState *s);
+ void (*post_load)(PICCommonState *s);
+} PICCommonClass;
+
+struct PICCommonState {
+ ISADevice dev;
+ uint8_t last_irr; /* edge detection */
+ uint8_t irr; /* interrupt request register */
+ uint8_t imr; /* interrupt mask register */
+ uint8_t isr; /* interrupt service register */
+ uint8_t priority_add; /* highest irq priority */
+ uint8_t irq_base;
+ uint8_t read_reg_select;
+ uint8_t poll;
+ uint8_t special_mask;
+ uint8_t init_state;
+ uint8_t auto_eoi;
+ uint8_t rotate_on_auto_eoi;
+ uint8_t special_fully_nested_mode;
+ uint8_t init4; /* true if 4 byte init */
+ uint8_t single_mode; /* true if slave pic is not initialized */
+ uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
+ qemu_irq int_out[1];
+ uint32_t master; /* reflects /SP input pin */
+ uint32_t iobase;
+ uint32_t elcr_addr;
+ MemoryRegion base_io;
+ MemoryRegion elcr_io;
+};
+
+void pic_reset_common(PICCommonState *s);
+
+ISADevice *i8259_init_chip(const char *name, ISABus *bus, bool master);
+
+
+#endif /* !QEMU_I8259_INTERNAL_H */
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0af201de2f..c87a6ca515 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
#include <hw/msi.h>
#include <hw/pc.h>
#include <hw/pci.h>
+#include <hw/sysbus.h>
#include "monitor.h"
#include "dma.h"
@@ -1214,3 +1215,55 @@ void ahci_reset(void *opaque)
ahci_reset_port(&d->ahci, i);
}
}
+
+typedef struct SysbusAHCIState {
+ SysBusDevice busdev;
+ AHCIState ahci;
+ uint32_t num_ports;
+} SysbusAHCIState;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+ .name = "sysbus-ahci",
+ .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+ SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
+ ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+ sysbus_init_mmio(dev, &s->ahci.mem);
+ sysbus_init_irq(dev, &s->ahci.irq);
+
+ qemu_register_reset(ahci_reset, &s->ahci);
+ return 0;
+}
+
+static Property sysbus_ahci_properties[] = {
+ DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ sbc->init = sysbus_ahci_init;
+ dc->vmsd = &vmstate_sysbus_ahci;
+ dc->props = sysbus_ahci_properties;
+}
+
+static TypeInfo sysbus_ahci_info = {
+ .name = "sysbus-ahci",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysbusAHCIState),
+ .class_init = sysbus_ahci_class_init,
+};
+
+static void sysbus_ahci_register(void)
+{
+ type_register_static(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 5fe98b1bb3..a119500f40 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -325,27 +325,34 @@ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
pci_ide_create_devs(dev, hd_table);
}
-static PCIDeviceInfo cmd646_ide_info[] = {
- {
- .qdev.name = "cmd646-ide",
- .qdev.size = sizeof(PCIIDEState),
- .init = pci_cmd646_ide_initfn,
- .exit = pci_cmd646_ide_exitfn,
- .vendor_id = PCI_VENDOR_ID_CMD,
- .device_id = PCI_DEVICE_ID_CMD_646,
- .revision = 0x07, // IDE controller revision
- .class_id = PCI_CLASS_STORAGE_IDE,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
- },{
- /* end of list */
- }
+static Property cmd646_ide_properties[] = {
+ DEFINE_PROP_UINT32("secondary", PCIIDEState, secondary, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void cmd646_ide_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_cmd646_ide_initfn;
+ k->exit = pci_cmd646_ide_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_CMD;
+ k->device_id = PCI_DEVICE_ID_CMD_646;
+ k->revision = 0x07;
+ k->class_id = PCI_CLASS_STORAGE_IDE;
+ dc->props = cmd646_ide_properties;
+}
+
+static TypeInfo cmd646_ide_info = {
+ .name = "cmd646-ide",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .class_init = cmd646_ide_class_init,
};
static void cmd646_ide_register(void)
{
- pci_qdev_register_many(cmd646_ide_info);
+ type_register_static(&cmd646_ide_info);
}
device_init(cmd646_ide_register);
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 3f7510f52e..5cdaa990ea 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -146,26 +146,30 @@ static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr,
msi_write_config(pci, addr, val, len);
}
-static PCIDeviceInfo ich_ahci_info[] = {
- {
- .qdev.name = "ich9-ahci",
- .qdev.alias = "ahci",
- .qdev.size = sizeof(AHCIPCIState),
- .qdev.vmsd = &vmstate_ahci,
- .init = pci_ich9_ahci_init,
- .exit = pci_ich9_uninit,
- .config_write = pci_ich9_write_config,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801IR,
- .revision = 0x02,
- .class_id = PCI_CLASS_STORAGE_SATA,
- },{
- /* end of list */
- }
+static void ich_ahci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_ich9_ahci_init;
+ k->exit = pci_ich9_uninit;
+ k->config_write = pci_ich9_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
+ k->revision = 0x02;
+ k->class_id = PCI_CLASS_STORAGE_SATA;
+ dc->vmsd = &vmstate_ahci;
+}
+
+static TypeInfo ich_ahci_info = {
+ .name = "ich9-ahci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(AHCIPCIState),
+ .class_init = ich_ahci_class_init,
};
static void ich_ahci_register(void)
{
- pci_qdev_register_many(ich_ahci_info);
+ type_register_static(&ich_ahci_info);
}
device_init(ich_ahci_register);
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 00b28dfdbc..c808a0ddf8 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -21,7 +21,6 @@
typedef struct IDEBus IDEBus;
typedef struct IDEDevice IDEDevice;
-typedef struct IDEDeviceInfo IDEDeviceInfo;
typedef struct IDEState IDEState;
typedef struct IDEDMA IDEDMA;
typedef struct IDEDMAOps IDEDMAOps;
@@ -450,6 +449,19 @@ struct IDEBus {
int error_status;
};
+#define TYPE_IDE_DEVICE "ide-device"
+#define IDE_DEVICE(obj) \
+ OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE)
+#define IDE_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE)
+#define IDE_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE)
+
+typedef struct IDEDeviceClass {
+ DeviceClass parent_class;
+ int (*init)(IDEDevice *dev);
+} IDEDeviceClass;
+
struct IDEDevice {
DeviceState qdev;
uint32_t unit;
@@ -458,12 +470,6 @@ struct IDEDevice {
char *serial;
};
-typedef int (*ide_qdev_initfn)(IDEDevice *dev);
-struct IDEDeviceInfo {
- DeviceInfo qdev;
- ide_qdev_initfn init;
-};
-
#define BM_STATUS_DMAING 0x01
#define BM_STATUS_ERROR 0x02
#define BM_STATUS_INT 0x04
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 219f3a4c6b..a0bcb43eba 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -94,23 +94,33 @@ ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
return dev;
}
-static ISADeviceInfo isa_ide_info = {
- .qdev.name = "isa-ide",
- .qdev.fw_name = "ide",
- .qdev.size = sizeof(ISAIDEState),
- .init = isa_ide_initfn,
- .qdev.reset = isa_ide_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", ISAIDEState, iobase, 0x1f0),
- DEFINE_PROP_HEX32("iobase2", ISAIDEState, iobase2, 0x3f6),
- DEFINE_PROP_UINT32("irq", ISAIDEState, isairq, 14),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property isa_ide_properties[] = {
+ DEFINE_PROP_HEX32("iobase", ISAIDEState, iobase, 0x1f0),
+ DEFINE_PROP_HEX32("iobase2", ISAIDEState, iobase2, 0x3f6),
+ DEFINE_PROP_UINT32("irq", ISAIDEState, isairq, 14),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void isa_ide_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = isa_ide_initfn;
+ dc->fw_name = "ide";
+ dc->reset = isa_ide_reset;
+ dc->props = isa_ide_properties;
+}
+
+static TypeInfo isa_ide_info = {
+ .name = "isa-ide",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISAIDEState),
+ .class_init = isa_ide_class_initfn,
};
static void isa_ide_register_devices(void)
{
- isa_qdev_register(&isa_ide_info);
+ type_register_static(&isa_ide_info);
}
device_init(isa_ide_register_devices)
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index cb3de6537b..246dd5704b 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -327,7 +327,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
bm->cmd = val & 0x09;
}
-static uint64_t bmdma_addr_read(void *opaque, dma_addr_t addr,
+static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr,
unsigned width)
{
BMDMAState *bm = opaque;
@@ -341,7 +341,7 @@ static uint64_t bmdma_addr_read(void *opaque, dma_addr_t addr,
return data;
}
-static void bmdma_addr_write(void *opaque, dma_addr_t addr,
+static void bmdma_addr_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned width)
{
BMDMAState *bm = opaque;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 34733454ea..bf4465bb49 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -195,7 +195,6 @@ PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
PCIDevice *dev;
dev = pci_create_simple(bus, devfn, "piix3-ide-xen");
- dev->qdev.info->unplug = pci_piix3_xen_ide_unplug;
pci_ide_create_devs(dev, hd_table);
return dev;
}
@@ -238,42 +237,72 @@ PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
return dev;
}
-static PCIDeviceInfo piix_ide_info[] = {
- {
- .qdev.name = "piix3-ide",
- .qdev.size = sizeof(PCIIDEState),
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = pci_piix_ide_initfn,
- .exit = pci_piix_ide_exitfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371SB_1,
- .class_id = PCI_CLASS_STORAGE_IDE,
- },{
- .qdev.name = "piix3-ide-xen",
- .qdev.size = sizeof(PCIIDEState),
- .qdev.no_user = 1,
- .init = pci_piix_ide_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371SB_1,
- .class_id = PCI_CLASS_STORAGE_IDE,
- },{
- .qdev.name = "piix4-ide",
- .qdev.size = sizeof(PCIIDEState),
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = pci_piix_ide_initfn,
- .exit = pci_piix_ide_exitfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371AB,
- .class_id = PCI_CLASS_STORAGE_IDE,
- },{
- /* end of list */
- }
+static void piix3_ide_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = pci_piix_ide_initfn;
+ k->exit = pci_piix_ide_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
+ k->class_id = PCI_CLASS_STORAGE_IDE;
+ dc->no_user = 1;
+}
+
+static TypeInfo piix3_ide_info = {
+ .name = "piix3-ide",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .class_init = piix3_ide_class_init,
+};
+
+static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_piix_ide_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
+ k->class_id = PCI_CLASS_STORAGE_IDE;
+ dc->no_user = 1;
+ dc->unplug = pci_piix3_xen_ide_unplug;
+}
+
+static TypeInfo piix3_ide_xen_info = {
+ .name = "piix3-ide-xen",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .class_init = piix3_ide_xen_class_init,
+};
+
+static void piix4_ide_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = pci_piix_ide_initfn;
+ k->exit = pci_piix_ide_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
+ k->class_id = PCI_CLASS_STORAGE_IDE;
+ dc->no_user = 1;
+}
+
+static TypeInfo piix4_ide_info = {
+ .name = "piix4-ide",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .class_init = piix4_ide_class_init,
};
static void piix_ide_register(void)
{
- pci_qdev_register_many(piix_ide_info);
+ type_register_static(&piix3_ide_info);
+ type_register_static(&piix3_ide_xen_info);
+ type_register_static(&piix4_ide_info);
}
device_init(piix_ide_register);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 42071277bb..1640616906 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -53,10 +53,10 @@ static char *idebus_get_fw_dev_path(DeviceState *dev)
return strdup(path);
}
-static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int ide_qdev_init(DeviceState *qdev)
{
- IDEDevice *dev = DO_UPCAST(IDEDevice, qdev, qdev);
- IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base);
+ IDEDevice *dev = IDE_DEVICE(qdev);
+ IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
if (!dev->conf.bs) {
@@ -85,19 +85,12 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
error_report("Invalid IDE unit %d", dev->unit);
goto err;
}
- return info->init(dev);
+ return dc->init(dev);
err:
return -1;
}
-static void ide_qdev_register(IDEDeviceInfo *info)
-{
- info->qdev.init = ide_qdev_init;
- info->qdev.bus_info = &ide_bus_info;
- qdev_register(&info->qdev);
-}
-
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
{
DeviceState *dev;
@@ -182,46 +175,93 @@ static int ide_drive_initfn(IDEDevice *dev)
DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial)
-static IDEDeviceInfo ide_dev_info[] = {
- {
- .qdev.name = "ide-hd",
- .qdev.fw_name = "drive",
- .qdev.desc = "virtual IDE disk",
- .qdev.size = sizeof(IDEDrive),
- .init = ide_hd_initfn,
- .qdev.props = (Property[]) {
- DEFINE_IDE_DEV_PROPERTIES(),
- DEFINE_PROP_END_OF_LIST(),
- }
- },{
- .qdev.name = "ide-cd",
- .qdev.fw_name = "drive",
- .qdev.desc = "virtual IDE CD-ROM",
- .qdev.size = sizeof(IDEDrive),
- .init = ide_cd_initfn,
- .qdev.props = (Property[]) {
- DEFINE_IDE_DEV_PROPERTIES(),
- DEFINE_PROP_END_OF_LIST(),
- }
- },{
- .qdev.name = "ide-drive", /* legacy -device ide-drive */
- .qdev.fw_name = "drive",
- .qdev.desc = "virtual IDE disk or CD-ROM (legacy)",
- .qdev.size = sizeof(IDEDrive),
- .init = ide_drive_initfn,
- .qdev.props = (Property[]) {
- DEFINE_IDE_DEV_PROPERTIES(),
- DEFINE_PROP_END_OF_LIST(),
- }
- }
+static Property ide_hd_properties[] = {
+ DEFINE_IDE_DEV_PROPERTIES(),
+ DEFINE_PROP_END_OF_LIST(),
};
-static void ide_dev_register(void)
+static void ide_hd_class_init(ObjectClass *klass, void *data)
{
- int i;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
+ k->init = ide_hd_initfn;
+ dc->fw_name = "drive";
+ dc->desc = "virtual IDE disk";
+ dc->props = ide_hd_properties;
+}
- for (i = 0; i < ARRAY_SIZE(ide_dev_info); i++) {
- ide_qdev_register(&ide_dev_info[i]);
- }
+static TypeInfo ide_hd_info = {
+ .name = "ide-hd",
+ .parent = TYPE_IDE_DEVICE,
+ .instance_size = sizeof(IDEDrive),
+ .class_init = ide_hd_class_init,
+};
+
+static Property ide_cd_properties[] = {
+ DEFINE_IDE_DEV_PROPERTIES(),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ide_cd_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
+ k->init = ide_cd_initfn;
+ dc->fw_name = "drive";
+ dc->desc = "virtual IDE CD-ROM";
+ dc->props = ide_cd_properties;
+}
+
+static TypeInfo ide_cd_info = {
+ .name = "ide-cd",
+ .parent = TYPE_IDE_DEVICE,
+ .instance_size = sizeof(IDEDrive),
+ .class_init = ide_cd_class_init,
+};
+
+static Property ide_drive_properties[] = {
+ DEFINE_IDE_DEV_PROPERTIES(),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ide_drive_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ IDEDeviceClass *k = IDE_DEVICE_CLASS(klass);
+ k->init = ide_drive_initfn;
+ dc->fw_name = "drive";
+ dc->desc = "virtual IDE disk or CD-ROM (legacy)";
+ dc->props = ide_drive_properties;
+}
+
+static TypeInfo ide_drive_info = {
+ .name = "ide-drive",
+ .parent = TYPE_IDE_DEVICE,
+ .instance_size = sizeof(IDEDrive),
+ .class_init = ide_drive_class_init,
+};
+
+static void ide_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = ide_qdev_init;
+ k->bus_info = &ide_bus_info;
+}
+
+static TypeInfo ide_device_type_info = {
+ .name = TYPE_IDE_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(IDEDevice),
+ .abstract = true,
+ .class_size = sizeof(IDEDeviceClass),
+ .class_init = ide_device_class_init,
+};
+
+static void ide_dev_register(void)
+{
+ type_register_static(&ide_hd_info);
+ type_register_static(&ide_cd_info);
+ type_register_static(&ide_drive_info);
+ type_register_static(&ide_device_type_info);
}
device_init(ide_dev_register);
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 4ea2064498..b4ca6f27b3 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -213,20 +213,29 @@ void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
pci_ide_create_devs(dev, hd_table);
}
-static PCIDeviceInfo via_ide_info = {
- .qdev.name = "via-ide",
- .qdev.size = sizeof(PCIIDEState),
- .qdev.no_user = 1,
- .init = vt82c686b_ide_initfn,
- .exit = vt82c686b_ide_exitfn,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_IDE,
- .revision = 0x06,
- .class_id = PCI_CLASS_STORAGE_IDE,
+static void via_ide_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = vt82c686b_ide_initfn;
+ k->exit = vt82c686b_ide_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_IDE;
+ k->revision = 0x06;
+ k->class_id = PCI_CLASS_STORAGE_IDE;
+ dc->no_user = 1;
+}
+
+static TypeInfo via_ide_info = {
+ .name = "via-ide",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .class_init = via_ide_class_init,
};
static void via_ide_register(void)
{
- pci_qdev_register(&via_ide_info);
+ type_register_static(&via_ide_info);
}
device_init(via_ide_register);
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index e5712fc3e7..6dbd649908 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -518,20 +518,45 @@ 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[]) {
- DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property core_properties[] = {
+ DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void core_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = integratorcm_init;
+ dc->props = core_properties;
+}
+
+static TypeInfo core_info = {
+ .name = "integrator_core",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(integratorcm_state),
+ .class_init = core_class_init,
+};
+
+static void icp_pic_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = icp_pic_init;
+}
+
+static TypeInfo icp_pic_info = {
+ .name = "integrator_pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(icp_pic_state),
+ .class_init = icp_pic_class_init,
};
static void integratorcp_register_devices(void)
{
- sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
- sysbus_register_withprop(&core_info);
+ type_register_static(&icp_pic_info);
+ type_register_static(&core_info);
}
device_init(integratorcp_register_devices)
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 10769e0f49..83c42d58b6 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -47,13 +47,12 @@ void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus,
bus->xfer = xfer;
}
-static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base)
+static int hda_codec_dev_init(DeviceState *qdev)
{
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, qdev->parent_bus);
HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
- HDACodecDeviceInfo *info = DO_UPCAST(HDACodecDeviceInfo, qdev, base);
+ HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
- dev->info = info;
if (dev->cad == -1) {
dev->cad = bus->next_cad;
}
@@ -61,27 +60,20 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base)
return -1;
}
bus->next_cad = dev->cad + 1;
- return info->init(dev);
+ return cdc->init(dev);
}
static int hda_codec_dev_exit(DeviceState *qdev)
{
HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
+ HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
- if (dev->info->exit) {
- dev->info->exit(dev);
+ if (cdc->exit) {
+ cdc->exit(dev);
}
return 0;
}
-void hda_codec_register(HDACodecDeviceInfo *info)
-{
- info->qdev.init = hda_codec_dev_init;
- info->qdev.exit = hda_codec_dev_exit;
- info->qdev.bus_info = &hda_codec_bus_info;
- qdev_register(&info->qdev);
-}
-
HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
{
DeviceState *qdev;
@@ -283,6 +275,7 @@ static int intel_hda_send_command(IntelHDAState *d, uint32_t verb)
{
uint32_t cad, nid, data;
HDACodecDevice *codec;
+ HDACodecDeviceClass *cdc;
cad = (verb >> 28) & 0x0f;
if (verb & (1 << 27)) {
@@ -298,7 +291,8 @@ static int intel_hda_send_command(IntelHDAState *d, uint32_t verb)
dprint(d, 1, "%s: addressed non-existing codec\n", __FUNCTION__);
return -1;
}
- codec->info->command(codec, nid, data);
+ cdc = HDA_CODEC_DEVICE_GET_CLASS(codec);
+ cdc->command(codec, nid, data);
return 0;
}
@@ -491,9 +485,12 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
HDACodecDevice *cdev;
QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+ HDACodecDeviceClass *cdc;
+
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
- if (cdev->info->stream) {
- cdev->info->stream(cdev, stream, running, output);
+ cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev);
+ if (cdc->stream) {
+ cdc->stream(cdev, stream, running, output);
}
}
}
@@ -1116,9 +1113,7 @@ static void intel_hda_reset(DeviceState *dev)
/* reset codecs */
QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
- if (qdev->info->reset) {
- qdev->info->reset(qdev);
- }
+ device_reset(DEVICE(cdev));
d->state_sts |= (1 << cdev->cad);
}
intel_hda_update_irq(d);
@@ -1129,7 +1124,7 @@ static int intel_hda_init(PCIDevice *pci)
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
uint8_t *conf = d->pci.config;
- d->name = d->pci.qdev.info->name;
+ d->name = object_get_typename(OBJECT(d));
pci_config_set_interrupt_pin(conf, 1);
@@ -1244,29 +1239,58 @@ static const VMStateDescription vmstate_intel_hda = {
}
};
-static PCIDeviceInfo intel_hda_info = {
- .qdev.name = "intel-hda",
- .qdev.desc = "Intel HD Audio Controller",
- .qdev.size = sizeof(IntelHDAState),
- .qdev.vmsd = &vmstate_intel_hda,
- .qdev.reset = intel_hda_reset,
- .init = intel_hda_init,
- .exit = intel_hda_exit,
- .config_write = intel_hda_write_config,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = 0x2668,
- .revision = 1,
- .class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
- DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property intel_hda_properties[] = {
+ DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
+ DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void intel_hda_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = intel_hda_init;
+ k->exit = intel_hda_exit;
+ k->config_write = intel_hda_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = 0x2668;
+ k->revision = 1;
+ k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
+ dc->desc = "Intel HD Audio Controller";
+ dc->reset = intel_hda_reset;
+ dc->vmsd = &vmstate_intel_hda;
+ dc->props = intel_hda_properties;
+}
+
+static TypeInfo intel_hda_info = {
+ .name = "intel-hda",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(IntelHDAState),
+ .class_init = intel_hda_class_init,
+};
+
+static void hda_codec_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = hda_codec_dev_init;
+ k->exit = hda_codec_dev_exit;
+ k->bus_info = &hda_codec_bus_info;
+}
+
+static TypeInfo hda_codec_device_type_info = {
+ .name = TYPE_HDA_CODEC_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(HDACodecDevice),
+ .abstract = true,
+ .class_size = sizeof(HDACodecDeviceClass),
+ .class_init = hda_codec_device_class_init,
};
static void intel_hda_register(void)
{
- pci_qdev_register(&intel_hda_info);
+ type_register_static(&intel_hda_info);
+ type_register_static(&hda_codec_device_type_info);
}
device_init(intel_hda_register);
diff --git a/hw/intel-hda.h b/hw/intel-hda.h
index 65fd2a85bb..a1cca5b1bb 100644
--- a/hw/intel-hda.h
+++ b/hw/intel-hda.h
@@ -6,9 +6,16 @@
/* --------------------------------------------------------------------- */
/* hda bus */
+#define TYPE_HDA_CODEC_DEVICE "hda-codec"
+#define HDA_CODEC_DEVICE(obj) \
+ OBJECT_CHECK(HDACodecDevice, (obj), TYPE_HDA_CODEC_DEVICE)
+#define HDA_CODEC_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(HDACodecDeviceClass, (klass), TYPE_HDA_CODEC_DEVICE)
+#define HDA_CODEC_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE)
+
typedef struct HDACodecBus HDACodecBus;
typedef struct HDACodecDevice HDACodecDevice;
-typedef struct HDACodecDeviceInfo HDACodecDeviceInfo;
typedef void (*hda_codec_response_func)(HDACodecDevice *dev,
bool solicited, uint32_t response);
@@ -23,24 +30,24 @@ struct HDACodecBus {
hda_codec_xfer_func xfer;
};
-struct HDACodecDevice {
- DeviceState qdev;
- HDACodecDeviceInfo *info;
- uint32_t cad; /* codec address */
-};
+typedef struct HDACodecDeviceClass
+{
+ DeviceClass parent_class;
-struct HDACodecDeviceInfo {
- DeviceInfo qdev;
int (*init)(HDACodecDevice *dev);
int (*exit)(HDACodecDevice *dev);
void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);
+} HDACodecDeviceClass;
+
+struct HDACodecDevice {
+ DeviceState qdev;
+ uint32_t cad; /* codec address */
};
void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus,
hda_codec_response_func response,
hda_codec_xfer_func xfer);
-void hda_codec_register(HDACodecDeviceInfo *info);
HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad);
void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response);
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 27b07c6317..79549f8ed1 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -24,9 +24,7 @@
#include "pc.h"
#include "apic.h"
#include "ioapic.h"
-#include "qemu-timer.h"
-#include "host-utils.h"
-#include "sysbus.h"
+#include "ioapic_internal.h"
//#define DEBUG_IOAPIC
@@ -37,65 +35,9 @@
#define DPRINTF(fmt, ...)
#endif
-#define MAX_IOAPICS 1
+static IOAPICCommonState *ioapics[MAX_IOAPICS];
-#define IOAPIC_VERSION 0x11
-
-#define IOAPIC_LVT_DEST_SHIFT 56
-#define IOAPIC_LVT_MASKED_SHIFT 16
-#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
-#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
-#define IOAPIC_LVT_POLARITY_SHIFT 13
-#define IOAPIC_LVT_DELIV_STATUS_SHIFT 12
-#define IOAPIC_LVT_DEST_MODE_SHIFT 11
-#define IOAPIC_LVT_DELIV_MODE_SHIFT 8
-
-#define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT)
-#define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
-
-#define IOAPIC_TRIGGER_EDGE 0
-#define IOAPIC_TRIGGER_LEVEL 1
-
-/*io{apic,sapic} delivery mode*/
-#define IOAPIC_DM_FIXED 0x0
-#define IOAPIC_DM_LOWEST_PRIORITY 0x1
-#define IOAPIC_DM_PMI 0x2
-#define IOAPIC_DM_NMI 0x4
-#define IOAPIC_DM_INIT 0x5
-#define IOAPIC_DM_SIPI 0x6
-#define IOAPIC_DM_EXTINT 0x7
-#define IOAPIC_DM_MASK 0x7
-
-#define IOAPIC_VECTOR_MASK 0xff
-
-#define IOAPIC_IOREGSEL 0x00
-#define IOAPIC_IOWIN 0x10
-
-#define IOAPIC_REG_ID 0x00
-#define IOAPIC_REG_VER 0x01
-#define IOAPIC_REG_ARB 0x02
-#define IOAPIC_REG_REDTBL_BASE 0x10
-#define IOAPIC_ID 0x00
-
-#define IOAPIC_ID_SHIFT 24
-#define IOAPIC_ID_MASK 0xf
-
-#define IOAPIC_VER_ENTRIES_SHIFT 16
-
-typedef struct IOAPICState IOAPICState;
-
-struct IOAPICState {
- SysBusDevice busdev;
- MemoryRegion io_memory;
- uint8_t id;
- uint8_t ioregsel;
- uint32_t irr;
- uint64_t ioredtbl[IOAPIC_NUM_PINS];
-};
-
-static IOAPICState *ioapics[MAX_IOAPICS];
-
-static void ioapic_service(IOAPICState *s)
+static void ioapic_service(IOAPICCommonState *s)
{
uint8_t i;
uint8_t trig_mode;
@@ -135,7 +77,7 @@ static void ioapic_service(IOAPICState *s)
static void ioapic_set_irq(void *opaque, int vector, int level)
{
- IOAPICState *s = opaque;
+ IOAPICCommonState *s = opaque;
/* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
* to GSI 2. GSI maps to ioapic 1-1. This is not
@@ -174,7 +116,7 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
void ioapic_eoi_broadcast(int vector)
{
- IOAPICState *s;
+ IOAPICCommonState *s;
uint64_t entry;
int i, n;
@@ -199,7 +141,7 @@ void ioapic_eoi_broadcast(int vector)
static uint64_t
ioapic_mem_read(void *opaque, target_phys_addr_t addr, unsigned int size)
{
- IOAPICState *s = opaque;
+ IOAPICCommonState *s = opaque;
int index;
uint32_t val = 0;
@@ -242,7 +184,7 @@ static void
ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
unsigned int size)
{
- IOAPICState *s = opaque;
+ IOAPICCommonState *s = opaque;
int index;
switch (addr & 0xff) {
@@ -278,83 +220,40 @@ ioapic_mem_write(void *opaque, target_phys_addr_t addr, uint64_t val,
}
}
-static int ioapic_post_load(void *opaque, int version_id)
-{
- IOAPICState *s = opaque;
-
- if (version_id == 1) {
- /* set sane value */
- s->irr = 0;
- }
- return 0;
-}
-
-static const VMStateDescription vmstate_ioapic = {
- .name = "ioapic",
- .version_id = 3,
- .post_load = ioapic_post_load,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(id, IOAPICState),
- VMSTATE_UINT8(ioregsel, IOAPICState),
- VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
- VMSTATE_UINT32_V(irr, IOAPICState, 2),
- VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void ioapic_reset(DeviceState *d)
-{
- IOAPICState *s = DO_UPCAST(IOAPICState, busdev.qdev, d);
- int i;
-
- s->id = 0;
- s->ioregsel = 0;
- s->irr = 0;
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
- }
-}
-
static const MemoryRegionOps ioapic_io_ops = {
.read = ioapic_mem_read,
.write = ioapic_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int ioapic_init1(SysBusDevice *dev)
+static void ioapic_init(IOAPICCommonState *s, int instance_no)
{
- IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
- static int ioapic_no;
-
- if (ioapic_no >= MAX_IOAPICS) {
- return -1;
- }
-
memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
- sysbus_init_mmio(dev, &s->io_memory);
- qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
+ qdev_init_gpio_in(&s->busdev.qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
+
+ ioapics[instance_no] = s;
+}
- ioapics[ioapic_no++] = s;
+static void ioapic_class_init(ObjectClass *klass, void *data)
+{
+ IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- return 0;
+ k->init = ioapic_init;
+ dc->reset = ioapic_reset_common;
}
-static SysBusDeviceInfo ioapic_info = {
- .init = ioapic_init1,
- .qdev.name = "ioapic",
- .qdev.size = sizeof(IOAPICState),
- .qdev.vmsd = &vmstate_ioapic,
- .qdev.reset = ioapic_reset,
- .qdev.no_user = 1,
+static TypeInfo ioapic_info = {
+ .name = "ioapic",
+ .parent = TYPE_IOAPIC_COMMON,
+ .instance_size = sizeof(IOAPICCommonState),
+ .class_init = ioapic_class_init,
};
static void ioapic_register_devices(void)
{
- sysbus_register_withprop(&ioapic_info);
+ type_register_static(&ioapic_info);
}
device_init(ioapic_register_devices)
diff --git a/hw/ioapic_common.c b/hw/ioapic_common.c
new file mode 100644
index 0000000000..f932700d12
--- /dev/null
+++ b/hw/ioapic_common.c
@@ -0,0 +1,121 @@
+/*
+ * IOAPIC emulation logic - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * Copyright (c) 2009 Xiantao Zhang, Intel
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ioapic.h"
+#include "ioapic_internal.h"
+#include "sysbus.h"
+
+void ioapic_reset_common(DeviceState *dev)
+{
+ IOAPICCommonState *s = IOAPIC_COMMON(dev);
+ int i;
+
+ s->id = 0;
+ s->ioregsel = 0;
+ s->irr = 0;
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
+ }
+}
+
+static void ioapic_dispatch_pre_save(void *opaque)
+{
+ IOAPICCommonState *s = IOAPIC_COMMON(opaque);
+ IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s);
+
+ if (info->pre_save) {
+ info->pre_save(s);
+ }
+}
+
+static int ioapic_dispatch_post_load(void *opaque, int version_id)
+{
+ IOAPICCommonState *s = IOAPIC_COMMON(opaque);
+ IOAPICCommonClass *info = IOAPIC_COMMON_GET_CLASS(s);
+
+ if (info->post_load) {
+ info->post_load(s);
+ }
+ return 0;
+}
+
+static int ioapic_init_common(SysBusDevice *dev)
+{
+ IOAPICCommonState *s = FROM_SYSBUS(IOAPICCommonState, dev);
+ IOAPICCommonClass *info;
+ static int ioapic_no;
+
+ if (ioapic_no >= MAX_IOAPICS) {
+ return -1;
+ }
+
+ info = IOAPIC_COMMON_GET_CLASS(s);
+ info->init(s, ioapic_no);
+
+ sysbus_init_mmio(&s->busdev, &s->io_memory);
+ ioapic_no++;
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_ioapic_common = {
+ .name = "ioapic",
+ .version_id = 3,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_save = ioapic_dispatch_pre_save,
+ .post_load = ioapic_dispatch_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(id, IOAPICCommonState),
+ VMSTATE_UINT8(ioregsel, IOAPICCommonState),
+ VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
+ VMSTATE_UINT32_V(irr, IOAPICCommonState, 2),
+ VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICCommonState, IOAPIC_NUM_PINS),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void ioapic_common_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ sc->init = ioapic_init_common;
+ dc->vmsd = &vmstate_ioapic_common;
+ dc->no_user = 1;
+}
+
+static TypeInfo ioapic_common_type = {
+ .name = TYPE_IOAPIC_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IOAPICCommonState),
+ .class_size = sizeof(IOAPICCommonClass),
+ .class_init = ioapic_common_class_init,
+ .abstract = true,
+};
+
+static void register_devices(void)
+{
+ type_register_static(&ioapic_common_type);
+}
+
+device_init(register_devices);
+
diff --git a/hw/ioapic_internal.h b/hw/ioapic_internal.h
new file mode 100644
index 0000000000..e04c9f3c12
--- /dev/null
+++ b/hw/ioapic_internal.h
@@ -0,0 +1,102 @@
+/*
+ * IOAPIC emulation logic - internal interfaces
+ *
+ * Copyright (c) 2004-2005 Fabrice Bellard
+ * Copyright (c) 2009 Xiantao Zhang, Intel
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_IOAPIC_INTERNAL_H
+#define QEMU_IOAPIC_INTERNAL_H
+
+#include "hw.h"
+#include "memory.h"
+#include "sysbus.h"
+
+#define MAX_IOAPICS 1
+
+#define IOAPIC_VERSION 0x11
+
+#define IOAPIC_LVT_DEST_SHIFT 56
+#define IOAPIC_LVT_MASKED_SHIFT 16
+#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
+#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
+#define IOAPIC_LVT_POLARITY_SHIFT 13
+#define IOAPIC_LVT_DELIV_STATUS_SHIFT 12
+#define IOAPIC_LVT_DEST_MODE_SHIFT 11
+#define IOAPIC_LVT_DELIV_MODE_SHIFT 8
+
+#define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT)
+#define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
+
+#define IOAPIC_TRIGGER_EDGE 0
+#define IOAPIC_TRIGGER_LEVEL 1
+
+/*io{apic,sapic} delivery mode*/
+#define IOAPIC_DM_FIXED 0x0
+#define IOAPIC_DM_LOWEST_PRIORITY 0x1
+#define IOAPIC_DM_PMI 0x2
+#define IOAPIC_DM_NMI 0x4
+#define IOAPIC_DM_INIT 0x5
+#define IOAPIC_DM_SIPI 0x6
+#define IOAPIC_DM_EXTINT 0x7
+#define IOAPIC_DM_MASK 0x7
+
+#define IOAPIC_VECTOR_MASK 0xff
+
+#define IOAPIC_IOREGSEL 0x00
+#define IOAPIC_IOWIN 0x10
+
+#define IOAPIC_REG_ID 0x00
+#define IOAPIC_REG_VER 0x01
+#define IOAPIC_REG_ARB 0x02
+#define IOAPIC_REG_REDTBL_BASE 0x10
+#define IOAPIC_ID 0x00
+
+#define IOAPIC_ID_SHIFT 24
+#define IOAPIC_ID_MASK 0xf
+
+#define IOAPIC_VER_ENTRIES_SHIFT 16
+
+typedef struct IOAPICCommonState IOAPICCommonState;
+
+#define TYPE_IOAPIC_COMMON "ioapic-common"
+#define IOAPIC_COMMON(obj) \
+ OBJECT_CHECK(IOAPICCommonState, (obj), TYPE_IOAPIC_COMMON)
+#define IOAPIC_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(IOAPICCommonClass, (klass), TYPE_IOAPIC_COMMON)
+#define IOAPIC_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(IOAPICCommonClass, (obj), TYPE_IOAPIC_COMMON)
+
+typedef struct IOAPICCommonClass {
+ SysBusDeviceClass parent_class;
+ void (*init)(IOAPICCommonState *s, int instance_no);
+ void (*pre_save)(IOAPICCommonState *s);
+ void (*post_load)(IOAPICCommonState *s);
+} IOAPICCommonClass;
+
+struct IOAPICCommonState {
+ SysBusDevice busdev;
+ MemoryRegion io_memory;
+ uint8_t id;
+ uint8_t ioregsel;
+ uint32_t irr;
+ uint64_t ioredtbl[IOAPIC_NUM_PINS];
+};
+
+void ioapic_reset_common(DeviceState *dev);
+
+#endif /* !QEMU_IOAPIC_INTERNAL_H */
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index a6bfbb9173..1c60123d43 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -80,7 +80,7 @@ static void ioh3420_write_config(PCIDevice *d,
static void ioh3420_reset(DeviceState *qdev)
{
- PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *d = PCI_DEVICE(qdev);
msi_reset(d);
ioh3420_aer_vector_update(d);
pcie_cap_root_reset(d);
@@ -201,36 +201,45 @@ static const VMStateDescription vmstate_ioh3420 = {
}
};
-static PCIDeviceInfo ioh3420_info = {
- .qdev.name = "ioh3420",
- .qdev.desc = "Intel IOH device id 3420 PCIE Root Port",
- .qdev.size = sizeof(PCIESlot),
- .qdev.reset = ioh3420_reset,
- .qdev.vmsd = &vmstate_ioh3420,
-
- .is_express = 1,
- .is_bridge = 1,
- .config_write = ioh3420_write_config,
- .init = ioh3420_initfn,
- .exit = ioh3420_exitfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_IOH_EPORT,
- .revision = PCI_DEVICE_ID_IOH_REV,
-
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
- DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
- DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
- port.br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ioh3420_properties[] = {
+ DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+ DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+ DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+ DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+ port.br.dev.exp.aer_log.log_max,
+ PCIE_AER_LOG_MAX_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ioh3420_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->is_express = 1;
+ k->is_bridge = 1;
+ k->config_write = ioh3420_write_config;
+ k->init = ioh3420_initfn;
+ k->exit = ioh3420_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_IOH_EPORT;
+ k->revision = PCI_DEVICE_ID_IOH_REV;
+ dc->desc = "Intel IOH device id 3420 PCIE Root Port";
+ dc->reset = ioh3420_reset;
+ dc->vmsd = &vmstate_ioh3420;
+ dc->props = ioh3420_properties;
+}
+
+static TypeInfo ioh3420_info = {
+ .name = "ioh3420",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIESlot),
+ .class_init = ioh3420_class_init,
};
static void ioh3420_register(void)
{
- pci_qdev_register(&ioh3420_info);
+ type_register_static(&ioh3420_info);
}
device_init(ioh3420_register);
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 5af790bf81..d03f82824c 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -110,22 +110,19 @@ void isa_register_portio_list(ISADevice *dev, uint16_t start,
portio_list_add(piolist, isabus->address_space_io, start);
}
-static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int isa_qdev_init(DeviceState *qdev)
{
- ISADevice *dev = DO_UPCAST(ISADevice, qdev, qdev);
- ISADeviceInfo *info = DO_UPCAST(ISADeviceInfo, qdev, base);
+ ISADevice *dev = ISA_DEVICE(qdev);
+ ISADeviceClass *klass = ISA_DEVICE_GET_CLASS(dev);
dev->isairq[0] = -1;
dev->isairq[1] = -1;
- return info->init(dev);
-}
+ if (klass->init) {
+ return klass->init(dev);
+ }
-void isa_qdev_register(ISADeviceInfo *info)
-{
- info->qdev.init = isa_qdev_init;
- info->qdev.bus_info = &isa_bus_info;
- qdev_register(&info->qdev);
+ return 0;
}
ISADevice *isa_create(ISABus *bus, const char *name)
@@ -137,7 +134,7 @@ ISADevice *isa_create(ISABus *bus, const char *name)
name);
}
dev = qdev_create(&bus->qbus, name);
- return DO_UPCAST(ISADevice, qdev, dev);
+ return ISA_DEVICE(dev);
}
ISADevice *isa_try_create(ISABus *bus, const char *name)
@@ -149,7 +146,7 @@ ISADevice *isa_try_create(ISABus *bus, const char *name)
name);
}
dev = qdev_try_create(&bus->qbus, name);
- return DO_UPCAST(ISADevice, qdev, dev);
+ return ISA_DEVICE(dev);
}
ISADevice *isa_create_simple(ISABus *bus, const char *name)
@@ -163,7 +160,7 @@ ISADevice *isa_create_simple(ISABus *bus, const char *name)
static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
- ISADevice *d = DO_UPCAST(ISADevice, qdev, dev);
+ ISADevice *d = ISA_DEVICE(dev);
if (d->isairq[1] != -1) {
monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
@@ -180,17 +177,43 @@ static int isabus_bridge_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo isabus_bridge_info = {
- .init = isabus_bridge_init,
- .qdev.name = "isabus-bridge",
- .qdev.fw_name = "isa",
- .qdev.size = sizeof(SysBusDevice),
- .qdev.no_user = 1,
+static void isabus_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = isabus_bridge_init;
+ dc->fw_name = "isa";
+ dc->no_user = 1;
+}
+
+static TypeInfo isabus_bridge_info = {
+ .name = "isabus-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = isabus_bridge_class_init,
+};
+
+static void isa_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = isa_qdev_init;
+ k->bus_info = &isa_bus_info;
+}
+
+static TypeInfo isa_device_type_info = {
+ .name = TYPE_ISA_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(ISADevice),
+ .abstract = true,
+ .class_size = sizeof(ISADeviceClass),
+ .class_init = isa_device_class_init,
};
static void isabus_register_devices(void)
{
- sysbus_register_withprop(&isabus_bridge_info);
+ type_register_static(&isabus_bridge_info);
+ type_register_static(&isa_device_type_info);
}
static char *isabus_get_fw_dev_path(DeviceState *dev)
diff --git a/hw/isa.h b/hw/isa.h
index b11a0be27f..40373fb107 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -10,7 +10,19 @@
#define ISA_NUM_IRQS 16
typedef struct ISADevice ISADevice;
-typedef struct ISADeviceInfo ISADeviceInfo;
+
+#define TYPE_ISA_DEVICE "isa-device"
+#define ISA_DEVICE(obj) \
+ OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE)
+#define ISA_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE)
+#define ISA_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
+
+typedef struct ISADeviceClass {
+ DeviceClass parent_class;
+ int (*init)(ISADevice *dev);
+} ISADeviceClass;
struct ISABus {
BusState qbus;
@@ -25,17 +37,10 @@ struct ISADevice {
int ioport_id;
};
-typedef int (*isa_qdev_initfn)(ISADevice *dev);
-struct ISADeviceInfo {
- DeviceInfo qdev;
- isa_qdev_initfn init;
-};
-
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io);
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, int isairq);
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
-void isa_qdev_register(ISADeviceInfo *info);
MemoryRegion *isa_address_space(ISADevice *dev);
ISADevice *isa_create(ISABus *bus, const char *name);
ISADevice *isa_try_create(ISABus *bus, const char *name);
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index bec2e0b8fe..6f017d474c 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -766,30 +766,41 @@ static int pci_ivshmem_uninit(PCIDevice *dev)
return 0;
}
-static PCIDeviceInfo ivshmem_info = {
- .qdev.name = "ivshmem",
- .qdev.size = sizeof(IVShmemState),
- .qdev.reset = ivshmem_reset,
- .init = pci_ivshmem_init,
- .exit = pci_ivshmem_uninit,
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = 0x1110,
- .class_id = PCI_CLASS_MEMORY_RAM,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
- DEFINE_PROP_STRING("size", IVShmemState, sizearg),
- DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1),
- DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, false),
- DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true),
- DEFINE_PROP_STRING("shm", IVShmemState, shmobj),
- DEFINE_PROP_STRING("role", IVShmemState, role),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ivshmem_properties[] = {
+ DEFINE_PROP_CHR("chardev", IVShmemState, server_chr),
+ DEFINE_PROP_STRING("size", IVShmemState, sizearg),
+ DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1),
+ DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, false),
+ DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true),
+ DEFINE_PROP_STRING("shm", IVShmemState, shmobj),
+ DEFINE_PROP_STRING("role", IVShmemState, role),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ivshmem_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_ivshmem_init;
+ k->exit = pci_ivshmem_uninit;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = 0x1110;
+ k->class_id = PCI_CLASS_MEMORY_RAM;
+ dc->reset = ivshmem_reset;
+ dc->props = ivshmem_properties;
+}
+
+static TypeInfo ivshmem_info = {
+ .name = "ivshmem",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(IVShmemState),
+ .class_init = ivshmem_class_init,
};
static void ivshmem_register_devices(void)
{
- pci_qdev_register(&ivshmem_info);
+ type_register_static(&ivshmem_info);
}
device_init(ivshmem_register_devices)
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
new file mode 100644
index 0000000000..dfc2ab3b03
--- /dev/null
+++ b/hw/kvm/apic.c
@@ -0,0 +1,147 @@
+/*
+ * KVM in-kernel APIC support
+ *
+ * Copyright (c) 2011 Siemens AG
+ *
+ * Authors:
+ * Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ */
+#include "hw/apic_internal.h"
+#include "kvm.h"
+
+static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
+ int reg_id, uint32_t val)
+{
+ *((uint32_t *)(kapic->regs + (reg_id << 4))) = val;
+}
+
+static inline uint32_t kvm_apic_get_reg(struct kvm_lapic_state *kapic,
+ int reg_id)
+{
+ return *((uint32_t *)(kapic->regs + (reg_id << 4)));
+}
+
+void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
+{
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ int i;
+
+ memset(kapic, 0, sizeof(kapic));
+ kvm_apic_set_reg(kapic, 0x2, s->id << 24);
+ kvm_apic_set_reg(kapic, 0x8, s->tpr);
+ kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
+ kvm_apic_set_reg(kapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
+ kvm_apic_set_reg(kapic, 0xf, s->spurious_vec);
+ for (i = 0; i < 8; i++) {
+ kvm_apic_set_reg(kapic, 0x10 + i, s->isr[i]);
+ kvm_apic_set_reg(kapic, 0x18 + i, s->tmr[i]);
+ kvm_apic_set_reg(kapic, 0x20 + i, s->irr[i]);
+ }
+ kvm_apic_set_reg(kapic, 0x28, s->esr);
+ kvm_apic_set_reg(kapic, 0x30, s->icr[0]);
+ kvm_apic_set_reg(kapic, 0x31, s->icr[1]);
+ for (i = 0; i < APIC_LVT_NB; i++) {
+ kvm_apic_set_reg(kapic, 0x32 + i, s->lvt[i]);
+ }
+ kvm_apic_set_reg(kapic, 0x38, s->initial_count);
+ kvm_apic_set_reg(kapic, 0x3e, s->divide_conf);
+}
+
+void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic)
+{
+ APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
+ int i, v;
+
+ s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
+ s->tpr = kvm_apic_get_reg(kapic, 0x8);
+ s->arb_id = kvm_apic_get_reg(kapic, 0x9);
+ s->log_dest = kvm_apic_get_reg(kapic, 0xd) >> 24;
+ s->dest_mode = kvm_apic_get_reg(kapic, 0xe) >> 28;
+ s->spurious_vec = kvm_apic_get_reg(kapic, 0xf);
+ for (i = 0; i < 8; i++) {
+ s->isr[i] = kvm_apic_get_reg(kapic, 0x10 + i);
+ s->tmr[i] = kvm_apic_get_reg(kapic, 0x18 + i);
+ s->irr[i] = kvm_apic_get_reg(kapic, 0x20 + i);
+ }
+ s->esr = kvm_apic_get_reg(kapic, 0x28);
+ s->icr[0] = kvm_apic_get_reg(kapic, 0x30);
+ s->icr[1] = kvm_apic_get_reg(kapic, 0x31);
+ for (i = 0; i < APIC_LVT_NB; i++) {
+ s->lvt[i] = kvm_apic_get_reg(kapic, 0x32 + i);
+ }
+ s->initial_count = kvm_apic_get_reg(kapic, 0x38);
+ s->divide_conf = kvm_apic_get_reg(kapic, 0x3e);
+
+ v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
+ s->count_shift = (v + 1) & 7;
+
+ s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
+ apic_next_timer(s, s->initial_count_load_time);
+}
+
+static void kvm_apic_set_base(APICCommonState *s, uint64_t val)
+{
+ s->apicbase = val;
+}
+
+static void kvm_apic_set_tpr(APICCommonState *s, uint8_t val)
+{
+ s->tpr = (val & 0x0f) << 4;
+}
+
+static void do_inject_external_nmi(void *data)
+{
+ APICCommonState *s = data;
+ CPUState *env = s->cpu_env;
+ uint32_t lvt;
+ int ret;
+
+ cpu_synchronize_state(env);
+
+ lvt = s->lvt[APIC_LVT_LINT1];
+ if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) {
+ ret = kvm_vcpu_ioctl(env, KVM_NMI);
+ if (ret < 0) {
+ fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
+ strerror(-ret));
+ }
+ }
+}
+
+static void kvm_apic_external_nmi(APICCommonState *s)
+{
+ run_on_cpu(s->cpu_env, do_inject_external_nmi, s);
+}
+
+static void kvm_apic_init(APICCommonState *s)
+{
+ memory_region_init_reservation(&s->io_memory, "kvm-apic-msi",
+ MSI_SPACE_SIZE);
+}
+
+static void kvm_apic_class_init(ObjectClass *klass, void *data)
+{
+ APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+ k->init = kvm_apic_init;
+ k->set_base = kvm_apic_set_base;
+ k->set_tpr = kvm_apic_set_tpr;
+ k->external_nmi = kvm_apic_external_nmi;
+}
+
+static TypeInfo kvm_apic_info = {
+ .name = "kvm-apic",
+ .parent = TYPE_APIC_COMMON,
+ .instance_size = sizeof(APICCommonState),
+ .class_init = kvm_apic_class_init,
+};
+
+static void kvm_apic_register_device(void)
+{
+ type_register_static(&kvm_apic_info);
+}
+
+device_init(kvm_apic_register_device)
diff --git a/hw/kvmclock.c b/hw/kvm/clock.c
index 3b9fb20495..d5a53869b3 100644
--- a/hw/kvmclock.c
+++ b/hw/kvm/clock.c
@@ -15,9 +15,9 @@
#include "qemu-common.h"
#include "sysemu.h"
-#include "sysbus.h"
#include "kvm.h"
-#include "kvmclock.h"
+#include "hw/sysbus.h"
+#include "hw/kvm/clock.h"
#include <linux/kvm.h>
#include <linux/kvm_para.h>
@@ -92,12 +92,21 @@ static const VMStateDescription kvmclock_vmsd = {
}
};
-static SysBusDeviceInfo kvmclock_info = {
- .qdev.name = "kvmclock",
- .qdev.size = sizeof(KVMClockState),
- .qdev.vmsd = &kvmclock_vmsd,
- .qdev.no_user = 1,
- .init = kvmclock_init,
+static void kvmclock_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = kvmclock_init;
+ dc->no_user = 1;
+ dc->vmsd = &kvmclock_vmsd;
+}
+
+static TypeInfo kvmclock_info = {
+ .name = "kvmclock",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(KVMClockState),
+ .class_init = kvmclock_class_init,
};
/* Note: Must be called after VCPU initialization. */
@@ -113,7 +122,7 @@ void kvmclock_create(void)
static void kvmclock_register_device(void)
{
if (kvm_enabled()) {
- sysbus_register_withprop(&kvmclock_info);
+ type_register_static(&kvmclock_info);
}
}
diff --git a/hw/kvmclock.h b/hw/kvm/clock.h
index 252ea13461..252ea13461 100644
--- a/hw/kvmclock.h
+++ b/hw/kvm/clock.h
diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c
new file mode 100644
index 0000000000..14bd427518
--- /dev/null
+++ b/hw/kvm/i8259.c
@@ -0,0 +1,138 @@
+/*
+ * KVM in-kernel PIC (i8259) support
+ *
+ * Copyright (c) 2011 Siemens AG
+ *
+ * Authors:
+ * Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ */
+#include "hw/i8259_internal.h"
+#include "hw/apic_internal.h"
+#include "kvm.h"
+
+static void kvm_pic_get(PICCommonState *s)
+{
+ struct kvm_irqchip chip;
+ struct kvm_pic_state *kpic;
+ int ret;
+
+ chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE;
+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
+ abort();
+ }
+
+ kpic = &chip.chip.pic;
+
+ s->last_irr = kpic->last_irr;
+ s->irr = kpic->irr;
+ s->imr = kpic->imr;
+ s->isr = kpic->isr;
+ s->priority_add = kpic->priority_add;
+ s->irq_base = kpic->irq_base;
+ s->read_reg_select = kpic->read_reg_select;
+ s->poll = kpic->poll;
+ s->special_mask = kpic->special_mask;
+ s->init_state = kpic->init_state;
+ s->auto_eoi = kpic->auto_eoi;
+ s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi;
+ s->special_fully_nested_mode = kpic->special_fully_nested_mode;
+ s->init4 = kpic->init4;
+ s->elcr = kpic->elcr;
+ s->elcr_mask = kpic->elcr_mask;
+}
+
+static void kvm_pic_put(PICCommonState *s)
+{
+ struct kvm_irqchip chip;
+ struct kvm_pic_state *kpic;
+ int ret;
+
+ chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE;
+
+ kpic = &chip.chip.pic;
+
+ kpic->last_irr = s->last_irr;
+ kpic->irr = s->irr;
+ kpic->imr = s->imr;
+ kpic->isr = s->isr;
+ kpic->priority_add = s->priority_add;
+ kpic->irq_base = s->irq_base;
+ kpic->read_reg_select = s->read_reg_select;
+ kpic->poll = s->poll;
+ kpic->special_mask = s->special_mask;
+ kpic->init_state = s->init_state;
+ kpic->auto_eoi = s->auto_eoi;
+ kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
+ kpic->special_fully_nested_mode = s->special_fully_nested_mode;
+ kpic->init4 = s->init4;
+ kpic->elcr = s->elcr;
+ kpic->elcr_mask = s->elcr_mask;
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
+ abort();
+ }
+}
+
+static void kvm_pic_reset(DeviceState *dev)
+{
+ PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, dev);
+
+ pic_reset_common(s);
+ s->elcr = 0;
+
+ kvm_pic_put(s);
+}
+
+static void kvm_pic_set_irq(void *opaque, int irq, int level)
+{
+ int delivered;
+
+ delivered = kvm_irqchip_set_irq(kvm_state, irq, level);
+ apic_report_irq_delivered(delivered);
+}
+
+static void kvm_pic_init(PICCommonState *s)
+{
+ memory_region_init_reservation(&s->base_io, "kvm-pic", 2);
+ memory_region_init_reservation(&s->elcr_io, "kvm-elcr", 1);
+}
+
+qemu_irq *kvm_i8259_init(ISABus *bus)
+{
+ i8259_init_chip("kvm-i8259", bus, true);
+ i8259_init_chip("kvm-i8259", bus, false);
+
+ return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS);
+}
+
+static void kvm_i8259_class_init(ObjectClass *klass, void *data)
+{
+ PICCommonClass *k = PIC_COMMON_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = kvm_pic_reset;
+ k->init = kvm_pic_init;
+ k->pre_save = kvm_pic_get;
+ k->post_load = kvm_pic_put;
+}
+
+static TypeInfo kvm_i8259_info = {
+ .name = "kvm-i8259",
+ .parent = TYPE_PIC_COMMON,
+ .instance_size = sizeof(PICCommonState),
+ .class_init = kvm_i8259_class_init,
+};
+
+static void kvm_pic_register(void)
+{
+ type_register_static(&kvm_i8259_info);
+}
+
+device_init(kvm_pic_register)
diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c
new file mode 100644
index 0000000000..b316933a96
--- /dev/null
+++ b/hw/kvm/ioapic.c
@@ -0,0 +1,125 @@
+/*
+ * KVM in-kernel IOPIC support
+ *
+ * Copyright (c) 2011 Siemens AG
+ *
+ * Authors:
+ * Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "hw/pc.h"
+#include "hw/ioapic_internal.h"
+#include "hw/apic_internal.h"
+#include "kvm.h"
+
+typedef struct KVMIOAPICState KVMIOAPICState;
+
+struct KVMIOAPICState {
+ IOAPICCommonState ioapic;
+ uint32_t kvm_gsi_base;
+};
+
+static void kvm_ioapic_get(IOAPICCommonState *s)
+{
+ struct kvm_irqchip chip;
+ struct kvm_ioapic_state *kioapic;
+ int ret, i;
+
+ chip.chip_id = KVM_IRQCHIP_IOAPIC;
+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
+ abort();
+ }
+
+ kioapic = &chip.chip.ioapic;
+
+ s->id = kioapic->id;
+ s->ioregsel = kioapic->ioregsel;
+ s->irr = kioapic->irr;
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ s->ioredtbl[i] = kioapic->redirtbl[i].bits;
+ }
+}
+
+static void kvm_ioapic_put(IOAPICCommonState *s)
+{
+ struct kvm_irqchip chip;
+ struct kvm_ioapic_state *kioapic;
+ int ret, i;
+
+ chip.chip_id = KVM_IRQCHIP_IOAPIC;
+ kioapic = &chip.chip.ioapic;
+
+ kioapic->id = s->id;
+ kioapic->ioregsel = s->ioregsel;
+ kioapic->base_address = s->busdev.mmio[0].addr;
+ kioapic->irr = s->irr;
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ kioapic->redirtbl[i].bits = s->ioredtbl[i];
+ }
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
+ abort();
+ }
+}
+
+static void kvm_ioapic_reset(DeviceState *dev)
+{
+ IOAPICCommonState *s = DO_UPCAST(IOAPICCommonState, busdev.qdev, dev);
+
+ ioapic_reset_common(dev);
+ kvm_ioapic_put(s);
+}
+
+static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
+{
+ KVMIOAPICState *s = opaque;
+ int delivered;
+
+ delivered = kvm_irqchip_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
+ apic_report_irq_delivered(delivered);
+}
+
+static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
+{
+ memory_region_init_reservation(&s->io_memory, "kvm-ioapic", 0x1000);
+
+ qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
+}
+
+static Property kvm_ioapic_properties[] = {
+ DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
+{
+ IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = kvm_ioapic_init;
+ k->pre_save = kvm_ioapic_get;
+ k->post_load = kvm_ioapic_put;
+ dc->reset = kvm_ioapic_reset;
+ dc->props = kvm_ioapic_properties;
+}
+
+static TypeInfo kvm_ioapic_info = {
+ .name = "kvm-ioapic",
+ .parent = TYPE_IOAPIC_COMMON,
+ .instance_size = sizeof(KVMIOAPICState),
+ .class_init = kvm_ioapic_class_init,
+};
+
+static void kvm_ioapic_register_device(void)
+{
+ type_register_static(&kvm_ioapic_info);
+}
+
+device_init(kvm_ioapic_register_device)
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 8b83fe2198..78777c7336 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -140,17 +140,36 @@ enum tx_state {
};
typedef struct {
- enum tx_state state;
+ /* state is a tx_state but we can't put enums in VMStateDescriptions. */
+ uint32_t state;
uint32_t cmd_a;
uint32_t cmd_b;
- int buffer_size;
- int offset;
- int pad;
- int fifo_used;
- int len;
+ int32_t buffer_size;
+ int32_t offset;
+ int32_t pad;
+ int32_t fifo_used;
+ int32_t len;
uint8_t data[2048];
} LAN9118Packet;
+static const VMStateDescription vmstate_lan9118_packet = {
+ .name = "lan9118_packet",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(state, LAN9118Packet),
+ VMSTATE_UINT32(cmd_a, LAN9118Packet),
+ VMSTATE_UINT32(cmd_b, LAN9118Packet),
+ VMSTATE_INT32(buffer_size, LAN9118Packet),
+ VMSTATE_INT32(offset, LAN9118Packet),
+ VMSTATE_INT32(pad, LAN9118Packet),
+ VMSTATE_INT32(fifo_used, LAN9118Packet),
+ VMSTATE_INT32(len, LAN9118Packet),
+ VMSTATE_UINT8_ARRAY(data, LAN9118Packet, 2048),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
typedef struct {
SysBusDevice busdev;
NICState *nic;
@@ -190,34 +209,95 @@ typedef struct {
uint32_t phy_int;
uint32_t phy_int_mask;
- int eeprom_writable;
+ int32_t eeprom_writable;
uint8_t eeprom[128];
- int tx_fifo_size;
+ int32_t tx_fifo_size;
LAN9118Packet *txp;
LAN9118Packet tx_packet;
- int tx_status_fifo_used;
- int tx_status_fifo_head;
+ int32_t tx_status_fifo_used;
+ int32_t tx_status_fifo_head;
uint32_t tx_status_fifo[512];
- int rx_status_fifo_size;
- int rx_status_fifo_used;
- int rx_status_fifo_head;
+ int32_t rx_status_fifo_size;
+ int32_t rx_status_fifo_used;
+ int32_t rx_status_fifo_head;
uint32_t rx_status_fifo[896];
- int rx_fifo_size;
- int rx_fifo_used;
- int rx_fifo_head;
+ int32_t rx_fifo_size;
+ int32_t rx_fifo_used;
+ int32_t rx_fifo_head;
uint32_t rx_fifo[3360];
- int rx_packet_size_head;
- int rx_packet_size_tail;
- int rx_packet_size[1024];
+ int32_t rx_packet_size_head;
+ int32_t rx_packet_size_tail;
+ int32_t rx_packet_size[1024];
- int rxp_offset;
- int rxp_size;
- int rxp_pad;
+ int32_t rxp_offset;
+ int32_t rxp_size;
+ int32_t rxp_pad;
} lan9118_state;
+static const VMStateDescription vmstate_lan9118 = {
+ .name = "lan9118",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PTIMER(timer, lan9118_state),
+ VMSTATE_UINT32(irq_cfg, lan9118_state),
+ VMSTATE_UINT32(int_sts, lan9118_state),
+ VMSTATE_UINT32(int_en, lan9118_state),
+ VMSTATE_UINT32(fifo_int, lan9118_state),
+ VMSTATE_UINT32(rx_cfg, lan9118_state),
+ VMSTATE_UINT32(tx_cfg, lan9118_state),
+ VMSTATE_UINT32(hw_cfg, lan9118_state),
+ VMSTATE_UINT32(pmt_ctrl, lan9118_state),
+ VMSTATE_UINT32(gpio_cfg, lan9118_state),
+ VMSTATE_UINT32(gpt_cfg, lan9118_state),
+ VMSTATE_UINT32(word_swap, lan9118_state),
+ VMSTATE_UINT32(free_timer_start, lan9118_state),
+ VMSTATE_UINT32(mac_cmd, lan9118_state),
+ VMSTATE_UINT32(mac_data, lan9118_state),
+ VMSTATE_UINT32(afc_cfg, lan9118_state),
+ VMSTATE_UINT32(e2p_cmd, lan9118_state),
+ VMSTATE_UINT32(e2p_data, lan9118_state),
+ VMSTATE_UINT32(mac_cr, lan9118_state),
+ VMSTATE_UINT32(mac_hashh, lan9118_state),
+ VMSTATE_UINT32(mac_hashl, lan9118_state),
+ VMSTATE_UINT32(mac_mii_acc, lan9118_state),
+ VMSTATE_UINT32(mac_mii_data, lan9118_state),
+ VMSTATE_UINT32(mac_flow, lan9118_state),
+ VMSTATE_UINT32(phy_status, lan9118_state),
+ VMSTATE_UINT32(phy_control, lan9118_state),
+ VMSTATE_UINT32(phy_advertise, lan9118_state),
+ VMSTATE_UINT32(phy_int, lan9118_state),
+ VMSTATE_UINT32(phy_int_mask, lan9118_state),
+ VMSTATE_INT32(eeprom_writable, lan9118_state),
+ VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
+ VMSTATE_INT32(tx_fifo_size, lan9118_state),
+ /* txp always points at tx_packet so need not be saved */
+ VMSTATE_STRUCT(tx_packet, lan9118_state, 0,
+ vmstate_lan9118_packet, LAN9118Packet),
+ VMSTATE_INT32(tx_status_fifo_used, lan9118_state),
+ VMSTATE_INT32(tx_status_fifo_head, lan9118_state),
+ VMSTATE_UINT32_ARRAY(tx_status_fifo, lan9118_state, 512),
+ VMSTATE_INT32(rx_status_fifo_size, lan9118_state),
+ VMSTATE_INT32(rx_status_fifo_used, lan9118_state),
+ VMSTATE_INT32(rx_status_fifo_head, lan9118_state),
+ VMSTATE_UINT32_ARRAY(rx_status_fifo, lan9118_state, 896),
+ VMSTATE_INT32(rx_fifo_size, lan9118_state),
+ VMSTATE_INT32(rx_fifo_used, lan9118_state),
+ VMSTATE_INT32(rx_fifo_head, lan9118_state),
+ VMSTATE_UINT32_ARRAY(rx_fifo, lan9118_state, 3360),
+ VMSTATE_INT32(rx_packet_size_head, lan9118_state),
+ VMSTATE_INT32(rx_packet_size_tail, lan9118_state),
+ VMSTATE_INT32_ARRAY(rx_packet_size, lan9118_state, 1024),
+ VMSTATE_INT32(rxp_offset, lan9118_state),
+ VMSTATE_INT32(rxp_size, lan9118_state),
+ VMSTATE_INT32(rxp_pad, lan9118_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void lan9118_update(lan9118_state *s)
{
int level;
@@ -1141,7 +1221,7 @@ static int lan9118_init1(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_lan9118_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
s->eeprom[0] = 0xa5;
for (i = 0; i < 6; i++) {
@@ -1155,24 +1235,35 @@ static int lan9118_init1(SysBusDevice *dev)
ptimer_set_freq(s->timer, 10000);
ptimer_set_limit(s->timer, 0xffff, 1);
- /* ??? Save/restore. */
return 0;
}
-static SysBusDeviceInfo lan9118_info = {
- .init = lan9118_init1,
- .qdev.name = "lan9118",
- .qdev.size = sizeof(lan9118_state),
- .qdev.reset = lan9118_reset,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(lan9118_state, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property lan9118_properties[] = {
+ DEFINE_NIC_PROPERTIES(lan9118_state, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void lan9118_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lan9118_init1;
+ dc->reset = lan9118_reset;
+ dc->props = lan9118_properties;
+ dc->vmsd = &vmstate_lan9118;
+}
+
+static TypeInfo lan9118_info = {
+ .name = "lan9118",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(lan9118_state),
+ .class_init = lan9118_class_init,
};
static void lan9118_register_devices(void)
{
- sysbus_register_withprop(&lan9118_info);
+ type_register_static(&lan9118_info);
}
/* Legacy helper function. Should go away when machine config files are
diff --git a/hw/lance.c b/hw/lance.c
index 716470061c..519720bd9c 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -137,22 +137,33 @@ static void lance_reset(DeviceState *dev)
pcnet_h_reset(&d->state);
}
-static SysBusDeviceInfo lance_info = {
- .init = lance_init,
- .qdev.name = "lance",
- .qdev.fw_name = "ethernet",
- .qdev.size = sizeof(SysBusPCNetState),
- .qdev.reset = lance_reset,
- .qdev.vmsd = &vmstate_lance,
- .qdev.props = (Property[]) {
- DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque),
- DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property lance_properties[] = {
+ DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque),
+ DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void lance_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lance_init;
+ dc->fw_name = "ethernet";
+ dc->reset = lance_reset;
+ dc->vmsd = &vmstate_lance;
+ dc->props = lance_properties;
+}
+
+static TypeInfo lance_info = {
+ .name = "lance",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusPCNetState),
+ .class_init = lance_class_init,
};
static void lance_register_devices(void)
{
- sysbus_register_withprop(&lance_info);
+ type_register_static(&lance_info);
}
device_init(lance_register_devices)
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
index 5454aa4e4d..38dd28230d 100644
--- a/hw/lm32_juart.c
+++ b/hw/lm32_juart.c
@@ -114,7 +114,7 @@ static int lm32_juart_init(SysBusDevice *dev)
{
LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
}
@@ -134,17 +134,26 @@ static const VMStateDescription vmstate_lm32_juart = {
}
};
-static SysBusDeviceInfo lm32_juart_info = {
- .init = lm32_juart_init,
- .qdev.name = "lm32-juart",
- .qdev.size = sizeof(LM32JuartState),
- .qdev.vmsd = &vmstate_lm32_juart,
- .qdev.reset = juart_reset,
+static void lm32_juart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lm32_juart_init;
+ dc->reset = juart_reset;
+ dc->vmsd = &vmstate_lm32_juart;
+}
+
+static TypeInfo lm32_juart_info = {
+ .name = "lm32-juart",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LM32JuartState),
+ .class_init = lm32_juart_class_init,
};
static void lm32_juart_register(void)
{
- sysbus_register_withprop(&lm32_juart_info);
+ type_register_static(&lm32_juart_info);
}
device_init(lm32_juart_register)
diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
index 8dd005077c..7be6d0d68e 100644
--- a/hw/lm32_pic.c
+++ b/hw/lm32_pic.c
@@ -174,17 +174,26 @@ static const VMStateDescription vmstate_lm32_pic = {
}
};
-static SysBusDeviceInfo lm32_pic_info = {
- .init = lm32_pic_init,
- .qdev.name = "lm32-pic",
- .qdev.size = sizeof(LM32PicState),
- .qdev.vmsd = &vmstate_lm32_pic,
- .qdev.reset = pic_reset,
+static void lm32_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lm32_pic_init;
+ dc->reset = pic_reset;
+ dc->vmsd = &vmstate_lm32_pic;
+}
+
+static TypeInfo lm32_pic_info = {
+ .name = "lm32-pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LM32PicState),
+ .class_init = lm32_pic_class_init,
};
static void lm32_pic_register(void)
{
- sysbus_register_withprop(&lm32_pic_info);
+ type_register_static(&lm32_pic_info);
}
device_init(lm32_pic_register)
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index 83974ee4fb..ba6f4acbaa 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -141,21 +141,32 @@ static const VMStateDescription vmstate_lm32_sys = {
}
};
-static SysBusDeviceInfo lm32_sys_info = {
- .init = lm32_sys_init,
- .qdev.name = "lm32-sys",
- .qdev.size = sizeof(LM32SysState),
- .qdev.vmsd = &vmstate_lm32_sys,
- .qdev.reset = sys_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property lm32_sys_properties[] = {
+ DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void lm32_sys_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lm32_sys_init;
+ dc->reset = sys_reset;
+ dc->vmsd = &vmstate_lm32_sys;
+ dc->props = lm32_sys_properties;
+}
+
+static TypeInfo lm32_sys_info = {
+ .name = "lm32-sys",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LM32SysState),
+ .class_init = lm32_sys_class_init,
};
static void lm32_sys_register(void)
{
- sysbus_register_withprop(&lm32_sys_info);
+ type_register_static(&lm32_sys_info);
}
device_init(lm32_sys_register)
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index 115e1e968f..3cb4e0a4f3 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -199,23 +199,32 @@ static const VMStateDescription vmstate_lm32_timer = {
}
};
-static SysBusDeviceInfo lm32_timer_info = {
- .init = lm32_timer_init,
- .qdev.name = "lm32-timer",
- .qdev.size = sizeof(LM32TimerState),
- .qdev.vmsd = &vmstate_lm32_timer,
- .qdev.reset = timer_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32(
- "frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY
- ),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property lm32_timer_properties[] = {
+ DEFINE_PROP_UINT32("frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void lm32_timer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lm32_timer_init;
+ dc->reset = timer_reset;
+ dc->vmsd = &vmstate_lm32_timer;
+ dc->props = lm32_timer_properties;
+}
+
+static TypeInfo lm32_timer_info = {
+ .name = "lm32-timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LM32TimerState),
+ .class_init = lm32_timer_class_init,
};
static void lm32_timer_register(void)
{
- sysbus_register_withprop(&lm32_timer_info);
+ type_register_static(&lm32_timer_info);
}
device_init(lm32_timer_register)
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index d013abd1c6..630ccb7131 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -252,7 +252,7 @@ static int lm32_uart_init(SysBusDevice *dev)
memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->iomem);
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
@@ -271,17 +271,26 @@ static const VMStateDescription vmstate_lm32_uart = {
}
};
-static SysBusDeviceInfo lm32_uart_info = {
- .init = lm32_uart_init,
- .qdev.name = "lm32-uart",
- .qdev.size = sizeof(LM32UartState),
- .qdev.vmsd = &vmstate_lm32_uart,
- .qdev.reset = uart_reset,
+static void lm32_uart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = lm32_uart_init;
+ dc->reset = uart_reset;
+ dc->vmsd = &vmstate_lm32_uart;
+}
+
+static TypeInfo lm32_uart_info = {
+ .name = "lm32-uart",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LM32UartState),
+ .class_init = lm32_uart_class_init,
};
static void lm32_uart_register(void)
{
- sysbus_register_withprop(&lm32_uart_info);
+ type_register_static(&lm32_uart_info);
}
device_init(lm32_uart_register)
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 992ce49729..895d306635 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -24,7 +24,7 @@
#include "console.h"
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
uint8_t i2c_dir;
uint8_t i2c_cycle;
uint8_t reg;
@@ -378,7 +378,7 @@ static void lm_kbd_write(LM823KbdState *s, int reg, int byte, uint8_t value)
}
}
-static void lm_i2c_event(i2c_slave *i2c, enum i2c_event event)
+static void lm_i2c_event(I2CSlave *i2c, enum i2c_event event)
{
LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
@@ -394,14 +394,14 @@ static void lm_i2c_event(i2c_slave *i2c, enum i2c_event event)
}
}
-static int lm_i2c_rx(i2c_slave *i2c)
+static int lm_i2c_rx(I2CSlave *i2c)
{
LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
return lm_kbd_read(s, s->reg, s->i2c_cycle ++);
}
-static int lm_i2c_tx(i2c_slave *i2c, uint8_t data)
+static int lm_i2c_tx(I2CSlave *i2c, uint8_t data)
{
LM823KbdState *s = (LM823KbdState *) i2c;
@@ -458,7 +458,7 @@ static const VMStateDescription vmstate_lm_kbd = {
};
-static int lm8323_init(i2c_slave *i2c)
+static int lm8323_init(I2CSlave *i2c)
{
LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
@@ -494,19 +494,28 @@ void lm832x_key_event(DeviceState *dev, int key, int state)
lm_kbd_irq_update(s);
}
-static I2CSlaveInfo lm8323_info = {
- .qdev.name = "lm8323",
- .qdev.size = sizeof(LM823KbdState),
- .qdev.vmsd = &vmstate_lm_kbd,
- .init = lm8323_init,
- .event = lm_i2c_event,
- .recv = lm_i2c_rx,
- .send = lm_i2c_tx
+static void lm8323_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = lm8323_init;
+ k->event = lm_i2c_event;
+ k->recv = lm_i2c_rx;
+ k->send = lm_i2c_tx;
+ dc->vmsd = &vmstate_lm_kbd;
+}
+
+static TypeInfo lm8323_info = {
+ .name = "lm8323",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(LM823KbdState),
+ .class_init = lm8323_class_init,
};
static void lm832x_register_devices(void)
{
- i2c_register_slave(&lm8323_info);
+ type_register_static(&lm8323_info);
}
device_init(lm832x_register_devices)
diff --git a/hw/loader.c b/hw/loader.c
index 446b62874e..415cdce534 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -108,8 +108,12 @@ int load_image_targphys(const char *filename,
int size;
size = get_image_size(filename);
- if (size > 0)
+ if (size > max_sz) {
+ return -1;
+ }
+ if (size > 0) {
rom_add_file_fixed(filename, addr, -1);
+ }
return size;
}
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 0d3a1016df..9a7ffe3f42 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1681,7 +1681,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
DeviceState *dev;
QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
- dev->info->reset(dev);
+ device_reset(dev);
}
s->sstat0 |= LSI_SSTAT0_RST;
lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
@@ -2120,23 +2120,31 @@ static int lsi_scsi_init(PCIDevice *dev)
return 0;
}
-static PCIDeviceInfo lsi_info = {
- .qdev.name = "lsi53c895a",
- .qdev.alias = "lsi",
- .qdev.size = sizeof(LSIState),
- .qdev.reset = lsi_scsi_reset,
- .qdev.vmsd = &vmstate_lsi_scsi,
- .init = lsi_scsi_init,
- .exit = lsi_scsi_uninit,
- .vendor_id = PCI_VENDOR_ID_LSI_LOGIC,
- .device_id = PCI_DEVICE_ID_LSI_53C895A,
- .class_id = PCI_CLASS_STORAGE_SCSI,
- .subsystem_id = 0x1000,
+static void lsi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = lsi_scsi_init;
+ k->exit = lsi_scsi_uninit;
+ k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
+ k->device_id = PCI_DEVICE_ID_LSI_53C895A;
+ k->class_id = PCI_CLASS_STORAGE_SCSI;
+ k->subsystem_id = 0x1000;
+ dc->reset = lsi_scsi_reset;
+ dc->vmsd = &vmstate_lsi_scsi;
+}
+
+static TypeInfo lsi_info = {
+ .name = "lsi53c895a",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(LSIState),
+ .class_init = lsi_class_init,
};
static void lsi53c895a_register_devices(void)
{
- pci_qdev_register(&lsi_info);
+ type_register_static(&lsi_info);
}
device_init(lsi53c895a_register_devices);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c0439966cf..c35867d0a1 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -126,7 +126,7 @@ static void alarm_cb (void *opaque)
/* Repeat once a second */
next_time = 1;
}
- qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock_ns(vm_clock) +
+ qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock_ns(rtc_clock) +
next_time * 1000);
qemu_set_irq(NVRAM->IRQ, 0);
}
@@ -687,7 +687,7 @@ static void m48t59_init_common(M48t59State *s)
{
s->buffer = g_malloc0(s->size);
if (s->type == 59) {
- s->alrm_timer = qemu_new_timer_ns(vm_clock, &alarm_cb, s);
+ s->alrm_timer = qemu_new_timer_ns(rtc_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s);
}
qemu_get_timedate(&s->alarm, 0);
@@ -720,37 +720,58 @@ static int m48t59_init1(SysBusDevice *dev)
return 0;
}
-static ISADeviceInfo m48t59_isa_info = {
- .init = m48t59_init_isa1,
- .qdev.name = "m48t59_isa",
- .qdev.size = sizeof(M48t59ISAState),
- .qdev.reset = m48t59_reset_isa,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1),
- DEFINE_PROP_UINT32("type", M48t59ISAState, state.type, -1),
- DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property m48t59_isa_properties[] = {
+ DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1),
+ DEFINE_PROP_UINT32("type", M48t59ISAState, state.type, -1),
+ DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base, 0),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo m48t59_info = {
- .init = m48t59_init1,
- .qdev.name = "m48t59",
- .qdev.size = sizeof(M48t59SysBusState),
- .qdev.reset = m48t59_reset_sysbus,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1),
- DEFINE_PROP_UINT32("type", M48t59SysBusState, state.type, -1),
- DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static void m48t59_init_class_isa1(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = m48t59_init_isa1;
+ dc->no_user = 1;
+ dc->reset = m48t59_reset_isa;
+ dc->props = m48t59_isa_properties;
+}
+
+static TypeInfo m48t59_isa_info = {
+ .name = "m48t59_isa",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(M48t59ISAState),
+ .class_init = m48t59_init_class_isa1,
+};
+
+static Property m48t59_properties[] = {
+ DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1),
+ DEFINE_PROP_UINT32("type", M48t59SysBusState, state.type, -1),
+ DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void m48t59_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = m48t59_init1;
+ dc->reset = m48t59_reset_sysbus;
+ dc->props = m48t59_properties;
+}
+
+static TypeInfo m48t59_info = {
+ .name = "m48t59",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(M48t59SysBusState),
+ .class_init = m48t59_class_init,
};
static void m48t59_register_devices(void)
{
- sysbus_register_withprop(&m48t59_info);
- isa_qdev_register(&m48t59_isa_info);
+ type_register_static(&m48t59_info);
+ type_register_static(&m48t59_isa_info);
}
device_init(m48t59_register_devices)
diff --git a/hw/macio.c b/hw/macio.c
index cc6ae40050..3d648e934b 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -27,8 +27,9 @@
#include "pci.h"
#include "escc.h"
-typedef struct macio_state_t macio_state_t;
-struct macio_state_t {
+typedef struct MacIOState
+{
+ PCIDevice parent;
int is_oldworld;
MemoryRegion bar;
MemoryRegion *pic_mem;
@@ -38,9 +39,9 @@ struct macio_state_t {
void *nvram;
int nb_ide;
MemoryRegion *ide_mem[4];
-};
+} MacIOState;
-static void macio_bar_setup(macio_state_t *macio_state)
+static void macio_bar_setup(MacIOState *macio_state)
{
int i;
MemoryRegion *bar = &macio_state->bar;
@@ -74,6 +75,35 @@ static void macio_bar_setup(macio_state_t *macio_state)
macio_nvram_setup_bar(macio_state->nvram, bar, 0x60000);
}
+static int macio_initfn(PCIDevice *d)
+{
+ d->config[0x3d] = 0x01; // interrupt on pin 1
+ return 0;
+}
+
+static void macio_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = macio_initfn;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->class_id = PCI_CLASS_OTHERS << 8;
+}
+
+static TypeInfo macio_info = {
+ .name = "macio",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(MacIOState),
+ .class_init = macio_class_init,
+};
+
+static void macio_register(void)
+{
+ type_register_static(&macio_info);
+}
+
+device_init(macio_register);
+
void macio_init (PCIBus *bus, int device_id, int is_oldworld,
MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
MemoryRegion *cuda_mem, void *nvram,
@@ -81,13 +111,12 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld,
MemoryRegion *escc_mem)
{
PCIDevice *d;
- macio_state_t *macio_state;
+ MacIOState *macio_state;
int i;
- d = pci_register_device(bus, "macio",
- sizeof(PCIDevice) + sizeof(macio_state_t),
- -1, NULL, NULL);
- macio_state = (macio_state_t *)(d + 1);
+ d = pci_create_simple(bus, -1, "macio");
+
+ macio_state = DO_UPCAST(MacIOState, parent, d);
macio_state->is_oldworld = is_oldworld;
macio_state->pic_mem = pic_mem;
macio_state->dbdma_mem = dbdma_mem;
@@ -104,11 +133,7 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld,
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
pci_config_set_device_id(d->config, device_id);
- pci_config_set_class(d->config, PCI_CLASS_OTHERS << 8);
-
- d->config[0x3d] = 0x01; // interrupt on pin 1
macio_bar_setup(macio_state);
pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &macio_state->bar);
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 0cd8410622..b628f1718d 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -50,7 +50,7 @@ typedef struct mv88w8618_audio_state {
uint32_t play_pos;
uint32_t last_free;
uint32_t clock_div;
- DeviceState *wm;
+ void *wm;
} mv88w8618_audio_state;
static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
@@ -272,25 +272,32 @@ static const VMStateDescription mv88w8618_audio_vmsd = {
}
};
-static SysBusDeviceInfo mv88w8618_audio_info = {
- .init = mv88w8618_audio_init,
- .qdev.name = "mv88w8618_audio",
- .qdev.size = sizeof(mv88w8618_audio_state),
- .qdev.reset = mv88w8618_audio_reset,
- .qdev.vmsd = &mv88w8618_audio_vmsd,
- .qdev.props = (Property[]) {
- {
- .name = "wm8750",
- .info = &qdev_prop_ptr,
- .offset = offsetof(mv88w8618_audio_state, wm),
- },
- {/* end of list */}
- }
+static Property mv88w8618_audio_properties[] = {
+ DEFINE_PROP_PTR("wm8750", mv88w8618_audio_state, wm),
+ {/* end of list */},
+};
+
+static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mv88w8618_audio_init;
+ dc->reset = mv88w8618_audio_reset;
+ dc->vmsd = &mv88w8618_audio_vmsd;
+ dc->props = mv88w8618_audio_properties;
+}
+
+static TypeInfo mv88w8618_audio_info = {
+ .name = "mv88w8618_audio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mv88w8618_audio_state),
+ .class_init = mv88w8618_audio_class_init,
};
static void mv88w8618_register_devices(void)
{
- sysbus_register_withprop(&mv88w8618_audio_info);
+ type_register_static(&mv88w8618_audio_info);
}
device_init(mv88w8618_register_devices)
diff --git a/hw/max111x.c b/hw/max111x.c
index fc79814bf8..9d61aa98db 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -153,24 +153,40 @@ void max111x_set_input(DeviceState *dev, int line, uint8_t value)
s->input[line] = value;
}
-static SSISlaveInfo max1110_info = {
- .qdev.name = "max1110",
- .qdev.size = sizeof(MAX111xState),
- .init = max1110_init,
- .transfer = max111x_transfer
+static void max1110_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = max1110_init;
+ k->transfer = max111x_transfer;
+}
+
+static TypeInfo max1110_info = {
+ .name = "max1110",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(MAX111xState),
+ .class_init = max1110_class_init,
};
-static SSISlaveInfo max1111_info = {
- .qdev.name = "max1111",
- .qdev.size = sizeof(MAX111xState),
- .init = max1111_init,
- .transfer = max111x_transfer
+static void max1111_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = max1111_init;
+ k->transfer = max111x_transfer;
+}
+
+static TypeInfo max1111_info = {
+ .name = "max1111",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(MAX111xState),
+ .class_init = max1111_class_init,
};
static void max111x_register_devices(void)
{
- ssi_register_slave(&max1110_info);
- ssi_register_slave(&max1111_info);
+ type_register_static(&max1110_info);
+ type_register_static(&max1111_info);
}
device_init(max111x_register_devices)
diff --git a/hw/max7310.c b/hw/max7310.c
index c1bdb2ee0c..3a6bb961ef 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -10,7 +10,7 @@
#include "i2c.h"
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
int i2c_command_byte;
int len;
@@ -33,7 +33,7 @@ static void max7310_reset(DeviceState *dev)
s->command = 0x00;
}
-static int max7310_rx(i2c_slave *i2c)
+static int max7310_rx(I2CSlave *i2c)
{
MAX7310State *s = (MAX7310State *) i2c;
@@ -68,7 +68,7 @@ static int max7310_rx(i2c_slave *i2c)
return 0xff;
}
-static int max7310_tx(i2c_slave *i2c, uint8_t data)
+static int max7310_tx(I2CSlave *i2c, uint8_t data)
{
MAX7310State *s = (MAX7310State *) i2c;
uint8_t diff;
@@ -123,7 +123,7 @@ static int max7310_tx(i2c_slave *i2c, uint8_t data)
return 0;
}
-static void max7310_event(i2c_slave *i2c, enum i2c_event event)
+static void max7310_event(I2CSlave *i2c, enum i2c_event event)
{
MAX7310State *s = (MAX7310State *) i2c;
s->len = 0;
@@ -175,7 +175,7 @@ static void max7310_gpio_set(void *opaque, int line, int level)
/* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
* but also accepts sequences that are not SMBus so return an I2C device. */
-static int max7310_init(i2c_slave *i2c)
+static int max7310_init(I2CSlave *i2c)
{
MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, i2c);
@@ -185,20 +185,29 @@ static int max7310_init(i2c_slave *i2c)
return 0;
}
-static I2CSlaveInfo max7310_info = {
- .qdev.name = "max7310",
- .qdev.size = sizeof(MAX7310State),
- .qdev.vmsd = &vmstate_max7310,
- .qdev.reset = max7310_reset,
- .init = max7310_init,
- .event = max7310_event,
- .recv = max7310_rx,
- .send = max7310_tx
+static void max7310_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = max7310_init;
+ k->event = max7310_event;
+ k->recv = max7310_rx;
+ k->send = max7310_tx;
+ dc->reset = max7310_reset;
+ dc->vmsd = &vmstate_max7310;
+}
+
+static TypeInfo max7310_info = {
+ .name = "max7310",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(MAX7310State),
+ .class_init = max7310_class_init,
};
static void max7310_register_devices(void)
{
- i2c_register_slave(&max7310_info);
+ type_register_static(&max7310_info);
}
device_init(max7310_register_devices)
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 657fa10d6d..4a43225707 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -101,6 +101,7 @@ typedef struct RTCState {
QEMUTimer *second_timer;
QEMUTimer *second_timer2;
Notifier clock_reset_notifier;
+ LostTickPolicy lost_tick_policy;
} RTCState;
static void rtc_set_time(RTCState *s);
@@ -183,7 +184,7 @@ static void rtc_periodic_timer(void *opaque)
if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
#ifdef TARGET_I386
- if(rtc_td_hack) {
+ if (s->lost_tick_policy == LOST_TICK_SLEW) {
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
@@ -544,7 +545,7 @@ static int rtc_post_load(void *opaque, int version_id)
RTCState *s = opaque;
if (version_id >= 2) {
- if (rtc_td_hack) {
+ if (s->lost_tick_policy == LOST_TICK_SLEW) {
rtc_coalesced_timer_update(s);
}
}
@@ -589,7 +590,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
qemu_mod_timer(s->second_timer2, s->next_second_time);
rtc_timer_update(s, now);
#ifdef TARGET_I386
- if (rtc_td_hack) {
+ if (s->lost_tick_policy == LOST_TICK_SLEW) {
rtc_coalesced_timer_update(s);
}
#endif
@@ -605,8 +606,9 @@ static void rtc_reset(void *opaque)
qemu_irq_lower(s->irq);
#ifdef TARGET_I386
- if (rtc_td_hack)
- s->irq_coalesced = 0;
+ if (s->lost_tick_policy == LOST_TICK_SLEW) {
+ s->irq_coalesced = 0;
+ }
#endif
}
@@ -626,10 +628,10 @@ static void visit_type_int32(Visitor *v, int *value, const char *name, Error **e
visit_type_int(v, &val, name, errp);
}
-static void rtc_get_date(DeviceState *dev, Visitor *v, void *opaque,
+static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
- ISADevice *isa = DO_UPCAST(ISADevice, qdev, dev);
+ ISADevice *isa = ISA_DEVICE(obj);
RTCState *s = DO_UPCAST(RTCState, dev, isa);
visit_start_struct(v, NULL, "struct tm", name, 0, errp);
@@ -654,12 +656,20 @@ static int rtc_initfn(ISADevice *dev)
rtc_set_date_from_host(dev);
- s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
#ifdef TARGET_I386
- if (rtc_td_hack)
+ switch (s->lost_tick_policy) {
+ case LOST_TICK_SLEW:
s->coalesced_timer =
qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
+ break;
+ case LOST_TICK_DISCARD:
+ break;
+ default:
+ return -EINVAL;
+ }
#endif
+
+ s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
@@ -676,8 +686,8 @@ static int rtc_initfn(ISADevice *dev)
qdev_set_legacy_instance_id(&dev->qdev, base, 2);
qemu_register_reset(rtc_reset, s);
- qdev_property_add(&s->dev.qdev, "date", "struct tm",
- rtc_get_date, NULL, NULL, s, NULL);
+ object_property_add(OBJECT(s), "date", "struct tm",
+ rtc_get_date, NULL, NULL, s, NULL);
return 0;
}
@@ -699,20 +709,32 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
return dev;
}
-static ISADeviceInfo mc146818rtc_info = {
- .qdev.name = "mc146818rtc",
- .qdev.size = sizeof(RTCState),
- .qdev.no_user = 1,
- .qdev.vmsd = &vmstate_rtc,
- .init = rtc_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property mc146818rtc_properties[] = {
+ DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
+ DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
+ lost_tick_policy, LOST_TICK_DISCARD),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rtc_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = rtc_initfn;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_rtc;
+ dc->props = mc146818rtc_properties;
+}
+
+static TypeInfo mc146818rtc_info = {
+ .name = "mc146818rtc",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(RTCState),
+ .class_init = rtc_class_initfn,
};
static void mc146818rtc_register(void)
{
- isa_qdev_register(&mc146818rtc_info);
+ type_register_static(&mc146818rtc_info);
}
device_init(mc146818rtc_register)
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index e824a49e9a..0881643a4c 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -319,17 +319,26 @@ static const VMStateDescription vmstate_milkymist_ac97 = {
}
};
-static SysBusDeviceInfo milkymist_ac97_info = {
- .init = milkymist_ac97_init,
- .qdev.name = "milkymist-ac97",
- .qdev.size = sizeof(MilkymistAC97State),
- .qdev.vmsd = &vmstate_milkymist_ac97,
- .qdev.reset = milkymist_ac97_reset,
+static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_ac97_init;
+ dc->reset = milkymist_ac97_reset;
+ dc->vmsd = &vmstate_milkymist_ac97;
+}
+
+static TypeInfo milkymist_ac97_info = {
+ .name = "milkymist-ac97",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistAC97State),
+ .class_init = milkymist_ac97_class_init,
};
static void milkymist_ac97_register(void)
{
- sysbus_register_withprop(&milkymist_ac97_info);
+ type_register_static(&milkymist_ac97_info);
}
device_init(milkymist_ac97_register)
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index be575c98a0..b5122afd57 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -145,17 +145,26 @@ static const VMStateDescription vmstate_milkymist_hpdmc = {
}
};
-static SysBusDeviceInfo milkymist_hpdmc_info = {
- .init = milkymist_hpdmc_init,
- .qdev.name = "milkymist-hpdmc",
- .qdev.size = sizeof(MilkymistHpdmcState),
- .qdev.vmsd = &vmstate_milkymist_hpdmc,
- .qdev.reset = milkymist_hpdmc_reset,
+static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_hpdmc_init;
+ dc->reset = milkymist_hpdmc_reset;
+ dc->vmsd = &vmstate_milkymist_hpdmc;
+}
+
+static TypeInfo milkymist_hpdmc_info = {
+ .name = "milkymist-hpdmc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistHpdmcState),
+ .class_init = milkymist_hpdmc_class_init,
};
static void milkymist_hpdmc_register(void)
{
- sysbus_register_withprop(&milkymist_hpdmc_info);
+ type_register_static(&milkymist_hpdmc_info);
}
device_init(milkymist_hpdmc_register)
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index 865a46c127..3c1c68a2e7 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -278,17 +278,26 @@ static const VMStateDescription vmstate_milkymist_memcard = {
}
};
-static SysBusDeviceInfo milkymist_memcard_info = {
- .init = milkymist_memcard_init,
- .qdev.name = "milkymist-memcard",
- .qdev.size = sizeof(MilkymistMemcardState),
- .qdev.vmsd = &vmstate_milkymist_memcard,
- .qdev.reset = milkymist_memcard_reset,
+static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_memcard_init;
+ dc->reset = milkymist_memcard_reset;
+ dc->vmsd = &vmstate_milkymist_memcard;
+}
+
+static TypeInfo milkymist_memcard_info = {
+ .name = "milkymist-memcard",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistMemcardState),
+ .class_init = milkymist_memcard_class_init,
};
static void milkymist_memcard_register(void)
{
- sysbus_register_withprop(&milkymist_memcard_info);
+ type_register_static(&milkymist_memcard_info);
}
device_init(milkymist_memcard_register)
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 7006d29788..b9b553fc95 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -479,7 +479,7 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
@@ -516,24 +516,35 @@ static const VMStateDescription vmstate_milkymist_minimac2 = {
}
};
-static SysBusDeviceInfo milkymist_minimac2_info = {
- .init = milkymist_minimac2_init,
- .qdev.name = "milkymist-minimac2",
- .qdev.size = sizeof(MilkymistMinimac2State),
- .qdev.vmsd = &vmstate_milkymist_minimac2,
- .qdev.reset = milkymist_minimac2_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
- buffers_base, 0),
- DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
- DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property milkymist_minimac2_properties[] = {
+ DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
+ buffers_base, 0),
+ DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
+ DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_minimac2_init;
+ dc->reset = milkymist_minimac2_reset;
+ dc->vmsd = &vmstate_milkymist_minimac2;
+ dc->props = milkymist_minimac2_properties;
+}
+
+static TypeInfo milkymist_minimac2_info = {
+ .name = "milkymist-minimac2",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistMinimac2State),
+ .class_init = milkymist_minimac2_class_init,
};
static void milkymist_minimac2_register(void)
{
- sysbus_register_withprop(&milkymist_minimac2_info);
+ type_register_static(&milkymist_minimac2_info);
}
device_init(milkymist_minimac2_register)
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index dc92eb68e3..1b73a4686b 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -519,17 +519,26 @@ static const VMStateDescription vmstate_milkymist_pfpu = {
}
};
-static SysBusDeviceInfo milkymist_pfpu_info = {
- .init = milkymist_pfpu_init,
- .qdev.name = "milkymist-pfpu",
- .qdev.size = sizeof(MilkymistPFPUState),
- .qdev.vmsd = &vmstate_milkymist_pfpu,
- .qdev.reset = milkymist_pfpu_reset,
+static void milkymist_pfpu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_pfpu_init;
+ dc->reset = milkymist_pfpu_reset;
+ dc->vmsd = &vmstate_milkymist_pfpu;
+}
+
+static TypeInfo milkymist_pfpu_info = {
+ .name = "milkymist-pfpu",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistPFPUState),
+ .class_init = milkymist_pfpu_class_init,
};
static void milkymist_pfpu_register(void)
{
- sysbus_register_withprop(&milkymist_pfpu_info);
+ type_register_static(&milkymist_pfpu_info);
}
device_init(milkymist_pfpu_register)
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 83bd1c4c6b..5d496cbdb0 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -297,32 +297,35 @@ static const VMStateDescription vmstate_milkymist_softusb = {
}
};
-static SysBusDeviceInfo milkymist_softusb_info = {
- .init = milkymist_softusb_init,
- .qdev.name = "milkymist-softusb",
- .qdev.size = sizeof(MilkymistSoftUsbState),
- .qdev.vmsd = &vmstate_milkymist_softusb,
- .qdev.reset = milkymist_softusb_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32(
- "pmem_base", MilkymistSoftUsbState, pmem_base, 0xa0000000
- ),
- DEFINE_PROP_UINT32(
- "pmem_size", MilkymistSoftUsbState, pmem_size, 0x00001000
- ),
- DEFINE_PROP_UINT32(
- "dmem_base", MilkymistSoftUsbState, dmem_base, 0xa0020000
- ),
- DEFINE_PROP_UINT32(
- "dmem_size", MilkymistSoftUsbState, dmem_size, 0x00002000
- ),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property milkymist_softusb_properties[] = {
+ DEFINE_PROP_UINT32("pmem_base", MilkymistSoftUsbState, pmem_base, 0xa0000000),
+ DEFINE_PROP_UINT32("pmem_size", MilkymistSoftUsbState, pmem_size, 0x00001000),
+ DEFINE_PROP_UINT32("dmem_base", MilkymistSoftUsbState, dmem_base, 0xa0020000),
+ DEFINE_PROP_UINT32("dmem_size", MilkymistSoftUsbState, dmem_size, 0x00002000),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_softusb_init;
+ dc->reset = milkymist_softusb_reset;
+ dc->vmsd = &vmstate_milkymist_softusb;
+ dc->props = milkymist_softusb_properties;
+}
+
+static TypeInfo milkymist_softusb_info = {
+ .name = "milkymist-softusb",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistSoftUsbState),
+ .class_init = milkymist_softusb_class_init,
};
static void milkymist_softusb_register(void)
{
- sysbus_register_withprop(&milkymist_softusb_info);
+ type_register_static(&milkymist_softusb_info);
}
device_init(milkymist_softusb_register)
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index bd2a298d2e..18171f6165 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -292,28 +292,39 @@ static const VMStateDescription vmstate_milkymist_sysctl = {
}
};
-static SysBusDeviceInfo milkymist_sysctl_info = {
- .init = milkymist_sysctl_init,
- .qdev.name = "milkymist-sysctl",
- .qdev.size = sizeof(MilkymistSysctlState),
- .qdev.vmsd = &vmstate_milkymist_sysctl,
- .qdev.reset = milkymist_sysctl_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("frequency", MilkymistSysctlState,
- freq_hz, 80000000),
- DEFINE_PROP_UINT32("capabilities", MilkymistSysctlState,
- capabilities, 0x00000000),
- DEFINE_PROP_UINT32("systemid", MilkymistSysctlState,
- systemid, 0x10014d31),
- DEFINE_PROP_UINT32("gpio_strappings", MilkymistSysctlState,
- strappings, 0x00000001),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property milkymist_sysctl_properties[] = {
+ DEFINE_PROP_UINT32("frequency", MilkymistSysctlState,
+ freq_hz, 80000000),
+ DEFINE_PROP_UINT32("capabilities", MilkymistSysctlState,
+ capabilities, 0x00000000),
+ DEFINE_PROP_UINT32("systemid", MilkymistSysctlState,
+ systemid, 0x10014d31),
+ DEFINE_PROP_UINT32("gpio_strappings", MilkymistSysctlState,
+ strappings, 0x00000001),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_sysctl_init;
+ dc->reset = milkymist_sysctl_reset;
+ dc->vmsd = &vmstate_milkymist_sysctl;
+ dc->props = milkymist_sysctl_properties;
+}
+
+static TypeInfo milkymist_sysctl_info = {
+ .name = "milkymist-sysctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistSysctlState),
+ .class_init = milkymist_sysctl_class_init,
};
static void milkymist_sysctl_register(void)
{
- sysbus_register_withprop(&milkymist_sysctl_info);
+ type_register_static(&milkymist_sysctl_info);
}
device_init(milkymist_sysctl_register)
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index 20110e5a83..474eae0a4a 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -465,17 +465,26 @@ static const VMStateDescription vmstate_milkymist_tmu2 = {
}
};
-static SysBusDeviceInfo milkymist_tmu2_info = {
- .init = milkymist_tmu2_init,
- .qdev.name = "milkymist-tmu2",
- .qdev.size = sizeof(MilkymistTMU2State),
- .qdev.vmsd = &vmstate_milkymist_tmu2,
- .qdev.reset = milkymist_tmu2_reset,
+static void milkymist_tmu2_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_tmu2_init;
+ dc->reset = milkymist_tmu2_reset;
+ dc->vmsd = &vmstate_milkymist_tmu2;
+}
+
+static TypeInfo milkymist_tmu2_info = {
+ .name = "milkymist-tmu2",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistTMU2State),
+ .class_init = milkymist_tmu2_class_init,
};
static void milkymist_tmu2_register(void)
{
- sysbus_register_withprop(&milkymist_tmu2_info);
+ type_register_static(&milkymist_tmu2_info);
}
device_init(milkymist_tmu2_register)
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index eaf1c0dce1..f9a229cf68 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -199,7 +199,7 @@ static int milkymist_uart_init(SysBusDevice *dev)
"milkymist-uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
@@ -218,17 +218,26 @@ static const VMStateDescription vmstate_milkymist_uart = {
}
};
-static SysBusDeviceInfo milkymist_uart_info = {
- .init = milkymist_uart_init,
- .qdev.name = "milkymist-uart",
- .qdev.size = sizeof(MilkymistUartState),
- .qdev.vmsd = &vmstate_milkymist_uart,
- .qdev.reset = milkymist_uart_reset,
+static void milkymist_uart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_uart_init;
+ dc->reset = milkymist_uart_reset;
+ dc->vmsd = &vmstate_milkymist_uart;
+}
+
+static TypeInfo milkymist_uart_info = {
+ .name = "milkymist-uart",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistUartState),
+ .class_init = milkymist_uart_class_init,
};
static void milkymist_uart_register(void)
{
- sysbus_register_withprop(&milkymist_uart_info);
+ type_register_static(&milkymist_uart_info);
}
device_init(milkymist_uart_register)
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 108115e300..92ad02f9e2 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -299,22 +299,33 @@ static const VMStateDescription vmstate_milkymist_vgafb = {
}
};
-static SysBusDeviceInfo milkymist_vgafb_info = {
- .init = milkymist_vgafb_init,
- .qdev.name = "milkymist-vgafb",
- .qdev.size = sizeof(MilkymistVgafbState),
- .qdev.vmsd = &vmstate_milkymist_vgafb,
- .qdev.reset = milkymist_vgafb_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
- DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property milkymist_vgafb_properties[] = {
+ DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
+ DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = milkymist_vgafb_init;
+ dc->reset = milkymist_vgafb_reset;
+ dc->vmsd = &vmstate_milkymist_vgafb;
+ dc->props = milkymist_vgafb_properties;
+}
+
+static TypeInfo milkymist_vgafb_info = {
+ .name = "milkymist-vgafb",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MilkymistVgafbState),
+ .class_init = milkymist_vgafb_class_init,
};
static void milkymist_vgafb_register(void)
{
- sysbus_register_withprop(&milkymist_vgafb_info);
+ type_register_static(&milkymist_vgafb_info);
}
device_init(milkymist_vgafb_register)
diff --git a/hw/milkymist-vgafb_template.h b/hw/milkymist-vgafb_template.h
index 69af9ef3f6..1d33ee8b50 100644
--- a/hw/milkymist-vgafb_template.h
+++ b/hw/milkymist-vgafb_template.h
@@ -39,7 +39,7 @@
#elif BITS == 24
#define COPY_PIXEL(to, r, g, b) \
do { \
- uint32 tmp = rgb_to_pixel24(r, g, b); \
+ uint32_t tmp = rgb_to_pixel24(r, g, b); \
*(to++) = tmp & 0xff; \
*(to++) = (tmp >> 8) & 0xff; \
*(to++) = (tmp >> 16) & 0xff; \
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index e625ec398f..d232630e66 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -996,11 +996,7 @@ void mips_malta_init (ram_addr_t ram_size,
if (cirrus_vga_enabled) {
pci_cirrus_vga_init(pci_bus);
} else if (vmsvga_enabled) {
- if (!pci_vmsvga_init(pci_bus)) {
- fprintf(stderr, "Warning: vmware_vga not available,"
- " using standard VGA instead\n");
- pci_vga_init(pci_bus);
- }
+ pci_vmsvga_init(pci_bus);
} else if (std_vga_enabled) {
pci_vga_init(pci_bus);
}
@@ -1011,13 +1007,18 @@ static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
return 0;
}
-static SysBusDeviceInfo mips_malta_device = {
- .init = mips_malta_sysbus_device_init,
- .qdev.name = "mips-malta",
- .qdev.size = sizeof(MaltaState),
- .qdev.props = (Property[]) {
- DEFINE_PROP_END_OF_LIST(),
- }
+static void mips_malta_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mips_malta_sysbus_device_init;
+}
+
+static TypeInfo mips_malta_device = {
+ .name = "mips-malta",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MaltaState),
+ .class_init = mips_malta_class_init,
};
static QEMUMachine mips_malta_machine = {
@@ -1030,7 +1031,7 @@ static QEMUMachine mips_malta_machine = {
static void mips_malta_device_init(void)
{
- sysbus_register_withprop(&mips_malta_device);
+ type_register_static(&mips_malta_device);
}
static void mips_malta_machine_init(void)
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index b1234b8282..a0e6c9fa1e 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -240,7 +240,7 @@ static int mipsnet_sysbus_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
@@ -252,22 +252,33 @@ static void mipsnet_sysbus_reset(DeviceState *dev)
mipsnet_reset(s);
}
-static SysBusDeviceInfo mipsnet_info = {
- .init = mipsnet_sysbus_init,
- .qdev.name = "mipsnet",
- .qdev.desc = "MIPS Simulator network device",
- .qdev.size = sizeof(MIPSnetState),
- .qdev.vmsd = &vmstate_mipsnet,
- .qdev.reset = mipsnet_sysbus_reset,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(MIPSnetState, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property mipsnet_properties[] = {
+ DEFINE_NIC_PROPERTIES(MIPSnetState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mipsnet_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mipsnet_sysbus_init;
+ dc->desc = "MIPS Simulator network device";
+ dc->reset = mipsnet_sysbus_reset;
+ dc->vmsd = &vmstate_mipsnet;
+ dc->props = mipsnet_properties;
+}
+
+static TypeInfo mipsnet_info = {
+ .name = "mipsnet",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MIPSnetState),
+ .class_init = mipsnet_class_init,
};
static void mipsnet_register_devices(void)
{
- sysbus_register_withprop(&mipsnet_info);
+ type_register_static(&mipsnet_info);
}
device_init(mipsnet_register_devices)
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index f01b38cfc2..28cd60d89c 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -121,14 +121,22 @@ static int mpc8544_guts_initfn(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo mpc8544_guts_info = {
- .init = mpc8544_guts_initfn,
- .qdev.name = "mpc8544-guts",
- .qdev.size = sizeof(GutsState),
+static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mpc8544_guts_initfn;
+}
+
+static TypeInfo mpc8544_guts_info = {
+ .name = "mpc8544-guts",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GutsState),
+ .class_init = mpc8544_guts_class_init,
};
static void mpc8544_guts_register(void)
{
- sysbus_register_withprop(&mpc8544_guts_info);
+ type_register_static(&mpc8544_guts_info);
}
device_init(mpc8544_guts_register);
diff --git a/hw/msi.c b/hw/msi.c
index f214fcf579..5d6ceb6df0 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -36,6 +36,9 @@
#define PCI_MSI_VECTORS_MAX 32
+/* Flag for interrupt controller to declare MSI/MSI-X support */
+bool msi_supported;
+
/* If we get rid of cap allocator, we won't need this. */
static inline uint8_t msi_cap_sizeof(uint16_t flags)
{
@@ -116,6 +119,11 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
uint16_t flags;
uint8_t cap_size;
int config_offset;
+
+ if (!msi_supported) {
+ return -ENOTSUP;
+ }
+
MSI_DEV_PRINTF(dev,
"init offset: 0x%"PRIx8" vector: %"PRId8
" 64bit %d mask %d\n",
diff --git a/hw/msi.h b/hw/msi.h
index 5766018d79..3040bb0b43 100644
--- a/hw/msi.h
+++ b/hw/msi.h
@@ -24,6 +24,8 @@
#include "qemu-common.h"
#include "pci.h"
+extern bool msi_supported;
+
bool msi_enabled(const PCIDevice *dev);
int msi_init(struct PCIDevice *dev, uint8_t offset,
unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask);
diff --git a/hw/msix.c b/hw/msix.c
index f47d26bb49..3835eaaf28 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -15,6 +15,7 @@
*/
#include "hw.h"
+#include "msi.h"
#include "msix.h"
#include "pci.h"
#include "range.h"
@@ -35,9 +36,6 @@
#define MSIX_MAX_ENTRIES 32
-/* Flag for interrupt controller to declare MSI-X support */
-int msix_supported;
-
/* Add MSI-X capability to the config space for the device. */
/* Given a bar and its size, add MSI-X table on top of it
* and fill MSI-X capability in the config space.
@@ -238,10 +236,11 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
unsigned bar_nr, unsigned bar_size)
{
int ret;
+
/* Nothing to do if MSI is not supported by interrupt controller */
- if (!msix_supported)
+ if (!msi_supported) {
return -ENOTSUP;
-
+ }
if (nentries > MSIX_MAX_ENTRIES)
return -EINVAL;
diff --git a/hw/msix.h b/hw/msix.h
index 7e04336618..5aba22b858 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -29,6 +29,4 @@ void msix_notify(PCIDevice *dev, unsigned vector);
void msix_reset(PCIDevice *dev);
-extern int msix_supported;
-
#endif
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 8bfa5dda37..1729db01a4 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -238,16 +238,25 @@ static VMStateDescription vmstate_mst_fpga_regs = {
},
};
-static SysBusDeviceInfo mst_fpga_info = {
- .init = mst_fpga_init,
- .qdev.name = "mainstone-fpga",
- .qdev.desc = "Mainstone II FPGA",
- .qdev.size = sizeof(mst_irq_state),
- .qdev.vmsd = &vmstate_mst_fpga_regs,
+static void mst_fpga_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mst_fpga_init;
+ dc->desc = "Mainstone II FPGA";
+ dc->vmsd = &vmstate_mst_fpga_regs;
+}
+
+static TypeInfo mst_fpga_info = {
+ .name = "mainstone-fpga",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mst_irq_state),
+ .class_init = mst_fpga_class_init,
};
static void mst_fpga_register(void)
{
- sysbus_register_withprop(&mst_fpga_info);
+ type_register_static(&mst_fpga_info);
}
device_init(mst_fpga_register);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 977ffb6e50..ac909248d4 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -387,7 +387,7 @@ static int mv88w8618_eth_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
MP_ETH_SIZE);
sysbus_init_mmio(dev, &s->iomem);
@@ -412,15 +412,26 @@ static const VMStateDescription mv88w8618_eth_vmsd = {
}
};
-static SysBusDeviceInfo mv88w8618_eth_info = {
- .init = mv88w8618_eth_init,
- .qdev.name = "mv88w8618_eth",
- .qdev.size = sizeof(mv88w8618_eth_state),
- .qdev.vmsd = &mv88w8618_eth_vmsd,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property mv88w8618_eth_properties[] = {
+ DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mv88w8618_eth_init;
+ dc->vmsd = &mv88w8618_eth_vmsd;
+ dc->props = mv88w8618_eth_properties;
+}
+
+static TypeInfo mv88w8618_eth_info = {
+ .name = "mv88w8618_eth",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mv88w8618_eth_state),
+ .class_init = mv88w8618_eth_class_init,
};
/* LCD register offsets */
@@ -624,11 +635,20 @@ static const VMStateDescription musicpal_lcd_vmsd = {
}
};
-static SysBusDeviceInfo musicpal_lcd_info = {
- .init = musicpal_lcd_init,
- .qdev.name = "musicpal_lcd",
- .qdev.size = sizeof(musicpal_lcd_state),
- .qdev.vmsd = &musicpal_lcd_vmsd,
+static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = musicpal_lcd_init;
+ dc->vmsd = &musicpal_lcd_vmsd;
+}
+
+static TypeInfo musicpal_lcd_info = {
+ .name = "musicpal_lcd",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(musicpal_lcd_state),
+ .class_init = musicpal_lcd_class_init,
};
/* PIC register offsets */
@@ -733,12 +753,21 @@ static const VMStateDescription mv88w8618_pic_vmsd = {
}
};
-static SysBusDeviceInfo mv88w8618_pic_info = {
- .init = mv88w8618_pic_init,
- .qdev.name = "mv88w8618_pic",
- .qdev.size = sizeof(mv88w8618_pic_state),
- .qdev.reset = mv88w8618_pic_reset,
- .qdev.vmsd = &mv88w8618_pic_vmsd,
+static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mv88w8618_pic_init;
+ dc->reset = mv88w8618_pic_reset;
+ dc->vmsd = &mv88w8618_pic_vmsd;
+}
+
+static TypeInfo mv88w8618_pic_info = {
+ .name = "mv88w8618_pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mv88w8618_pic_state),
+ .class_init = mv88w8618_pic_class_init,
};
/* PIT register offsets */
@@ -901,12 +930,21 @@ static const VMStateDescription mv88w8618_pit_vmsd = {
}
};
-static SysBusDeviceInfo mv88w8618_pit_info = {
- .init = mv88w8618_pit_init,
- .qdev.name = "mv88w8618_pit",
- .qdev.size = sizeof(mv88w8618_pit_state),
- .qdev.reset = mv88w8618_pit_reset,
- .qdev.vmsd = &mv88w8618_pit_vmsd,
+static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mv88w8618_pit_init;
+ dc->reset = mv88w8618_pit_reset;
+ dc->vmsd = &mv88w8618_pit_vmsd;
+}
+
+static TypeInfo mv88w8618_pit_info = {
+ .name = "mv88w8618_pit",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mv88w8618_pit_state),
+ .class_init = mv88w8618_pit_class_init,
};
/* Flash config register offsets */
@@ -973,11 +1011,20 @@ static const VMStateDescription mv88w8618_flashcfg_vmsd = {
}
};
-static SysBusDeviceInfo mv88w8618_flashcfg_info = {
- .init = mv88w8618_flashcfg_init,
- .qdev.name = "mv88w8618_flashcfg",
- .qdev.size = sizeof(mv88w8618_flashcfg_state),
- .qdev.vmsd = &mv88w8618_flashcfg_vmsd,
+static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mv88w8618_flashcfg_init;
+ dc->vmsd = &mv88w8618_flashcfg_vmsd;
+}
+
+static TypeInfo mv88w8618_flashcfg_info = {
+ .name = "mv88w8618_flashcfg",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(mv88w8618_flashcfg_state),
+ .class_init = mv88w8618_flashcfg_class_init,
};
/* Misc register offsets */
@@ -1285,12 +1332,21 @@ static const VMStateDescription musicpal_gpio_vmsd = {
}
};
-static SysBusDeviceInfo musicpal_gpio_info = {
- .init = musicpal_gpio_init,
- .qdev.name = "musicpal_gpio",
- .qdev.size = sizeof(musicpal_gpio_state),
- .qdev.reset = musicpal_gpio_reset,
- .qdev.vmsd = &musicpal_gpio_vmsd,
+static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = musicpal_gpio_init;
+ dc->reset = musicpal_gpio_reset;
+ dc->vmsd = &musicpal_gpio_vmsd;
+}
+
+static TypeInfo musicpal_gpio_info = {
+ .name = "musicpal_gpio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(musicpal_gpio_state),
+ .class_init = musicpal_gpio_class_init,
};
/* Keyboard codes & masks */
@@ -1431,11 +1487,20 @@ static const VMStateDescription musicpal_key_vmsd = {
}
};
-static SysBusDeviceInfo musicpal_key_info = {
- .init = musicpal_key_init,
- .qdev.name = "musicpal_key",
- .qdev.size = sizeof(musicpal_key_state),
- .qdev.vmsd = &musicpal_key_vmsd,
+static void musicpal_key_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = musicpal_key_init;
+ dc->vmsd = &musicpal_key_vmsd;
+}
+
+static TypeInfo musicpal_key_info = {
+ .name = "musicpal_key",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(musicpal_key_state),
+ .class_init = musicpal_key_class_init,
};
static struct arm_boot_info musicpal_binfo = {
@@ -1602,17 +1667,30 @@ static void musicpal_machine_init(void)
machine_init(musicpal_machine_init);
+static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = mv88w8618_wlan_init;
+}
+
+static TypeInfo mv88w8618_wlan_info = {
+ .name = "mv88w8618_wlan",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = mv88w8618_wlan_class_init,
+};
+
static void musicpal_register_devices(void)
{
- sysbus_register_withprop(&mv88w8618_pic_info);
- sysbus_register_withprop(&mv88w8618_pit_info);
- sysbus_register_withprop(&mv88w8618_flashcfg_info);
- sysbus_register_withprop(&mv88w8618_eth_info);
- sysbus_register_dev("mv88w8618_wlan", sizeof(SysBusDevice),
- mv88w8618_wlan_init);
- sysbus_register_withprop(&musicpal_lcd_info);
- sysbus_register_withprop(&musicpal_gpio_info);
- sysbus_register_withprop(&musicpal_key_info);
+ type_register_static(&mv88w8618_pic_info);
+ type_register_static(&mv88w8618_pit_info);
+ type_register_static(&mv88w8618_flashcfg_info);
+ type_register_static(&mv88w8618_eth_info);
+ type_register_static(&mv88w8618_wlan_info);
+ type_register_static(&musicpal_lcd_info);
+ type_register_static(&musicpal_gpio_info);
+ type_register_static(&musicpal_key_info);
}
device_init(musicpal_register_devices)
diff --git a/hw/nand.c b/hw/nand.c
index 8597aa6b1c..5d947b1ced 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -417,23 +417,34 @@ static int nand_device_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo nand_info = {
- .init = nand_device_init,
- .qdev.name = "nand",
- .qdev.size = sizeof(NANDFlashState),
- .qdev.reset = nand_reset,
- .qdev.vmsd = &vmstate_nand,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
- DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
- DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property nand_properties[] = {
+ DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
+ DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
+ DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void nand_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = nand_device_init;
+ dc->reset = nand_reset;
+ dc->vmsd = &vmstate_nand;
+ dc->props = nand_properties;
+}
+
+static TypeInfo nand_info = {
+ .name = "nand",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NANDFlashState),
+ .class_init = nand_class_init,
};
static void nand_create_device(void)
{
- sysbus_register_withprop(&nand_info);
+ type_register_static(&nand_info);
}
/*
diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c
index 11ffee7d7c..1352282152 100644
--- a/hw/ne2000-isa.c
+++ b/hw/ne2000-isa.c
@@ -76,27 +76,37 @@ static int isa_ne2000_initfn(ISADevice *dev)
ne2000_reset(s);
s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->c.macaddr.a);
return 0;
}
-static ISADeviceInfo ne2000_isa_info = {
- .qdev.name = "ne2k_isa",
- .qdev.size = sizeof(ISANE2000State),
- .init = isa_ne2000_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", ISANE2000State, iobase, 0x300),
- DEFINE_PROP_UINT32("irq", ISANE2000State, isairq, 9),
- DEFINE_NIC_PROPERTIES(ISANE2000State, ne2000.c),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property ne2000_isa_properties[] = {
+ DEFINE_PROP_HEX32("iobase", ISANE2000State, iobase, 0x300),
+ DEFINE_PROP_UINT32("irq", ISANE2000State, isairq, 9),
+ DEFINE_NIC_PROPERTIES(ISANE2000State, ne2000.c),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = isa_ne2000_initfn;
+ dc->props = ne2000_isa_properties;
+}
+
+static TypeInfo ne2000_isa_info = {
+ .name = "ne2k_isa",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISANE2000State),
+ .class_init = isa_ne2000_class_initfn,
};
static void ne2000_isa_register_devices(void)
{
- isa_qdev_register(&ne2000_isa_info);
+ type_register_static(&ne2000_isa_info);
}
device_init(ne2000_isa_register_devices)
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 62e082f8a9..080811ec4d 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -760,7 +760,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
ne2000_reset(s);
s->nic = qemu_new_nic(&net_ne2000_info, &s->c,
- pci_dev->qdev.info->name, pci_dev->qdev.id, s);
+ object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->c.macaddr.a);
if (!pci_dev->qdev.hotplugged) {
@@ -786,24 +786,35 @@ static int pci_ne2000_exit(PCIDevice *pci_dev)
return 0;
}
-static PCIDeviceInfo ne2000_info = {
- .qdev.name = "ne2k_pci",
- .qdev.size = sizeof(PCINE2000State),
- .qdev.vmsd = &vmstate_pci_ne2000,
- .init = pci_ne2000_init,
- .exit = pci_ne2000_exit,
- .vendor_id = PCI_VENDOR_ID_REALTEK,
- .device_id = PCI_DEVICE_ID_REALTEK_8029,
- .class_id = PCI_CLASS_NETWORK_ETHERNET,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ne2000_properties[] = {
+ DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ne2000_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_ne2000_init;
+ k->exit = pci_ne2000_exit;
+ k->vendor_id = PCI_VENDOR_ID_REALTEK;
+ k->device_id = PCI_DEVICE_ID_REALTEK_8029;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ dc->vmsd = &vmstate_pci_ne2000;
+ dc->props = ne2000_properties;
+}
+
+static TypeInfo ne2000_info = {
+ .name = "ne2k_pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCINE2000State),
+ .class_init = ne2000_class_init,
};
static void ne2000_register_devices(void)
{
- pci_qdev_register(&ne2000_info);
+ type_register_static(&ne2000_info);
}
device_init(ne2000_register_devices)
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 29147be8b8..9a9a8e183f 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -731,40 +731,62 @@ static int omap2_gpio_init(SysBusDevice *dev)
* translation.)
*/
-static SysBusDeviceInfo omap_gpio_info = {
- .init = omap_gpio_init,
- .qdev.name = "omap-gpio",
- .qdev.size = sizeof(struct omap_gpif_s),
- .qdev.reset = omap_gpif_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
- DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property omap_gpio_properties[] = {
+ DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
+ DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo omap2_gpio_info = {
- .init = omap2_gpio_init,
- .qdev.name = "omap2-gpio",
- .qdev.size = sizeof(struct omap2_gpif_s),
- .qdev.reset = omap2_gpif_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
- DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
- DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
- DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
- DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
- DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
- DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
- DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
- DEFINE_PROP_END_OF_LIST()
- }
+static void omap_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = omap_gpio_init;
+ dc->reset = omap_gpif_reset;
+ dc->props = omap_gpio_properties;
+}
+
+static TypeInfo omap_gpio_info = {
+ .name = "omap-gpio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct omap_gpif_s),
+ .class_init = omap_gpio_class_init,
+};
+
+static Property omap2_gpio_properties[] = {
+ DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
+ DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
+ DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
+ DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
+ DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
+ DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
+ DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
+ DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void omap2_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = omap2_gpio_init;
+ dc->reset = omap2_gpif_reset;
+ dc->props = omap2_gpio_properties;
+}
+
+static TypeInfo omap2_gpio_info = {
+ .name = "omap2-gpio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct omap2_gpif_s),
+ .class_init = omap2_gpio_class_init,
};
static void omap_gpio_register_device(void)
{
- sysbus_register_withprop(&omap_gpio_info);
- sysbus_register_withprop(&omap2_gpio_info);
+ type_register_static(&omap_gpio_info);
+ type_register_static(&omap2_gpio_info);
}
device_init(omap_gpio_register_device)
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index fc53ec71fb..5aa98a8fdb 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -373,16 +373,27 @@ static int omap_intc_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo omap_intc_info = {
- .init = omap_intc_init,
- .qdev.name = "omap-intc",
- .qdev.size = sizeof(struct omap_intr_handler_s),
- .qdev.reset = omap_inth_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
- DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property omap_intc_properties[] = {
+ DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
+ DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void omap_intc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = omap_intc_init;
+ dc->reset = omap_inth_reset;
+ dc->props = omap_intc_properties;
+}
+
+static TypeInfo omap_intc_info = {
+ .name = "omap-intc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct omap_intr_handler_s),
+ .class_init = omap_intc_class_init,
};
static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr,
@@ -604,24 +615,35 @@ static int omap2_intc_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo omap2_intc_info = {
- .init = omap2_intc_init,
- .qdev.name = "omap2-intc",
- .qdev.size = sizeof(struct omap_intr_handler_s),
- .qdev.reset = omap_inth_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
- revision, 0x21),
- DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk),
- DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property omap2_intc_properties[] = {
+ DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
+ revision, 0x21),
+ DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk),
+ DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void omap2_intc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = omap2_intc_init;
+ dc->reset = omap_inth_reset;
+ dc->props = omap2_intc_properties;
+}
+
+static TypeInfo omap2_intc_info = {
+ .name = "omap2-intc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct omap_intr_handler_s),
+ .class_init = omap2_intc_class_init,
};
static void omap_intc_register_device(void)
{
- sysbus_register_withprop(&omap_intc_info);
- sysbus_register_withprop(&omap2_intc_info);
+ type_register_static(&omap_intc_info);
+ type_register_static(&omap2_intc_info);
}
device_init(omap_intc_register_device)
diff --git a/hw/onenand.c b/hw/onenand.c
index 33c9718629..8744b04db3 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -802,24 +802,35 @@ static int onenand_initfn(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo onenand_info = {
- .init = onenand_initfn,
- .qdev.name = "onenand",
- .qdev.size = sizeof(OneNANDState),
- .qdev.reset = onenand_system_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
- DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
- DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
- DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
- DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
- DEFINE_PROP_END_OF_LIST()
- }
+static Property onenand_properties[] = {
+ DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
+ DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
+ DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
+ DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
+ DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void onenand_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = onenand_initfn;
+ dc->reset = onenand_system_reset;
+ dc->props = onenand_properties;
+}
+
+static TypeInfo onenand_info = {
+ .name = "onenand",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OneNANDState),
+ .class_init = onenand_class_init,
};
static void onenand_register_device(void)
{
- sysbus_register_withprop(&onenand_info);
+ type_register_static(&onenand_info);
}
void *onenand_raw_otp(DeviceState *onenand_device)
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index f7cc1b403b..09f2757df3 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -717,7 +717,7 @@ static int sysbus_open_eth_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->nic = qemu_new_nic(&net_open_eth_info, &s->conf,
- s->dev.qdev.info->name, s->dev.qdev.id, s);
+ object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
return 0;
}
@@ -727,21 +727,32 @@ static void qdev_open_eth_reset(DeviceState *dev)
open_eth_reset(d);
}
-static SysBusDeviceInfo open_eth_info = {
- .qdev.name = "open_eth",
- .qdev.desc = "Opencores 10/100 Mbit Ethernet",
- .qdev.size = sizeof(OpenEthState),
- .qdev.reset = qdev_open_eth_reset,
- .init = sysbus_open_eth_init,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(OpenEthState, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property open_eth_properties[] = {
+ DEFINE_NIC_PROPERTIES(OpenEthState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void open_eth_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sysbus_open_eth_init;
+ dc->desc = "Opencores 10/100 Mbit Ethernet";
+ dc->reset = qdev_open_eth_reset;
+ dc->props = open_eth_properties;
+}
+
+static TypeInfo open_eth_info = {
+ .name = "open_eth",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OpenEthState),
+ .class_init = open_eth_class_init,
};
static void open_eth_register_devices(void)
{
- sysbus_register_withprop(&open_eth_info);
+ type_register_static(&open_eth_info);
}
device_init(open_eth_register_devices)
diff --git a/hw/openpic.c b/hw/openpic.c
index 22fc275b62..280b7a9bbb 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1181,41 +1181,17 @@ static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
}
-qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
+qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
qemu_irq **irqs, qemu_irq irq_out)
{
openpic_t *opp;
- uint8_t *pci_conf;
int i, m;
/* XXX: for now, only one CPU is supported */
if (nb_cpus != 1)
return NULL;
- if (bus) {
- opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
- -1, NULL, NULL);
- pci_conf = opp->pci_dev.config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
- pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
- pci_conf[0x3d] = 0x00; // no interrupt pin
-
- memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
-#if 0 // Don't implement ISU for now
- opp_io_memory = cpu_register_io_memory(openpic_src_read,
- openpic_src_write, NULL
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
- opp_io_memory);
-#endif
-
- /* Register I/O spaces */
- pci_register_bar(&opp->pci_dev, 0,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &opp->mem);
- } else {
- opp = g_malloc0(sizeof(openpic_t));
- memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
- }
+ opp = g_malloc0(sizeof(openpic_t));
+ memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
// isu_base &= 0xFFFC0000;
opp->nb_cpus = nb_cpus;
diff --git a/hw/openpic.h b/hw/openpic.h
index 715f0847bf..855603026b 100644
--- a/hw/openpic.h
+++ b/hw/openpic.h
@@ -11,7 +11,7 @@ enum {
OPENPIC_OUTPUT_NB,
};
-qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
+qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
qemu_irq **irqs, qemu_irq irq_out);
qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
int nb_cpus, qemu_irq **irqs, qemu_irq irq_out);
diff --git a/hw/parallel.c b/hw/parallel.c
index c4c5dbee5b..484d727927 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -583,22 +583,32 @@ bool parallel_mm_init(MemoryRegion *address_space,
return true;
}
-static ISADeviceInfo parallel_isa_info = {
- .qdev.name = "isa-parallel",
- .qdev.size = sizeof(ISAParallelState),
- .init = parallel_isa_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("index", ISAParallelState, index, -1),
- DEFINE_PROP_HEX32("iobase", ISAParallelState, iobase, -1),
- DEFINE_PROP_UINT32("irq", ISAParallelState, isairq, 7),
- DEFINE_PROP_CHR("chardev", ISAParallelState, state.chr),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property parallel_isa_properties[] = {
+ DEFINE_PROP_UINT32("index", ISAParallelState, index, -1),
+ DEFINE_PROP_HEX32("iobase", ISAParallelState, iobase, -1),
+ DEFINE_PROP_UINT32("irq", ISAParallelState, isairq, 7),
+ DEFINE_PROP_CHR("chardev", ISAParallelState, state.chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = parallel_isa_initfn;
+ dc->props = parallel_isa_properties;
+}
+
+static TypeInfo parallel_isa_info = {
+ .name = "isa-parallel",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISAParallelState),
+ .class_init = parallel_isa_class_initfn,
};
static void parallel_register_devices(void)
{
- isa_qdev_register(&parallel_isa_info);
+ type_register_static(&parallel_isa_info);
}
device_init(parallel_register_devices)
diff --git a/hw/pc.c b/hw/pc.c
index 85304cf115..7f3aa65d20 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -36,9 +36,10 @@
#include "elf.h"
#include "multiboot.h"
#include "mc146818rtc.h"
-#include "msix.h"
+#include "msi.h"
#include "sysbus.h"
#include "sysemu.h"
+#include "kvm.h"
#include "blockdev.h"
#include "ui/qemu-spice.h"
#include "memory.h"
@@ -496,18 +497,26 @@ static int port92_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo port92_info = {
- .qdev.name = "port92",
- .qdev.size = sizeof(Port92State),
- .qdev.vmsd = &vmstate_port92_isa,
- .qdev.no_user = 1,
- .qdev.reset = port92_reset,
- .init = port92_initfn,
+static void port92_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = port92_initfn;
+ dc->no_user = 1;
+ dc->reset = port92_reset;
+ dc->vmsd = &vmstate_port92_isa;
+}
+
+static TypeInfo port92_info = {
+ .name = "port92",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(Port92State),
+ .class_init = port92_class_initfn,
};
static void port92_register(void)
{
- isa_qdev_register(&port92_info);
+ type_register_static(&port92_info);
}
device_init(port92_register)
@@ -609,7 +618,7 @@ static void *bochs_bios_init(void)
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
acpi_tables_len);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_IRQ0_OVERRIDE, &irq0override, 1);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
smbios_table = smbios_get_table(&smbios_len);
if (smbios_table)
@@ -878,25 +887,30 @@ DeviceState *cpu_get_current_apic(void)
static DeviceState *apic_init(void *env, uint8_t apic_id)
{
DeviceState *dev;
- SysBusDevice *d;
static int apic_mapped;
- dev = qdev_create(NULL, "apic");
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ dev = qdev_create(NULL, "kvm-apic");
+ } else {
+ dev = qdev_create(NULL, "apic");
+ }
qdev_prop_set_uint8(dev, "id", apic_id);
qdev_prop_set_ptr(dev, "cpu_env", env);
qdev_init_nofail(dev);
- d = sysbus_from_qdev(dev);
/* XXX: mapping more APICs at the same memory location */
if (apic_mapped == 0) {
/* NOTE: the APIC is directly connected to the CPU - it is not
on the global memory bus. */
/* XXX: what if the base changes? */
- sysbus_mmio_map(d, 0, MSI_ADDR_BASE);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, MSI_ADDR_BASE);
apic_mapped = 1;
}
- msix_supported = 1;
+ /* KVM does not support MSI yet. */
+ if (!kvm_enabled() || !kvm_irqchip_in_kernel()) {
+ msi_supported = true;
+ }
return dev;
}
@@ -1080,16 +1094,11 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
if (pci_bus) {
dev = pci_cirrus_vga_init(pci_bus);
} else {
- dev = isa_cirrus_vga_init(get_system_memory());
+ dev = &isa_create_simple(isa_bus, "isa-cirrus-vga")->qdev;
}
} else if (vmsvga_enabled) {
if (pci_bus) {
dev = pci_vmsvga_init(pci_bus);
- if (!dev) {
- fprintf(stderr, "Warning: vmware_vga not available,"
- " using standard VGA instead\n");
- dev = pci_vga_init(pci_bus);
- }
} else {
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
}
diff --git a/hw/pc.h b/hw/pc.h
index 13e41f101e..c666ec9827 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -62,11 +62,11 @@ bool parallel_mm_init(MemoryRegion *address_space,
/* i8259.c */
-typedef struct PicState PicState;
-extern PicState *isa_pic;
+extern DeviceState *isa_pic;
qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
-int pic_read_irq(PicState *s);
-int pic_get_output(PicState *s);
+qemu_irq *kvm_i8259_init(ISABus *bus);
+int pic_read_irq(DeviceState *d);
+int pic_get_output(DeviceState *d);
void pic_info(Monitor *mon);
void irq_info(Monitor *mon);
@@ -226,7 +226,6 @@ int isa_vga_mm_init(target_phys_addr_t vram_base,
/* cirrus_vga.c */
DeviceState *pci_cirrus_vga_init(PCIBus *bus);
-DeviceState *isa_cirrus_vga_init(MemoryRegion *address_space);
/* ne2000.c */
static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 3aea3cc9de..c06f1b544e 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -34,7 +34,7 @@
#include "boards.h"
#include "ide.h"
#include "kvm.h"
-#include "kvmclock.h"
+#include "kvm/clock.h"
#include "sysemu.h"
#include "sysbus.h"
#include "arch_init.h"
@@ -53,13 +53,62 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+static void kvm_piix3_setup_irq_routing(bool pci_enabled)
+{
+#ifdef CONFIG_KVM
+ KVMState *s = kvm_state;
+ int ret, i;
+
+ if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
+ for (i = 0; i < 8; ++i) {
+ if (i == 2) {
+ continue;
+ }
+ kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
+ }
+ for (i = 8; i < 16; ++i) {
+ kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
+ }
+ if (pci_enabled) {
+ for (i = 0; i < 24; ++i) {
+ if (i == 0) {
+ kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
+ } else if (i != 2) {
+ kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, i);
+ }
+ }
+ }
+ ret = kvm_irqchip_commit_routes(s);
+ if (ret < 0) {
+ hw_error("KVM IRQ routing setup failed");
+ }
+ }
+#endif /* CONFIG_KVM */
+}
+
+static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
+{
+ GSIState *s = opaque;
+
+ if (n < ISA_NUM_IRQS) {
+ /* Kernel will forward to both PIC and IOAPIC */
+ qemu_set_irq(s->i8259_irq[n], level);
+ } else {
+ qemu_set_irq(s->ioapic_irq[n], level);
+ }
+}
+
static void ioapic_init(GSIState *gsi_state)
{
DeviceState *dev;
SysBusDevice *d;
unsigned int i;
- dev = qdev_create(NULL, "ioapic");
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ dev = qdev_create(NULL, "kvm-ioapic");
+ } else {
+ dev = qdev_create(NULL, "ioapic");
+ }
qdev_init_nofail(dev);
d = sysbus_from_qdev(dev);
sysbus_mmio_map(d, 0, 0xfec00000);
@@ -134,7 +183,13 @@ static void pc_init1(MemoryRegion *system_memory,
}
gsi_state = g_malloc0(sizeof(*gsi_state));
- gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ kvm_piix3_setup_irq_routing(pci_enabled);
+ gsi = qemu_allocate_irqs(kvm_piix3_gsi_handler, gsi_state,
+ GSI_NUM_PINS);
+ } else {
+ gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+ }
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
@@ -154,11 +209,13 @@ static void pc_init1(MemoryRegion *system_memory,
}
isa_bus_irqs(isa_bus, gsi);
- if (!xen_enabled()) {
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ i8259 = kvm_i8259_init(isa_bus);
+ } else if (xen_enabled()) {
+ i8259 = xen_interrupt_controller_init();
+ } else {
cpu_irq = pc_allocate_cpu_irq();
i8259 = i8259_init(isa_bus, cpu_irq[0]);
- } else {
- i8259 = xen_interrupt_controller_init();
}
for (i = 0; i < ISA_NUM_IRQS; i++) {
@@ -172,7 +229,7 @@ static void pc_init1(MemoryRegion *system_memory,
dev = pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
if (dev) {
- qdev_property_add_child(qdev_get_root(), "vga", dev, NULL);
+ object_property_add_child(object_get_root(), "vga", OBJECT(dev), NULL);
}
if (xen_enabled()) {
@@ -210,8 +267,8 @@ static void pc_init1(MemoryRegion *system_memory,
* For now, let's "fix" this by making judicious use of paths. This
* is not generally the right way to do this.
*/
- qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
- "rtc", (DeviceState *)rtc_state, NULL);
+ object_property_add_child(object_resolve_path("/i440fx/piix3", NULL),
+ "rtc", (Object *)rtc_state, NULL);
} else {
for(i = 0; i < MAX_IDE_BUS; i++) {
ISADevice *dev;
diff --git a/hw/pci.c b/hw/pci.c
index c3082bc7c6..5f4f80ed10 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -89,7 +89,6 @@ static const VMStateDescription vmstate_pcibus = {
VMSTATE_END_OF_LIST()
}
};
-
static int pci_bar(PCIDevice *d, int reg)
{
uint8_t type;
@@ -159,11 +158,8 @@ void pci_device_deassert_intx(PCIDevice *dev)
void pci_device_reset(PCIDevice *dev)
{
int r;
- /* TODO: call the below unconditionally once all pci devices
- * are qdevified */
- if (dev->qdev.info) {
- qdev_reset_all(&dev->qdev);
- }
+
+ qdev_reset_all(&dev->qdev);
dev->irq_state = 0;
pci_update_irq_status(dev);
@@ -733,11 +729,11 @@ static void pci_config_free(PCIDevice *pci_dev)
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
- const char *name, int devfn,
- const PCIDeviceInfo *info)
+ const char *name, int devfn)
{
- PCIConfigReadFunc *config_read = info->config_read;
- PCIConfigWriteFunc *config_write = info->config_write;
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+ PCIConfigReadFunc *config_read = pc->config_read;
+ PCIConfigWriteFunc *config_write = pc->config_write;
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
@@ -759,29 +755,29 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
- pci_config_set_vendor_id(pci_dev->config, info->vendor_id);
- pci_config_set_device_id(pci_dev->config, info->device_id);
- pci_config_set_revision(pci_dev->config, info->revision);
- pci_config_set_class(pci_dev->config, info->class_id);
+ pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);
+ pci_config_set_device_id(pci_dev->config, pc->device_id);
+ pci_config_set_revision(pci_dev->config, pc->revision);
+ pci_config_set_class(pci_dev->config, pc->class_id);
- if (!info->is_bridge) {
- if (info->subsystem_vendor_id || info->subsystem_id) {
+ if (!pc->is_bridge) {
+ if (pc->subsystem_vendor_id || pc->subsystem_id) {
pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
- info->subsystem_vendor_id);
+ pc->subsystem_vendor_id);
pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
- info->subsystem_id);
+ pc->subsystem_id);
} else {
pci_set_default_subsystem_id(pci_dev);
}
} else {
/* subsystem_vendor_id/subsystem_id are only for header type 0 */
- assert(!info->subsystem_vendor_id);
- assert(!info->subsystem_id);
+ assert(!pc->subsystem_vendor_id);
+ assert(!pc->subsystem_id);
}
pci_init_cmask(pci_dev);
pci_init_wmask(pci_dev);
pci_init_w1cmask(pci_dev);
- if (info->is_bridge) {
+ if (pc->is_bridge) {
pci_init_wmask_bridge(pci_dev);
}
if (pci_init_multifunction(bus, pci_dev)) {
@@ -808,26 +804,6 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
pci_config_free(pci_dev);
}
-/* TODO: obsolete. eliminate this once all pci devices are qdevifed. */
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
- int instance_size, int devfn,
- PCIConfigReadFunc *config_read,
- PCIConfigWriteFunc *config_write)
-{
- PCIDevice *pci_dev;
- PCIDeviceInfo info = {
- .config_read = config_read,
- .config_write = config_write,
- };
-
- pci_dev = g_malloc0(instance_size);
- pci_dev = do_pci_register_device(pci_dev, bus, name, devfn, &info);
- if (pci_dev == NULL) {
- hw_error("PCI: can't register device\n");
- }
- return pci_dev;
-}
-
static void pci_unregister_io_regions(PCIDevice *pci_dev)
{
PCIIORegion *r;
@@ -843,12 +819,12 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
static int pci_unregister_device(DeviceState *dev)
{
- PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
- PCIDeviceInfo *info = DO_UPCAST(PCIDeviceInfo, qdev, dev->info);
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
int ret = 0;
- if (info->exit)
- ret = info->exit(pci_dev);
+ if (pc->exit)
+ ret = pc->exit(pci_dev);
if (ret)
return ret;
@@ -1477,31 +1453,32 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
return bus->devices[devfn];
}
-static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int pci_qdev_init(DeviceState *qdev)
{
PCIDevice *pci_dev = (PCIDevice *)qdev;
- PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
PCIBus *bus;
int rc;
bool is_default_rom;
/* initialize cap_present for pci_is_express() and pci_config_size() */
- if (info->is_express) {
+ if (pc->is_express) {
pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
}
bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
- pci_dev = do_pci_register_device(pci_dev, bus, base->name,
- pci_dev->devfn, info);
+ pci_dev = do_pci_register_device(pci_dev, bus,
+ object_get_typename(OBJECT(qdev)),
+ pci_dev->devfn);
if (pci_dev == NULL)
return -1;
- if (qdev->hotplugged && info->no_hotplug) {
- qerror_report(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
+ if (qdev->hotplugged && pc->no_hotplug) {
+ qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev)));
do_pci_unregister_device(pci_dev);
return -1;
}
- if (info->init) {
- rc = info->init(pci_dev);
+ if (pc->init) {
+ rc = pc->init(pci_dev);
if (rc != 0) {
do_pci_unregister_device(pci_dev);
return rc;
@@ -1510,8 +1487,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
/* rom loading */
is_default_rom = false;
- if (pci_dev->romfile == NULL && info->romfile != NULL) {
- pci_dev->romfile = g_strdup(info->romfile);
+ if (pci_dev->romfile == NULL && pc->romfile != NULL) {
+ pci_dev->romfile = g_strdup(pc->romfile);
is_default_rom = true;
}
pci_add_option_rom(pci_dev, is_default_rom);
@@ -1533,34 +1510,18 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
static int pci_unplug_device(DeviceState *qdev)
{
- PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
- PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
+ PCIDevice *dev = PCI_DEVICE(qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
- if (info->no_hotplug) {
- qerror_report(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
+ if (pc->no_hotplug) {
+ qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
return -1;
}
+ object_unparent(OBJECT(dev));
return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
PCI_HOTPLUG_DISABLED);
}
-void pci_qdev_register(PCIDeviceInfo *info)
-{
- info->qdev.init = pci_qdev_init;
- info->qdev.unplug = pci_unplug_device;
- info->qdev.exit = pci_unregister_device;
- info->qdev.bus_info = &pci_bus_info;
- qdev_register(&info->qdev);
-}
-
-void pci_qdev_register_many(PCIDeviceInfo *info)
-{
- while (info->qdev.name) {
- pci_qdev_register(info);
- info++;
- }
-}
-
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
const char *name)
{
@@ -1569,22 +1530,7 @@ PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
dev = qdev_create(&bus->qbus, name);
qdev_prop_set_uint32(dev, "addr", devfn);
qdev_prop_set_bit(dev, "multifunction", multifunction);
- return DO_UPCAST(PCIDevice, qdev, dev);
-}
-
-PCIDevice *pci_try_create_multifunction(PCIBus *bus, int devfn,
- bool multifunction,
- const char *name)
-{
- DeviceState *dev;
-
- dev = qdev_try_create(&bus->qbus, name);
- if (!dev) {
- return NULL;
- }
- qdev_prop_set_uint32(dev, "addr", devfn);
- qdev_prop_set_bit(dev, "multifunction", multifunction);
- return DO_UPCAST(PCIDevice, qdev, dev);
+ return PCI_DEVICE(dev);
}
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
@@ -1606,11 +1552,6 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
return pci_create_simple_multifunction(bus, devfn, false, name);
}
-PCIDevice *pci_try_create(PCIBus *bus, int devfn, const char *name)
-{
- return pci_try_create_multifunction(bus, devfn, false, name);
-}
-
static int pci_find_space(PCIDevice *pdev, uint8_t size)
{
int config_size = pci_config_size(pdev);
@@ -1724,6 +1665,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
char *path;
void *ptr;
char name[32];
+ const VMStateDescription *vmsd;
if (!pdev->romfile)
return 0;
@@ -1760,10 +1702,13 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
size = 1 << qemu_fls(size);
}
- if (pdev->qdev.info->vmsd)
- snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->vmsd->name);
- else
- snprintf(name, sizeof(name), "%s.rom", pdev->qdev.info->name);
+ vmsd = qdev_get_vmsd(DEVICE(pdev));
+
+ if (vmsd) {
+ snprintf(name, sizeof(name), "%s.rom", vmsd->name);
+ } else {
+ snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev)));
+ }
pdev->has_rom = true;
memory_region_init_ram(&pdev->rom, name, size);
vmstate_register_ram(&pdev->rom, &pdev->qdev);
@@ -2004,9 +1949,8 @@ static int pci_qdev_find_recursive(PCIBus *bus,
}
/* roughly check if given qdev is pci device */
- if (qdev->info->init == &pci_qdev_init &&
- qdev->parent_bus->info == &pci_bus_info) {
- *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+ if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) {
+ *pdev = PCI_DEVICE(qdev);
return 0;
}
return -EINVAL;
@@ -2040,3 +1984,28 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev)
{
return dev->bus->address_space_io;
}
+
+static void pci_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = pci_qdev_init;
+ k->unplug = pci_unplug_device;
+ k->exit = pci_unregister_device;
+ k->bus_info = &pci_bus_info;
+}
+
+static TypeInfo pci_device_type_info = {
+ .name = TYPE_PCI_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .abstract = true,
+ .class_size = sizeof(PCIDeviceClass),
+ .class_init = pci_device_class_init,
+};
+
+static void pci_register_devices(void)
+{
+ type_register_static(&pci_device_type_info);
+}
+
+device_init(pci_register_devices);
diff --git a/hw/pci.h b/hw/pci.h
index 0d2cff6fec..33b0b184ea 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -127,6 +127,46 @@ enum {
QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
};
+#define TYPE_PCI_DEVICE "pci-device"
+#define PCI_DEVICE(obj) \
+ OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
+
+typedef struct PCIDeviceClass {
+ DeviceClass parent_class;
+
+ int (*init)(PCIDevice *dev);
+ PCIUnregisterFunc *exit;
+ PCIConfigReadFunc *config_read;
+ PCIConfigWriteFunc *config_write;
+
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint8_t revision;
+ uint16_t class_id;
+ uint16_t subsystem_vendor_id; /* only for header type = 0 */
+ uint16_t subsystem_id; /* only for header type = 0 */
+
+ /*
+ * pci-to-pci bridge or normal device.
+ * This doesn't mean pci host switch.
+ * When card bus bridge is supported, this would be enhanced.
+ */
+ int is_bridge;
+
+ /* pcie stuff */
+ int is_express; /* is this device pci express? */
+
+ /* device isn't hot-pluggable */
+ int no_hotplug;
+
+ /* rom bar */
+ const char *romfile;
+} PCIDeviceClass;
+
struct PCIDevice {
DeviceState qdev;
/* PCI config space */
@@ -196,11 +236,6 @@ struct PCIDevice {
uint32_t rom_bar;
};
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
- int instance_size, int devfn,
- PCIConfigReadFunc *config_read,
- PCIConfigWriteFunc *config_write);
-
void pci_register_bar(PCIDevice *pci_dev, int region_num,
uint8_t attr, MemoryRegion *memory);
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
@@ -429,52 +464,13 @@ pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
return val & mask;
}
-typedef int (*pci_qdev_initfn)(PCIDevice *dev);
-typedef struct {
- DeviceInfo qdev;
- pci_qdev_initfn init;
- PCIUnregisterFunc *exit;
- PCIConfigReadFunc *config_read;
- PCIConfigWriteFunc *config_write;
-
- uint16_t vendor_id;
- uint16_t device_id;
- uint8_t revision;
- uint16_t class_id;
- uint16_t subsystem_vendor_id; /* only for header type = 0 */
- uint16_t subsystem_id; /* only for header type = 0 */
-
- /*
- * pci-to-pci bridge or normal device.
- * This doesn't mean pci host switch.
- * When card bus bridge is supported, this would be enhanced.
- */
- int is_bridge;
-
- /* pcie stuff */
- int is_express; /* is this device pci express? */
-
- /* device isn't hot-pluggable */
- int no_hotplug;
-
- /* rom bar */
- const char *romfile;
-} PCIDeviceInfo;
-
-void pci_qdev_register(PCIDeviceInfo *info);
-void pci_qdev_register_many(PCIDeviceInfo *info);
-
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
const char *name);
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
bool multifunction,
const char *name);
-PCIDevice *pci_try_create_multifunction(PCIBus *bus, int devfn,
- bool multifunction,
- const char *name);
PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
-PCIDevice *pci_try_create(PCIBus *bus, int devfn, const char *name);
static inline int pci_is_express(const PCIDevice *d)
{
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index 650d1650c5..1ed43394de 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -294,7 +294,7 @@ void pci_bridge_reset_reg(PCIDevice *dev)
/* default reset function for PCI-to-PCI bridge */
void pci_bridge_reset(DeviceState *qdev)
{
- PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *dev = PCI_DEVICE(qdev);
pci_bridge_reset_reg(dev);
}
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 83f38934ec..e8235a7d05 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -98,6 +98,7 @@
#define PCI_DEVICE_ID_MPC8533E 0x0030
#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_82378 0x0484
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
#define PCI_DEVICE_ID_INTEL_82801D 0x24CD
@@ -120,3 +121,6 @@
#define PCI_VENDOR_ID_XEN 0x5853
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
+
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_DEVICE_ID_NEC_UPD720200 0x0194
diff --git a/hw/pcie.c b/hw/pcie.c
index 5c9eb2f0ac..7c92f193e7 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -203,7 +203,7 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
static int pcie_cap_slot_hotplug(DeviceState *qdev,
PCIDevice *pci_dev, PCIHotplugState state)
{
- PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *d = PCI_DEVICE(qdev);
uint8_t *exp_cap = d->config + d->exp.exp_cap;
uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 06b40c540c..b4c53bed6c 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -497,16 +497,24 @@ static int i8042_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo i8042_info = {
- .qdev.name = "i8042",
- .qdev.size = sizeof(ISAKBDState),
- .qdev.vmsd = &vmstate_kbd_isa,
- .qdev.no_user = 1,
- .init = i8042_initfn,
+static void i8042_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = i8042_initfn;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_kbd_isa;
+}
+
+static TypeInfo i8042_info = {
+ .name = "i8042",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISAKBDState),
+ .class_init = i8042_class_initfn,
};
static void i8042_register(void)
{
- isa_qdev_register(&i8042_info);
+ type_register_static(&i8042_info);
}
device_init(i8042_register)
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 4e164da3ac..439f32caae 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -348,26 +348,37 @@ static void pci_reset(DeviceState *dev)
pcnet_h_reset(&d->state);
}
-static PCIDeviceInfo pcnet_info = {
- .qdev.name = "pcnet",
- .qdev.size = sizeof(PCIPCNetState),
- .qdev.reset = pci_reset,
- .qdev.vmsd = &vmstate_pci_pcnet,
- .init = pci_pcnet_init,
- .exit = pci_pcnet_uninit,
- .vendor_id = PCI_VENDOR_ID_AMD,
- .device_id = PCI_DEVICE_ID_AMD_LANCE,
- .revision = 0x10,
- .class_id = PCI_CLASS_NETWORK_ETHERNET,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property pcnet_properties[] = {
+ DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pcnet_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_pcnet_init;
+ k->exit = pci_pcnet_uninit;
+ k->vendor_id = PCI_VENDOR_ID_AMD;
+ k->device_id = PCI_DEVICE_ID_AMD_LANCE;
+ k->revision = 0x10;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ dc->reset = pci_reset;
+ dc->vmsd = &vmstate_pci_pcnet;
+ dc->props = pcnet_properties;
+}
+
+static TypeInfo pcnet_info = {
+ .name = "pcnet",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIPCNetState),
+ .class_init = pcnet_class_init,
};
static void pci_pcnet_register_devices(void)
{
- pci_qdev_register(&pcnet_info);
+ type_register_static(&pcnet_info);
}
device_init(pci_pcnet_register_devices)
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 306dc6ed7e..c53f06ef3b 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -688,7 +688,6 @@ static void pcnet_s_reset(PCNetState *s)
printf("pcnet_s_reset\n");
#endif
- s->lnkst = 0x40;
s->rdra = 0;
s->tdra = 0;
s->rap = 0;
@@ -1719,7 +1718,7 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
- s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
+ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
@@ -1751,5 +1750,7 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
}
*(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
+ s->lnkst = 0x40; /* initial link state: up */
+
return 0;
}
diff --git a/hw/piix4.c b/hw/piix4.c
index 51af459073..4e7a2370cd 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -102,25 +102,30 @@ int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
return d->devfn;
}
-static PCIDeviceInfo piix4_info[] = {
- {
- .qdev.name = "PIIX4",
- .qdev.desc = "ISA bridge",
- .qdev.size = sizeof(PIIX4State),
- .qdev.vmsd = &vmstate_piix4,
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = piix4_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371AB_0, // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
- .class_id = PCI_CLASS_BRIDGE_ISA,
- },{
- /* end of list */
- }
+static void piix4_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = piix4_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+ dc->desc = "ISA bridge";
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_piix4;
+}
+
+static TypeInfo piix4_info = {
+ .name = "PIIX4",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX4State),
+ .class_init = piix4_class_init,
};
static void piix4_register(void)
{
- pci_qdev_register_many(piix4_info);
+ type_register_static(&piix4_info);
}
device_init(piix4_register);
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 3652522e58..190642733f 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -277,7 +277,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
address_space_io, 0);
s->bus = b;
qdev_init_nofail(dev);
- qdev_property_add_child(qdev_get_root(), "i440fx", dev, NULL);
+ object_property_add_child(object_get_root(), "i440fx", OBJECT(dev), NULL);
d = pci_create_simple(b, 0, device_name);
*pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
@@ -316,7 +316,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
PIIX_NUM_PIRQS);
}
- qdev_property_add_child(dev, "piix3", &piix3->dev.qdev, NULL);
+ object_property_add_child(OBJECT(dev), "piix3", OBJECT(piix3), NULL);
piix3->pic = pic;
*isa_bus = DO_UPCAST(ISABus, qbus,
qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
@@ -502,60 +502,98 @@ static int piix3_initfn(PCIDevice *dev)
return 0;
}
-static PCIDeviceInfo i440fx_info[] = {
- {
- .qdev.name = "i440FX",
- .qdev.desc = "Host bridge",
- .qdev.size = sizeof(PCII440FXState),
- .qdev.vmsd = &vmstate_i440fx,
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = i440fx_initfn,
- .config_write = i440fx_write_config,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82441,
- .revision = 0x02,
- .class_id = PCI_CLASS_BRIDGE_HOST,
- },{
- .qdev.name = "PIIX3",
- .qdev.desc = "ISA bridge",
- .qdev.size = sizeof(PIIX3State),
- .qdev.vmsd = &vmstate_piix3,
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = piix3_initfn,
- .config_write = piix3_write_config,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
- .class_id = PCI_CLASS_BRIDGE_ISA,
- },{
- .qdev.name = "PIIX3-xen",
- .qdev.desc = "ISA bridge",
- .qdev.size = sizeof(PIIX3State),
- .qdev.vmsd = &vmstate_piix3,
- .qdev.no_user = 1,
- .no_hotplug = 1,
- .init = piix3_initfn,
- .config_write = piix3_write_config_xen,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
- .class_id = PCI_CLASS_BRIDGE_ISA,
- },{
- /* end of list */
- }
+static void piix3_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ dc->desc = "ISA bridge";
+ dc->vmsd = &vmstate_piix3;
+ dc->no_user = 1,
+ k->no_hotplug = 1;
+ k->init = piix3_initfn;
+ k->config_write = piix3_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+}
+
+static TypeInfo piix3_info = {
+ .name = "PIIX3",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX3State),
+ .class_init = piix3_class_init,
+};
+
+static void piix3_xen_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ dc->desc = "ISA bridge";
+ dc->vmsd = &vmstate_piix3;
+ dc->no_user = 1;
+ k->no_hotplug = 1;
+ k->init = piix3_initfn;
+ k->config_write = piix3_write_config_xen;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+};
+
+static TypeInfo piix3_xen_info = {
+ .name = "PIIX3-xen",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX3State),
+ .class_init = piix3_xen_class_init,
};
-static SysBusDeviceInfo i440fx_pcihost_info = {
- .init = i440fx_pcihost_initfn,
- .qdev.name = "i440FX-pcihost",
- .qdev.fw_name = "pci",
- .qdev.size = sizeof(I440FXState),
- .qdev.no_user = 1,
+static void i440fx_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = i440fx_initfn;
+ k->config_write = i440fx_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82441;
+ k->revision = 0x02;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ dc->desc = "Host bridge";
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_i440fx;
+}
+
+static TypeInfo i440fx_info = {
+ .name = "i440FX",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCII440FXState),
+ .class_init = i440fx_class_init,
+};
+
+static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = i440fx_pcihost_initfn;
+ dc->fw_name = "pci";
+ dc->no_user = 1;
+}
+
+static TypeInfo i440fx_pcihost_info = {
+ .name = "i440FX-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(I440FXState),
+ .class_init = i440fx_pcihost_class_init,
};
static void i440fx_register(void)
{
- sysbus_register_withprop(&i440fx_pcihost_info);
- pci_qdev_register_many(i440fx_info);
+ type_register_static(&i440fx_info);
+ type_register_static(&piix3_info);
+ type_register_static(&piix3_xen_info);
+ type_register_static(&i440fx_pcihost_info);
}
device_init(i440fx_register);
diff --git a/hw/pl011.c b/hw/pl011.c
index 1b05d76a78..752cbf9725 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -264,7 +264,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
s->id = id;
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
s->read_trigger = 1;
s->ifl = 0x12;
@@ -278,22 +278,48 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
return 0;
}
-static int pl011_init_arm(SysBusDevice *dev)
+static int pl011_arm_init(SysBusDevice *dev)
{
return pl011_init(dev, pl011_id_arm);
}
-static int pl011_init_luminary(SysBusDevice *dev)
+static int pl011_luminary_init(SysBusDevice *dev)
{
return pl011_init(dev, pl011_id_luminary);
}
+static void pl011_arm_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pl011_arm_init;
+}
+
+static TypeInfo pl011_arm_info = {
+ .name = "pl011",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl011_state),
+ .class_init = pl011_arm_class_init,
+};
+
+static void pl011_luminary_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pl011_luminary_init;
+}
+
+static TypeInfo pl011_luminary_info = {
+ .name = "pl011_luminary",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl011_state),
+ .class_init = pl011_luminary_class_init,
+};
+
static void pl011_register_devices(void)
{
- sysbus_register_dev("pl011", sizeof(pl011_state),
- pl011_init_arm);
- sysbus_register_dev("pl011_luminary", sizeof(pl011_state),
- pl011_init_luminary);
+ type_register_static(&pl011_arm_info);
+ type_register_static(&pl011_luminary_info);
}
device_init(pl011_register_devices)
diff --git a/hw/pl022.c b/hw/pl022.c
index d43e4a29da..30bd3442bb 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -285,9 +285,23 @@ static int pl022_init(SysBusDevice *dev)
return 0;
}
+static void pl022_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pl022_init;
+}
+
+static TypeInfo pl022_info = {
+ .name = "pl022",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl022_state),
+ .class_init = pl022_class_init,
+};
+
static void pl022_register_devices(void)
{
- sysbus_register_dev("pl022", sizeof(pl022_state), pl022_init);
+ type_register_static(&pl022_info);
}
device_init(pl022_register_devices)
diff --git a/hw/pl031.c b/hw/pl031.c
index 2fb0c8ef24..8416a609ef 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -213,17 +213,26 @@ static int pl031_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo pl031_info = {
- .init = pl031_init,
- .qdev.name = "pl031",
- .qdev.size = sizeof(pl031_state),
- .qdev.vmsd = &vmstate_pl031,
- .qdev.no_user = 1,
+static void pl031_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl031_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl031;
+}
+
+static TypeInfo pl031_info = {
+ .name = "pl031",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl031_state),
+ .class_init = pl031_class_init,
};
static void pl031_register_devices(void)
{
- sysbus_register_withprop(&pl031_info);
+ type_register_static(&pl031_info);
}
device_init(pl031_register_devices)
diff --git a/hw/pl041.c b/hw/pl041.c
index 4585ccf9c0..6d99c9cbbc 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -613,24 +613,34 @@ static const VMStateDescription vmstate_pl041 = {
}
};
-static SysBusDeviceInfo pl041_device_info = {
- .init = pl041_init,
- .qdev.name = "pl041",
- .qdev.size = sizeof(pl041_state),
- .qdev.vmsd = &vmstate_pl041,
- .qdev.reset = pl041_device_reset,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- /* Non-compact FIFO depth property */
- DEFINE_PROP_UINT32("nc_fifo_depth", pl041_state,
- fifo_depth, DEFAULT_FIFO_DEPTH),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property pl041_device_properties[] = {
+ /* Non-compact FIFO depth property */
+ DEFINE_PROP_UINT32("nc_fifo_depth", pl041_state, fifo_depth, DEFAULT_FIFO_DEPTH),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pl041_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl041_init;
+ dc->no_user = 1;
+ dc->reset = pl041_device_reset;
+ dc->vmsd = &vmstate_pl041;
+ dc->props = pl041_device_properties;
+}
+
+static TypeInfo pl041_device_info = {
+ .name = "pl041",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl041_state),
+ .class_init = pl041_device_class_init,
};
static void pl041_register_device(void)
{
- sysbus_register_withprop(&pl041_device_info);
+ type_register_static(&pl041_device_info);
}
device_init(pl041_register_device)
diff --git a/hw/pl050.c b/hw/pl050.c
index 8182a1c82d..b0094ac9b3 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -157,24 +157,42 @@ static int pl050_init_mouse(SysBusDevice *dev)
return pl050_init(dev, 1);
}
-static SysBusDeviceInfo pl050_kbd_info = {
- .init = pl050_init_keyboard,
- .qdev.name = "pl050_keyboard",
- .qdev.size = sizeof(pl050_state),
- .qdev.vmsd = &vmstate_pl050,
+static void pl050_kbd_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl050_init_keyboard;
+ dc->vmsd = &vmstate_pl050;
+}
+
+static TypeInfo pl050_kbd_info = {
+ .name = "pl050_keyboard",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl050_state),
+ .class_init = pl050_kbd_class_init,
};
-static SysBusDeviceInfo pl050_mouse_info = {
- .init = pl050_init_mouse,
- .qdev.name = "pl050_mouse",
- .qdev.size = sizeof(pl050_state),
- .qdev.vmsd = &vmstate_pl050,
+static void pl050_mouse_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl050_init_mouse;
+ dc->vmsd = &vmstate_pl050;
+}
+
+static TypeInfo pl050_mouse_info = {
+ .name = "pl050_mouse",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl050_state),
+ .class_init = pl050_mouse_class_init,
};
static void pl050_register_devices(void)
{
- sysbus_register_withprop(&pl050_kbd_info);
- sysbus_register_withprop(&pl050_mouse_info);
+ type_register_static(&pl050_kbd_info);
+ type_register_static(&pl050_mouse_info);
}
device_init(pl050_register_devices)
diff --git a/hw/pl061.c b/hw/pl061.c
index f33ae84408..3136c99423 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -293,24 +293,42 @@ static int pl061_init_arm(SysBusDevice *dev)
return pl061_init(dev, pl061_id);
}
-static SysBusDeviceInfo pl061_info = {
- .init = pl061_init_arm,
- .qdev.name = "pl061",
- .qdev.size = sizeof(pl061_state),
- .qdev.vmsd = &vmstate_pl061,
+static void pl061_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl061_init_arm;
+ dc->vmsd = &vmstate_pl061;
+}
+
+static TypeInfo pl061_info = {
+ .name = "pl061",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl061_state),
+ .class_init = pl061_class_init,
};
-static SysBusDeviceInfo pl061_luminary_info = {
- .init = pl061_init_luminary,
- .qdev.name = "pl061_luminary",
- .qdev.size = sizeof(pl061_state),
- .qdev.vmsd = &vmstate_pl061,
+static void pl061_luminary_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl061_init_luminary;
+ dc->vmsd = &vmstate_pl061;
+}
+
+static TypeInfo pl061_luminary_info = {
+ .name = "pl061_luminary",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl061_state),
+ .class_init = pl061_luminary_class_init,
};
static void pl061_register_devices(void)
{
- sysbus_register_withprop(&pl061_info);
- sysbus_register_withprop(&pl061_luminary_info);
+ type_register_static(&pl061_info);
+ type_register_static(&pl061_luminary_info);
}
device_init(pl061_register_devices)
diff --git a/hw/pl080.c b/hw/pl080.c
index e001df92e0..4405d1823b 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -373,28 +373,46 @@ static int pl081_init(SysBusDevice *dev)
return pl08x_init(dev, 2);
}
-static SysBusDeviceInfo pl080_info = {
- .init = pl080_init,
- .qdev.name = "pl080",
- .qdev.size = sizeof(pl080_state),
- .qdev.vmsd = &vmstate_pl080,
- .qdev.no_user = 1,
+static void pl080_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl080_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl080;
+}
+
+static TypeInfo pl080_info = {
+ .name = "pl080",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl080_state),
+ .class_init = pl080_class_init,
};
-static SysBusDeviceInfo pl081_info = {
- .init = pl081_init,
- .qdev.name = "pl081",
- .qdev.size = sizeof(pl080_state),
- .qdev.vmsd = &vmstate_pl080,
- .qdev.no_user = 1,
+static void pl081_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl081_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl080;
+}
+
+static TypeInfo pl081_info = {
+ .name = "pl081",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl080_state),
+ .class_init = pl081_class_init,
};
/* The PL080 and PL081 are the same except for the number of channels
they implement (8 and 2 respectively). */
static void pl080_register_devices(void)
{
- sysbus_register_withprop(&pl080_info);
- sysbus_register_withprop(&pl081_info);
+ type_register_static(&pl080_info);
+ type_register_static(&pl081_info);
}
device_init(pl080_register_devices)
diff --git a/hw/pl110.c b/hw/pl110.c
index 0e1f415aeb..86e95a3ffd 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -469,35 +469,62 @@ static int pl111_init(SysBusDevice *dev)
return pl110_init(dev);
}
-static SysBusDeviceInfo pl110_info = {
- .init = pl110_init,
- .qdev.name = "pl110",
- .qdev.size = sizeof(pl110_state),
- .qdev.vmsd = &vmstate_pl110,
- .qdev.no_user = 1,
+static void pl110_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl110_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl110;
+}
+
+static TypeInfo pl110_info = {
+ .name = "pl110",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl110_state),
+ .class_init = pl110_class_init,
};
-static SysBusDeviceInfo pl110_versatile_info = {
- .init = pl110_versatile_init,
- .qdev.name = "pl110_versatile",
- .qdev.size = sizeof(pl110_state),
- .qdev.vmsd = &vmstate_pl110,
- .qdev.no_user = 1,
+static void pl110_versatile_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl110_versatile_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl110;
+}
+
+static TypeInfo pl110_versatile_info = {
+ .name = "pl110_versatile",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl110_state),
+ .class_init = pl110_versatile_class_init,
};
-static SysBusDeviceInfo pl111_info = {
- .init = pl111_init,
- .qdev.name = "pl111",
- .qdev.size = sizeof(pl110_state),
- .qdev.vmsd = &vmstate_pl110,
- .qdev.no_user = 1,
+static void pl111_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl111_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_pl110;
+}
+
+static TypeInfo pl111_info = {
+ .name = "pl111",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl110_state),
+ .class_init = pl111_class_init,
};
static void pl110_register_devices(void)
{
- sysbus_register_withprop(&pl110_info);
- sysbus_register_withprop(&pl110_versatile_info);
- sysbus_register_withprop(&pl111_info);
+ type_register_static(&pl110_info);
+ type_register_static(&pl110_versatile_info);
+ type_register_static(&pl111_info);
}
device_init(pl110_register_devices)
diff --git a/hw/pl181.c b/hw/pl181.c
index b79aa418fa..ae636e220e 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -487,18 +487,27 @@ static int pl181_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo pl181_info = {
- .init = pl181_init,
- .qdev.name = "pl181",
- .qdev.size = sizeof(pl181_state),
- .qdev.vmsd = &vmstate_pl181,
- .qdev.reset = pl181_reset,
- .qdev.no_user = 1,
+static void pl181_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *k = DEVICE_CLASS(klass);
+
+ sdc->init = pl181_init;
+ k->vmsd = &vmstate_pl181;
+ k->reset = pl181_reset;
+ k->no_user = 1;
+}
+
+static TypeInfo pl181_info = {
+ .name = "pl181",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl181_state),
+ .class_init = pl181_class_init,
};
static void pl181_register_devices(void)
{
- sysbus_register_withprop(&pl181_info);
+ type_register_static(&pl181_info);
}
device_init(pl181_register_devices)
diff --git a/hw/pl190.c b/hw/pl190.c
index 6fc2656f69..956ab21c6a 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -255,18 +255,27 @@ static const VMStateDescription vmstate_pl190 = {
}
};
-static SysBusDeviceInfo pl190_info = {
- .init = pl190_init,
- .qdev.name = "pl190",
- .qdev.size = sizeof(pl190_state),
- .qdev.vmsd = &vmstate_pl190,
- .qdev.reset = pl190_reset,
- .qdev.no_user = 1,
+static void pl190_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pl190_init;
+ dc->no_user = 1;
+ dc->reset = pl190_reset;
+ dc->vmsd = &vmstate_pl190;
+}
+
+static TypeInfo pl190_info = {
+ .name = "pl190",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(pl190_state),
+ .class_init = pl190_class_init,
};
static void pl190_register_devices(void)
{
- sysbus_register_withprop(&pl190_info);
+ type_register_static(&pl190_info);
}
device_init(pl190_register_devices)
diff --git a/hw/ppc440.c b/hw/ppc440.c
deleted file mode 100644
index cd8a95d52b..0000000000
--- a/hw/ppc440.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Qemu PowerPC 440 chip emulation
- *
- * Copyright 2007 IBM Corporation.
- * Authors:
- * Jerone Young <jyoung5@us.ibm.com>
- * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- * Hollis Blanchard <hollisb@us.ibm.com>
- *
- * This work is licensed under the GNU GPL license version 2 or later.
- *
- */
-
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "ppc440.h"
-#include "ppc405.h"
-#include "sysemu.h"
-#include "kvm.h"
-
-#define PPC440EP_PCI_CONFIG 0xeec00000
-#define PPC440EP_PCI_INTACK 0xeed00000
-#define PPC440EP_PCI_SPECIAL 0xeed00000
-#define PPC440EP_PCI_REGS 0xef400000
-#define PPC440EP_PCI_IO 0xe8000000
-#define PPC440EP_PCI_IOLEN 0x00010000
-
-#define PPC440EP_SDRAM_NR_BANKS 4
-
-static const unsigned int ppc440ep_sdram_bank_sizes[] = {
- 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
-};
-
-CPUState *ppc440ep_init(MemoryRegion *address_space_mem, ram_addr_t *ram_size,
- PCIBus **pcip, const unsigned int pci_irq_nrs[4],
- int do_init, const char *cpu_model)
-{
- MemoryRegion *ram_memories
- = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
- target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS];
- target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS];
- CPUState *env;
- qemu_irq *pic;
- qemu_irq *irqs;
- qemu_irq *pci_irqs;
-
- if (cpu_model == NULL) {
- cpu_model = "440-Xilinx"; // XXX: should be 440EP
- }
- env = cpu_init(cpu_model);
- if (!env) {
- fprintf(stderr, "Unable to initialize CPU!\n");
- exit(1);
- }
-
- ppc_dcr_init(env, NULL, NULL);
-
- /* interrupt controller */
- irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
- irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
- irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
- pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-
- /* SDRAM controller */
- memset(ram_bases, 0, sizeof(ram_bases));
- memset(ram_sizes, 0, sizeof(ram_sizes));
- *ram_size = ppc4xx_sdram_adjust(*ram_size, PPC440EP_SDRAM_NR_BANKS,
- ram_memories,
- ram_bases, ram_sizes,
- ppc440ep_sdram_bank_sizes);
- /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
- ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
- ram_bases, ram_sizes, do_init);
-
- /* PCI */
- pci_irqs = g_malloc(sizeof(qemu_irq) * 4);
- pci_irqs[0] = pic[pci_irq_nrs[0]];
- pci_irqs[1] = pic[pci_irq_nrs[1]];
- pci_irqs[2] = pic[pci_irq_nrs[2]];
- pci_irqs[3] = pic[pci_irq_nrs[3]];
- *pcip = ppc4xx_pci_init(env, pci_irqs,
- PPC440EP_PCI_CONFIG,
- PPC440EP_PCI_INTACK,
- PPC440EP_PCI_SPECIAL,
- PPC440EP_PCI_REGS);
- if (!*pcip)
- printf("couldn't create PCI controller!\n");
-
- isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
-
- if (serial_hds[0] != NULL) {
- serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
- PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
- DEVICE_BIG_ENDIAN);
- }
- if (serial_hds[1] != NULL) {
- serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
- PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
- DEVICE_BIG_ENDIAN);
- }
-
- return env;
-}
diff --git a/hw/ppc440.h b/hw/ppc440.h
deleted file mode 100644
index 9c27c36fd0..0000000000
--- a/hw/ppc440.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Qemu PowerPC 440 board emualtion
- *
- * Copyright 2007 IBM Corporation.
- * Authors: Jerone Young <jyoung5@us.ibm.com>
- * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- *
- * This work is licensed under the GNU GPL licence version 2 or later
- *
- */
-
-#ifndef QEMU_PPC440_H
-#define QEMU_PPC440_H
-
-#include "hw.h"
-
-CPUState *ppc440ep_init(MemoryRegion *address_space, ram_addr_t *ram_size,
- PCIBus **pcip, const unsigned int pci_irq_nrs[4],
- int do_init, const char *cpu_model);
-
-#endif
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index b734e3a56c..f86b16838a 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -3,9 +3,9 @@
*
* Copyright 2007 IBM Corporation.
* Authors:
- * Jerone Young <jyoung5@us.ibm.com>
- * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- * Hollis Blanchard <hollisb@us.ibm.com>
+ * Jerone Young <jyoung5@us.ibm.com>
+ * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ * Hollis Blanchard <hollisb@us.ibm.com>
*
* This work is licensed under the GNU GPL license version 2 or later.
*
@@ -17,13 +17,17 @@
#include "hw.h"
#include "pci.h"
#include "boards.h"
-#include "ppc440.h"
#include "kvm.h"
#include "kvm_ppc.h"
#include "device_tree.h"
#include "loader.h"
#include "elf.h"
#include "exec-memory.h"
+#include "pc.h"
+#include "ppc.h"
+#include "ppc405.h"
+#include "sysemu.h"
+#include "sysbus.h"
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
@@ -32,6 +36,21 @@
#define FDT_ADDR 0x1800000
#define RAMDISK_ADDR 0x1900000
+#define PPC440EP_PCI_CONFIG 0xeec00000
+#define PPC440EP_PCI_INTACK 0xeed00000
+#define PPC440EP_PCI_SPECIAL 0xeed00000
+#define PPC440EP_PCI_REGS 0xef400000
+#define PPC440EP_PCI_IO 0xe8000000
+#define PPC440EP_PCI_IOLEN 0x00010000
+
+#define PPC440EP_SDRAM_NR_BANKS 4
+
+static const unsigned int ppc440ep_sdram_bank_sizes[] = {
+ 256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
+};
+
+static target_phys_addr_t entry;
+
static int bamboo_load_device_tree(target_phys_addr_t addr,
uint32_t ramsize,
target_phys_addr_t initrd_base,
@@ -101,6 +120,42 @@ out:
return ret;
}
+/* Create reset TLB entries for BookE, spanning the 32bit addr space. */
+static void mmubooke_create_initial_mapping(CPUState *env,
+ target_ulong va,
+ target_phys_addr_t pa)
+{
+ ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+ tlb->attr = 0;
+ tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+ tlb->size = 1 << 31; /* up to 0x80000000 */
+ tlb->EPN = va & TARGET_PAGE_MASK;
+ tlb->RPN = pa & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+
+ tlb = &env->tlb.tlbe[1];
+ tlb->attr = 0;
+ tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+ tlb->size = 1 << 31; /* up to 0xffffffff */
+ tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+ tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+
+ cpu_reset(env);
+ env->gpr[1] = (16<<20) - 8;
+ env->gpr[3] = FDT_ADDR;
+ env->nip = entry;
+
+ /* Create a mapping for the kernel. */
+ mmubooke_create_initial_mapping(env, 0, 0);
+}
+
static void bamboo_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@@ -110,19 +165,76 @@ static void bamboo_init(ram_addr_t ram_size,
{
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *ram_memories
+ = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
+ target_phys_addr_t ram_bases[PPC440EP_SDRAM_NR_BANKS];
+ target_phys_addr_t ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+ qemu_irq *pic;
+ qemu_irq *irqs;
PCIBus *pcibus;
CPUState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
- target_phys_addr_t entry = 0;
target_phys_addr_t loadaddr = 0;
target_long initrd_size = 0;
+ DeviceState *dev;
int success;
int i;
/* Setup CPU. */
- env = ppc440ep_init(address_space_mem, &ram_size, &pcibus,
- pci_irq_nrs, 1, cpu_model);
+ if (cpu_model == NULL) {
+ cpu_model = "440EP";
+ }
+ env = cpu_init(cpu_model);
+ if (!env) {
+ fprintf(stderr, "Unable to initialize CPU!\n");
+ exit(1);
+ }
+
+ qemu_register_reset(main_cpu_reset, env);
+ ppc_booke_timers_init(env, 400000000, 0);
+ ppc_dcr_init(env, NULL, NULL);
+
+ /* interrupt controller */
+ irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+ irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+ irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+ pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+
+ /* SDRAM controller */
+ memset(ram_bases, 0, sizeof(ram_bases));
+ memset(ram_sizes, 0, sizeof(ram_sizes));
+ ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS,
+ ram_memories,
+ ram_bases, ram_sizes,
+ ppc440ep_sdram_bank_sizes);
+ /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
+ ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
+ ram_bases, ram_sizes, 1);
+
+ /* PCI */
+ dev = sysbus_create_varargs("ppc4xx-pcihost", PPC440EP_PCI_CONFIG,
+ pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
+ pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
+ NULL);
+ pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+ if (!pcibus) {
+ fprintf(stderr, "couldn't create PCI controller!\n");
+ exit(1);
+ }
+
+ isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+
+ if (serial_hds[0] != NULL) {
+ serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+ PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+ DEVICE_BIG_ENDIAN);
+ }
+ if (serial_hds[1] != NULL) {
+ serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+ PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+ DEVICE_BIG_ENDIAN);
+ }
if (pcibus) {
/* Register network interfaces. */
@@ -169,12 +281,6 @@ static void bamboo_init(ram_addr_t ram_size,
fprintf(stderr, "couldn't load device tree\n");
exit(1);
}
-
- /* Set initial guest state. */
- env->gpr[1] = (16<<20) - 8;
- env->gpr[3] = FDT_ADDR;
- env->nip = entry;
- /* XXX we currently depend on KVM to create some initial TLB entries. */
}
if (kvm_enabled())
@@ -182,34 +288,14 @@ static void bamboo_init(ram_addr_t ram_size,
}
static QEMUMachine bamboo_machine = {
- .name = "bamboo-0.13",
- .alias = "bamboo",
- .desc = "bamboo",
- .init = bamboo_init,
-};
-
-static QEMUMachine bamboo_machine_v0_12 = {
- .name = "bamboo-0.12",
+ .name = "bamboo",
.desc = "bamboo",
.init = bamboo_init,
- .compat_props = (GlobalProperty[]) {
- {
- .driver = "virtio-serial-pci",
- .property = "max_ports",
- .value = stringify(1),
- },{
- .driver = "virtio-serial-pci",
- .property = "vectors",
- .value = stringify(0),
- },
- { /* end of list */ }
- },
};
static void bamboo_machine_init(void)
{
qemu_register_machine(&bamboo_machine);
- qemu_register_machine(&bamboo_machine_v0_12);
}
machine_init(bamboo_machine_init);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 2c69210225..d11f120d32 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -49,13 +49,14 @@ struct PCITargetMap {
#define PPC4xx_PCI_NR_PTMS 2
struct PPC4xxPCIState {
+ PCIHostState pci_state;
+
struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
+ qemu_irq irq[4];
- PCIHostState pci_state;
- PCIDevice *pci_dev;
- MemoryRegion iomem_addr;
- MemoryRegion iomem_regs;
+ MemoryRegion container;
+ MemoryRegion iomem;
};
typedef struct PPC4xxPCIState PPC4xxPCIState;
@@ -83,8 +84,10 @@ typedef struct PPC4xxPCIState PPC4xxPCIState;
#define PCIL0_PTM1LA 0x34
#define PCIL0_PTM2MS 0x38
#define PCIL0_PTM2LA 0x3c
+#define PCI_REG_BASE 0x800000
#define PCI_REG_SIZE 0x40
+#define PCI_ALL_SIZE (PCI_REG_BASE + PCI_REG_SIZE)
static uint64_t pci4xx_cfgaddr_read(void *opaque, target_phys_addr_t addr,
unsigned size)
@@ -275,6 +278,10 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
qemu_irq *pci_irqs = opaque;
DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
+ if (irq_num < 0) {
+ fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);
+ return;
+ }
qemu_set_irq(pci_irqs[irq_num], level);
}
@@ -310,7 +317,6 @@ static const VMStateDescription vmstate_ppc4xx_pci = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
vmstate_pci_master_map,
struct PCIMasterMap),
@@ -322,60 +328,81 @@ static const VMStateDescription vmstate_ppc4xx_pci = {
};
/* XXX Interrupt acknowledge cycles not supported. */
-PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
- target_phys_addr_t config_space,
- target_phys_addr_t int_ack,
- target_phys_addr_t special_cycle,
- target_phys_addr_t registers)
+static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
+{
+ PPC4xxPCIState *s;
+ PCIHostState *h;
+ PCIBus *b;
+ int i;
+
+ h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ s = DO_UPCAST(PPC4xxPCIState, pci_state, h);
+
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+
+ b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, ppc4xx_pci_set_irq,
+ ppc4xx_pci_map_irq, s->irq, get_system_memory(),
+ get_system_io(), 0, 4);
+ s->pci_state.bus = b;
+
+ pci_create_simple(b, 0, "ppc4xx-host-bridge");
+
+ /* XXX split into 2 memory regions, one for config space, one for regs */
+ memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE);
+ memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h,
+ "pci-conf-idx", 4);
+ memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+ "pci-conf-data", 4);
+ memory_region_init_io(&s->iomem, &pci_reg_ops, s,
+ "pci.reg", PCI_REG_SIZE);
+ memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
+ memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
+ memory_region_add_subregion(&s->container, PCI_REG_BASE, &s->iomem);
+ sysbus_init_mmio(dev, &s->container);
+ qemu_register_reset(ppc4xx_pci_reset, s);
+
+ return 0;
+}
+
+static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "Host bridge";
+ k->vendor_id = PCI_VENDOR_ID_IBM;
+ k->device_id = PCI_DEVICE_ID_IBM_440GX;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static TypeInfo ppc4xx_host_bridge_info = {
+ .name = "ppc4xx-host-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = ppc4xx_host_bridge_class_init,
+};
+
+static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = ppc4xx_pcihost_initfn;
+ dc->vmsd = &vmstate_ppc4xx_pci;
+}
+
+static TypeInfo ppc4xx_pcihost_info = {
+ .name = "ppc4xx-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PPC4xxPCIState),
+ .class_init = ppc4xx_pcihost_class_init,
+};
+
+static void ppc4xx_pci_register(void)
{
- PPC4xxPCIState *controller;
- static int ppc4xx_pci_id;
- uint8_t *pci_conf;
-
- controller = g_malloc0(sizeof(PPC4xxPCIState));
-
- controller->pci_state.bus = pci_register_bus(NULL, "pci",
- ppc4xx_pci_set_irq,
- ppc4xx_pci_map_irq,
- pci_irqs,
- get_system_memory(),
- get_system_io(),
- 0, 4);
-
- controller->pci_dev = pci_register_device(controller->pci_state.bus,
- "host bridge", sizeof(PCIDevice),
- 0, NULL, NULL);
- pci_conf = controller->pci_dev->config;
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_440GX);
- pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
-
- /* CFGADDR */
- memory_region_init_io(&controller->iomem_addr, &pci4xx_cfgaddr_ops,
- controller, "pci.cfgaddr", 4);
- memory_region_add_subregion(get_system_memory(),
- config_space + PCIC0_CFGADDR,
- &controller->iomem_addr);
-
- /* CFGDATA */
- memory_region_init_io(&controller->pci_state.data_mem,
- &pci_host_data_be_ops,
- &controller->pci_state, "pci-conf-data", 4);
- memory_region_add_subregion(get_system_memory(),
- config_space + PCIC0_CFGDATA,
- &controller->pci_state.data_mem);
-
- /* Internal registers */
- memory_region_init_io(&controller->iomem_regs, &pci_reg_ops, controller,
- "pci.regs", PCI_REG_SIZE);
- memory_region_add_subregion(get_system_memory(), registers,
- &controller->iomem_regs);
-
- qemu_register_reset(ppc4xx_pci_reset, controller);
-
- /* XXX load/save code not tested. */
- vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
- &vmstate_ppc4xx_pci, controller);
-
- return controller->pci_state.bus;
+ type_register_static(&ppc4xx_pcihost_info);
+ type_register_static(&ppc4xx_host_bridge_info);
}
+device_init(ppc4xx_pci_register);
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index a746c9c3c6..506187b182 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -311,7 +311,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
exit(1);
}
}
- pic = openpic_init(NULL, &pic_mem, smp_cpus, openpic_irqs, NULL);
+ pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs, NULL);
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
/* 970 gets a U3 bus */
pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io());
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 47dab3f184..eb43fb5849 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -29,7 +29,7 @@
#include "sysemu.h"
#include "isa.h"
#include "pci.h"
-#include "prep_pci.h"
+#include "pci_host.h"
#include "usb-ohci.h"
#include "ppc.h"
#include "boards.h"
@@ -83,37 +83,9 @@ static const int ide_irq[2] = { 13, 13 };
static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
-//static ISADevice *pit;
-
/* ISA IO ports bridge */
#define PPC_IO_BASE 0x80000000
-#if 0
-/* Speaker port 0x61 */
-static int speaker_data_on;
-static int dummy_refresh_clock;
-#endif
-
-static void speaker_ioport_write (void *opaque, uint32_t addr, uint32_t val)
-{
-#if 0
- speaker_data_on = (val >> 1) & 1;
- pit_set_gate(pit, 2, val & 1);
-#endif
-}
-
-static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
-{
-#if 0
- int out;
- out = pit_get_out(pit, 2, qemu_get_clock_ns(vm_clock));
- dummy_refresh_clock ^= 1;
- return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
- (dummy_refresh_clock << 4);
-#endif
- return 0;
-}
-
/* PCI intack register */
/* Read-only register (?) */
static void PPC_intack_write (void *opaque, target_phys_addr_t addr,
@@ -522,9 +494,12 @@ static void ppc_prep_init (ram_addr_t ram_size,
MemoryRegion *bios = g_new(MemoryRegion, 1);
uint32_t kernel_base, initrd_base;
long kernel_size, initrd_size;
+ DeviceState *dev;
+ SysBusDevice *sys;
+ PCIHostState *pcihost;
PCIBus *pci_bus;
+ PCIDevice *pci;
ISABus *isa_bus;
- qemu_irq *i8259;
qemu_irq *cpu_exit_irq;
int ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
@@ -560,6 +535,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
/* allocate and load BIOS */
memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE);
+ memory_region_set_readonly(bios, true);
+ memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios);
vmstate_register_ram_global(bios);
if (bios_name == NULL)
bios_name = BIOS_FILENAME;
@@ -573,8 +550,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
target_phys_addr_t bios_addr;
bios_size = (bios_size + 0xfff) & ~0xfff;
bios_addr = (uint32_t)(-bios_size);
- memory_region_set_readonly(bios, true);
- memory_region_add_subregion(sysmem, bios_addr, bios);
bios_size = load_image_targphys(filename, bios_addr, bios_size);
}
if (bios_size < 0 || bios_size > BIOS_SIZE) {
@@ -626,16 +601,34 @@ static void ppc_prep_init (ram_addr_t ram_size,
}
}
- isa_mem_base = 0xc0000000;
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
hw_error("Only 6xx bus is supported on PREP machine\n");
}
- /* Hmm, prep has no pci-isa bridge ??? */
- isa_bus = isa_bus_new(NULL, get_system_io());
- i8259 = i8259_init(isa_bus, first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
- pci_bus = pci_prep_init(i8259, get_system_memory(), get_system_io());
- isa_bus_irqs(isa_bus, i8259);
- // pci_bus = i440fx_init();
+
+ dev = qdev_create(NULL, "raven-pcihost");
+ sys = sysbus_from_qdev(dev);
+ pcihost = DO_UPCAST(PCIHostState, busdev, sys);
+ pcihost->address_space = get_system_memory();
+ qdev_init_nofail(dev);
+ object_property_add_child(object_get_root(), "raven", OBJECT(dev), NULL);
+ pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+ if (pci_bus == NULL) {
+ fprintf(stderr, "Couldn't create PCI host controller.\n");
+ exit(1);
+ }
+
+ /* PCI -> ISA bridge */
+ pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ qdev_connect_gpio_out(&pci->qdev, 0,
+ first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
+ qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq);
+ sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9));
+ sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11));
+ sysbus_connect_irq(&pcihost->busdev, 2, qdev_get_gpio_in(&pci->qdev, 9));
+ sysbus_connect_irq(&pcihost->busdev, 3, qdev_get_gpio_in(&pci->qdev, 11));
+ isa_bus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&pci->qdev, "isa.0"));
+
/* Register 8 MB of ISA IO space (needed for non-contiguous map) */
memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl,
"ppc-io", 0x00800000);
@@ -643,9 +636,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
/* init basic PC hardware */
pci_vga_init(pci_bus);
- // openpic = openpic_init(0x00000000, 0xF0000000, 1);
- // pit = pit_init(0x40, 0);
- rtc_init(isa_bus, 2000, NULL);
if (serial_hds[0])
serial_isa_init(isa_bus, 0, serial_hds[0]);
@@ -672,9 +662,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
}
isa_create_simple(isa_bus, "i8042");
- cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
- DMA_init(1, cpu_exit_irq);
-
// SB16_init();
for(i = 0; i < MAX_FD; i++) {
@@ -682,9 +669,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
}
fdctrl_init_isa(isa_bus, fd);
- /* Register speaker port */
- register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
- register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
/* Register fake IO ports for PREP */
sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
@@ -707,7 +691,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
usb_ohci_init_pci(pci_bus, -1);
}
- m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
+ m48t59 = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
if (m48t59 == NULL)
return;
sysctrl->nvram = m48t59;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index b606206e00..d5bce71429 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -339,25 +339,43 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
return 0;
}
-static PCIDeviceInfo e500_host_bridge_info = {
- .qdev.name = "e500-host-bridge",
- .qdev.desc = "Host bridge",
- .qdev.size = sizeof(PCIDevice),
- .vendor_id = PCI_VENDOR_ID_FREESCALE,
- .device_id = PCI_DEVICE_ID_MPC8533E,
- .class_id = PCI_CLASS_PROCESSOR_POWERPC,
+static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = PCI_VENDOR_ID_FREESCALE;
+ k->device_id = PCI_DEVICE_ID_MPC8533E;
+ k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
+ dc->desc = "Host bridge";
+}
+
+static TypeInfo e500_host_bridge_info = {
+ .name = "e500-host-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = e500_host_bridge_class_init,
};
-static SysBusDeviceInfo e500_pcihost_info = {
- .init = e500_pcihost_initfn,
- .qdev.name = "e500-pcihost",
- .qdev.size = sizeof(PPCE500PCIState),
- .qdev.vmsd = &vmstate_ppce500_pci,
+static void e500_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = e500_pcihost_initfn;
+ dc->vmsd = &vmstate_ppce500_pci;
+}
+
+static TypeInfo e500_pcihost_info = {
+ .name = "e500-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PPCE500PCIState),
+ .class_init = e500_pcihost_class_init,
};
static void e500_pci_register(void)
{
- sysbus_register_withprop(&e500_pcihost_info);
- pci_qdev_register(&e500_host_bridge_info);
+ type_register_static(&e500_pcihost_info);
+ type_register_static(&e500_host_bridge_info);
}
device_init(e500_pci_register);
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index e7b1453855..9d648ec90a 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -203,14 +203,22 @@ static int ppce500_spin_initfn(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo ppce500_spin_info = {
- .init = ppce500_spin_initfn,
- .qdev.name = "e500-spin",
- .qdev.size = sizeof(SpinState),
+static void ppce500_spin_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = ppce500_spin_initfn;
+}
+
+static TypeInfo ppce500_spin_info = {
+ .name = "e500-spin",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SpinState),
+ .class_init = ppce500_spin_class_init,
};
static void ppce500_spin_register(void)
{
- sysbus_register_withprop(&ppce500_spin_info);
+ type_register_static(&ppce500_spin_info);
}
device_init(ppce500_spin_register);
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index ea9fb6902c..40b8bb0edd 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -25,9 +25,16 @@
#include "hw.h"
#include "pci.h"
#include "pci_host.h"
-#include "prep_pci.h"
+#include "exec-memory.h"
-typedef PCIHostState PREPPCIState;
+typedef struct PRePPCIState {
+ PCIHostState host_state;
+ qemu_irq irq[4];
+} PREPPCIState;
+
+typedef struct RavenPCIState {
+ PCIDevice dev;
+} RavenPCIState;
static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
{
@@ -40,58 +47,24 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
return (addr & 0x7ff) | (i << 11);
}
-static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 1);
-}
-
-static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
- val = bswap16(val);
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 2);
-}
-
-static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void ppc_pci_io_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
{
PREPPCIState *s = opaque;
- val = bswap32(val);
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 4);
+ pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, size);
}
-static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr)
+static uint64_t ppc_pci_io_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
{
PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 1);
- return val;
-}
-
-static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr)
-{
- PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 2);
- val = bswap16(val);
- return val;
-}
-
-static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
-{
- PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 4);
- val = bswap32(val);
- return val;
+ return pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), size);
}
static const MemoryRegionOps PPC_PCIIO_ops = {
- .old_mmio = {
- .read = { PPC_PCIIO_readb, PPC_PCIIO_readw, PPC_PCIIO_readl, },
- .write = { PPC_PCIIO_writeb, PPC_PCIIO_writew, PPC_PCIIO_writel, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .read = ppc_pci_io_read,
+ .write = ppc_pci_io_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
};
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
@@ -103,46 +76,107 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
{
qemu_irq *pic = opaque;
- qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
+ qemu_set_irq(pic[irq_num] , level);
}
-PCIBus *pci_prep_init(qemu_irq *pic,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io)
+static int raven_pcihost_init(SysBusDevice *dev)
{
- PREPPCIState *s;
- PCIDevice *d;
+ PCIHostState *h = FROM_SYSBUS(PCIHostState, dev);
+ PREPPCIState *s = DO_UPCAST(PREPPCIState, host_state, h);
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *address_space_io = get_system_io();
+ PCIBus *bus;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
- s = g_malloc0(sizeof(PREPPCIState));
- s->bus = pci_register_bus(NULL, "pci",
- prep_set_irq, prep_map_irq, pic,
- address_space_mem,
- address_space_io,
- 0, 4);
+ bus = pci_register_bus(&h->busdev.qdev, NULL,
+ prep_set_irq, prep_map_irq, s->irq,
+ address_space_mem, address_space_io, 0, 4);
+ h->bus = bus;
- memory_region_init_io(&s->conf_mem, &pci_host_conf_be_ops, s,
+ memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s,
"pci-conf-idx", 1);
- memory_region_add_subregion(address_space_io, 0xcf8, &s->conf_mem);
- sysbus_init_ioports(&s->busdev, 0xcf8, 1);
+ sysbus_add_io(dev, 0xcf8, &h->conf_mem);
+ sysbus_init_ioports(&h->busdev, 0xcf8, 1);
- memory_region_init_io(&s->data_mem, &pci_host_data_be_ops, s,
+ memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s,
"pci-conf-data", 1);
- memory_region_add_subregion(address_space_io, 0xcfc, &s->data_mem);
- sysbus_init_ioports(&s->busdev, 0xcfc, 1);
-
- memory_region_init_io(&s->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
- memory_region_add_subregion(address_space_mem, 0x80800000, &s->mmcfg);
-
- /* PCI host bridge */
- d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
- sizeof(PCIDevice), 0, NULL, NULL);
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_RAVEN);
- d->config[0x08] = 0x00; // revision
- pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+ sysbus_add_io(dev, 0xcfc, &h->data_mem);
+ sysbus_init_ioports(&h->busdev, 0xcfc, 1);
+
+ memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
+ memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
+
+ pci_create_simple(bus, 0, "raven");
+
+ return 0;
+}
+
+static int raven_init(PCIDevice *d)
+{
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x34] = 0x00; // capabilities_pointer
- return s->bus;
+ return 0;
+}
+
+static const VMStateDescription vmstate_raven = {
+ .name = "raven",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, RavenPCIState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void raven_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = raven_init;
+ k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+ k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+ dc->desc = "PReP Host Bridge - Motorola Raven";
+ dc->vmsd = &vmstate_raven;
+ dc->no_user = 1;
+}
+
+static TypeInfo raven_info = {
+ .name = "raven",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(RavenPCIState),
+ .class_init = raven_class_init,
+};
+
+static void raven_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = raven_pcihost_init;
+ dc->fw_name = "pci";
+ dc->no_user = 1;
}
+
+static TypeInfo raven_pcihost_info = {
+ .name = "raven-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PREPPCIState),
+ .class_init = raven_pcihost_class_init,
+};
+
+static void raven_register_devices(void)
+{
+ type_register_static(&raven_pcihost_info);
+ type_register_static(&raven_info);
+}
+
+device_init(raven_register_devices)
diff --git a/hw/prep_pci.h b/hw/prep_pci.h
deleted file mode 100644
index b6b481a517..0000000000
--- a/hw/prep_pci.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef QEMU_PREP_PCI_H
-#define QEMU_PREP_PCI_H
-
-#include "qemu-common.h"
-#include "memory.h"
-
-PCIBus *pci_prep_init(qemu_irq *pic,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io);
-
-#endif
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 6ddd5005de..244c614510 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1233,17 +1233,26 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = {
},
};
-static SysBusDeviceInfo pxa2xx_rtc_sysbus_info = {
- .init = pxa2xx_rtc_init,
- .qdev.name = "pxa2xx_rtc",
- .qdev.desc = "PXA2xx RTC Controller",
- .qdev.size = sizeof(PXA2xxRTCState),
- .qdev.vmsd = &vmstate_pxa2xx_rtc_regs,
+static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_rtc_init;
+ dc->desc = "PXA2xx RTC Controller";
+ dc->vmsd = &vmstate_pxa2xx_rtc_regs;
+}
+
+static TypeInfo pxa2xx_rtc_sysbus_info = {
+ .name = "pxa2xx_rtc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxRTCState),
+ .class_init = pxa2xx_rtc_sysbus_class_init,
};
/* I2C Interface */
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
PXA2xxI2CState *host;
} PXA2xxI2CSlaveState;
@@ -1279,7 +1288,7 @@ static void pxa2xx_i2c_update(PXA2xxI2CState *s)
}
/* These are only stubs now. */
-static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
+static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
{
PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
PXA2xxI2CState *s = slave->host;
@@ -1303,7 +1312,7 @@ static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
pxa2xx_i2c_update(s);
}
-static int pxa2xx_i2c_rx(i2c_slave *i2c)
+static int pxa2xx_i2c_rx(I2CSlave *i2c)
{
PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
PXA2xxI2CState *s = slave->host;
@@ -1318,7 +1327,7 @@ static int pxa2xx_i2c_rx(i2c_slave *i2c)
return s->data;
}
-static int pxa2xx_i2c_tx(i2c_slave *i2c, uint8_t data)
+static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data)
{
PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
PXA2xxI2CState *s = slave->host;
@@ -1466,19 +1475,27 @@ static const VMStateDescription vmstate_pxa2xx_i2c = {
}
};
-static int pxa2xx_i2c_slave_init(i2c_slave *i2c)
+static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
{
/* Nothing to do. */
return 0;
}
-static I2CSlaveInfo pxa2xx_i2c_slave_info = {
- .qdev.name = "pxa2xx-i2c-slave",
- .qdev.size = sizeof(PXA2xxI2CSlaveState),
- .init = pxa2xx_i2c_slave_init,
- .event = pxa2xx_i2c_event,
- .recv = pxa2xx_i2c_rx,
- .send = pxa2xx_i2c_tx
+static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
+{
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = pxa2xx_i2c_slave_init;
+ k->event = pxa2xx_i2c_event;
+ k->recv = pxa2xx_i2c_rx;
+ k->send = pxa2xx_i2c_tx;
+}
+
+static TypeInfo pxa2xx_i2c_slave_info = {
+ .name = "pxa2xx-i2c-slave",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(PXA2xxI2CSlaveState),
+ .class_init = pxa2xx_i2c_slave_class_init,
};
PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
@@ -1526,17 +1543,28 @@ i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
return s->bus;
}
-static SysBusDeviceInfo pxa2xx_i2c_info = {
- .init = pxa2xx_i2c_initfn,
- .qdev.name = "pxa2xx_i2c",
- .qdev.desc = "PXA2xx I2C Bus Controller",
- .qdev.size = sizeof(PXA2xxI2CState),
- .qdev.vmsd = &vmstate_pxa2xx_i2c,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
- DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property pxa2xx_i2c_properties[] = {
+ DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
+ DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_i2c_initfn;
+ dc->desc = "PXA2xx I2C Bus Controller";
+ dc->vmsd = &vmstate_pxa2xx_i2c;
+ dc->props = pxa2xx_i2c_properties;
+}
+
+static TypeInfo pxa2xx_i2c_info = {
+ .name = "pxa2xx_i2c",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxI2CState),
+ .class_init = pxa2xx_i2c_class_init,
};
/* PXA Inter-IC Sound Controller */
@@ -2288,12 +2316,26 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
return s;
}
+static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pxa2xx_ssp_init;
+}
+
+static TypeInfo pxa2xx_ssp_info = {
+ .name = "pxa2xx-ssp",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxSSPState),
+ .class_init = pxa2xx_ssp_class_init,
+};
+
static void pxa2xx_register_devices(void)
{
- i2c_register_slave(&pxa2xx_i2c_slave_info);
- sysbus_register_dev("pxa2xx-ssp", sizeof(PXA2xxSSPState), pxa2xx_ssp_init);
- sysbus_register_withprop(&pxa2xx_i2c_info);
- sysbus_register_withprop(&pxa2xx_rtc_sysbus_info);
+ type_register_static(&pxa2xx_i2c_slave_info);
+ type_register_static(&pxa2xx_ssp_info);
+ type_register_static(&pxa2xx_i2c_info);
+ type_register_static(&pxa2xx_rtc_sysbus_info);
}
device_init(pxa2xx_register_devices)
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index cb281071f0..2d61565f1d 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -543,20 +543,31 @@ static VMStateDescription vmstate_pxa2xx_dma = {
},
};
-static SysBusDeviceInfo pxa2xx_dma_info = {
- .init = pxa2xx_dma_init,
- .qdev.name = "pxa2xx-dma",
- .qdev.desc = "PXA2xx DMA controller",
- .qdev.size = sizeof(PXA2xxDMAState),
- .qdev.vmsd = &vmstate_pxa2xx_dma,
- .qdev.props = (Property[]) {
- DEFINE_PROP_INT32("channels", PXA2xxDMAState, channels, -1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property pxa2xx_dma_properties[] = {
+ DEFINE_PROP_INT32("channels", PXA2xxDMAState, channels, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_dma_init;
+ dc->desc = "PXA2xx DMA controller";
+ dc->vmsd = &vmstate_pxa2xx_dma;
+ dc->props = pxa2xx_dma_properties;
+}
+
+static TypeInfo pxa2xx_dma_info = {
+ .name = "pxa2xx-dma",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxDMAState),
+ .class_init = pxa2xx_dma_class_init,
};
static void pxa2xx_dma_register(void)
{
- sysbus_register_withprop(&pxa2xx_dma_info);
+ type_register_static(&pxa2xx_dma_info);
}
device_init(pxa2xx_dma_register);
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index cc58c40914..67fd17c4ca 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -317,20 +317,31 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
},
};
-static SysBusDeviceInfo pxa2xx_gpio_info = {
- .init = pxa2xx_gpio_initfn,
- .qdev.name = "pxa2xx-gpio",
- .qdev.desc = "PXA2xx GPIO controller",
- .qdev.size = sizeof(PXA2xxGPIOInfo),
- .qdev.props = (Property []) {
- DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
- DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property pxa2xx_gpio_properties[] = {
+ DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
+ DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_gpio_initfn;
+ dc->desc = "PXA2xx GPIO controller";
+ dc->props = pxa2xx_gpio_properties;
+}
+
+static TypeInfo pxa2xx_gpio_info = {
+ .name = "pxa2xx-gpio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxGPIOInfo),
+ .class_init = pxa2xx_gpio_class_init,
};
static void pxa2xx_gpio_register(void)
{
- sysbus_register_withprop(&pxa2xx_gpio_info);
+ type_register_static(&pxa2xx_gpio_info);
}
device_init(pxa2xx_gpio_register);
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 92effbc806..ca85743aea 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -296,16 +296,25 @@ static int pxa2xx_pic_initfn(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo pxa2xx_pic_info = {
- .init = pxa2xx_pic_initfn,
- .qdev.name = "pxa2xx_pic",
- .qdev.desc = "PXA2xx PIC",
- .qdev.size = sizeof(PXA2xxPICState),
- .qdev.vmsd = &vmstate_pxa2xx_pic_regs,
+static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_pic_initfn;
+ dc->desc = "PXA2xx PIC";
+ dc->vmsd = &vmstate_pxa2xx_pic_regs;
+}
+
+static TypeInfo pxa2xx_pic_info = {
+ .name = "pxa2xx_pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxPICState),
+ .class_init = pxa2xx_pic_class_init,
};
static void pxa2xx_pic_register(void)
{
- sysbus_register_withprop(&pxa2xx_pic_info);
+ type_register_static(&pxa2xx_pic_info);
}
device_init(pxa2xx_pic_register);
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 50e26789d2..90800751b1 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -477,37 +477,59 @@ static const VMStateDescription vmstate_pxa2xx_timer_regs = {
}
};
-static SysBusDeviceInfo pxa25x_timer_dev_info = {
- .init = pxa2xx_timer_init,
- .qdev.name = "pxa25x-timer",
- .qdev.desc = "PXA25x timer",
- .qdev.size = sizeof(PXA2xxTimerInfo),
- .qdev.vmsd = &vmstate_pxa2xx_timer_regs,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
- DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, false),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property pxa25x_timer_dev_properties[] = {
+ DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
+ DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
+ PXA2XX_TIMER_HAVE_TM4, false),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo pxa27x_timer_dev_info = {
- .init = pxa2xx_timer_init,
- .qdev.name = "pxa27x-timer",
- .qdev.desc = "PXA27x timer",
- .qdev.size = sizeof(PXA2xxTimerInfo),
- .qdev.vmsd = &vmstate_pxa2xx_timer_regs,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
- DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, true),
- DEFINE_PROP_END_OF_LIST(),
- },
+static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_timer_init;
+ dc->desc = "PXA25x timer";
+ dc->vmsd = &vmstate_pxa2xx_timer_regs;
+ dc->props = pxa25x_timer_dev_properties;
+}
+
+static TypeInfo pxa25x_timer_dev_info = {
+ .name = "pxa25x-timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxTimerInfo),
+ .class_init = pxa25x_timer_dev_class_init,
+};
+
+static Property pxa27x_timer_dev_properties[] = {
+ DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
+ DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
+ PXA2XX_TIMER_HAVE_TM4, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = pxa2xx_timer_init;
+ dc->desc = "PXA27x timer";
+ dc->vmsd = &vmstate_pxa2xx_timer_regs;
+ dc->props = pxa27x_timer_dev_properties;
+}
+
+static TypeInfo pxa27x_timer_dev_info = {
+ .name = "pxa27x-timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxTimerInfo),
+ .class_init = pxa27x_timer_dev_class_init,
};
static void pxa2xx_timer_register(void)
{
- sysbus_register_withprop(&pxa25x_timer_dev_info);
- sysbus_register_withprop(&pxa27x_timer_dev_info);
+ type_register_static(&pxa25x_timer_dev_info);
+ type_register_static(&pxa27x_timer_dev_info);
};
device_init(pxa2xx_timer_register);
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 5ddda2d0f4..5976dcdf47 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -18,9 +18,10 @@ static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len)
return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr);
}
-static void get_taddr(DeviceState *dev, Visitor *v, void *opaque,
+static void get_taddr(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
int64_t value;
@@ -29,9 +30,10 @@ static void get_taddr(DeviceState *dev, Visitor *v, void *opaque,
visit_type_int(v, &value, name, errp);
}
-static void set_taddr(DeviceState *dev, Visitor *v, void *opaque,
+static void set_taddr(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
new file mode 100644
index 0000000000..135c2bf237
--- /dev/null
+++ b/hw/qdev-monitor.c
@@ -0,0 +1,588 @@
+/*
+ * Dynamic device configuration and creation.
+ *
+ * Copyright (c) 2009 CodeSourcery
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qdev.h"
+#include "monitor.h"
+
+/*
+ * Aliases were a bad idea from the start. Let's keep them
+ * from spreading further.
+ */
+typedef struct QDevAlias
+{
+ const char *typename;
+ const char *alias;
+} QDevAlias;
+
+static const QDevAlias qdev_alias_table[] = {
+ { "virtio-blk-pci", "virtio-blk" },
+ { "virtio-net-pci", "virtio-net" },
+ { "virtio-serial-pci", "virtio-serial" },
+ { "virtio-balloon-pci", "virtio-balloon" },
+ { "virtio-blk-s390", "virtio-blk" },
+ { "virtio-net-s390", "virtio-net" },
+ { "virtio-serial-s390", "virtio-serial" },
+ { "lsi53c895a", "lsi" },
+ { "ich9-ahci", "ahci" },
+ { }
+};
+
+static const char *qdev_class_get_alias(DeviceClass *dc)
+{
+ const char *typename = object_class_get_name(OBJECT_CLASS(dc));
+ int i;
+
+ for (i = 0; qdev_alias_table[i].typename; i++) {
+ if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
+ return qdev_alias_table[i].alias;
+ }
+ }
+
+ return NULL;
+}
+
+static bool qdev_class_has_alias(DeviceClass *dc)
+{
+ return (qdev_class_get_alias(dc) != NULL);
+}
+
+static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+{
+ DeviceClass *dc;
+ bool *show_no_user = opaque;
+
+ dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
+
+ if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
+ return;
+ }
+
+ error_printf("name \"%s\"", object_class_get_name(klass));
+ if (dc->bus_info) {
+ error_printf(", bus %s", dc->bus_info->name);
+ }
+ if (qdev_class_has_alias(dc)) {
+ error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
+ }
+ if (dc->desc) {
+ error_printf(", desc \"%s\"", dc->desc);
+ }
+ if (dc->no_user) {
+ error_printf(", no-user");
+ }
+ error_printf("\n");
+}
+
+static int set_property(const char *name, const char *value, void *opaque)
+{
+ DeviceState *dev = opaque;
+
+ if (strcmp(name, "driver") == 0)
+ return 0;
+ if (strcmp(name, "bus") == 0)
+ return 0;
+
+ if (qdev_prop_parse(dev, name, value) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+static const char *find_typename_by_alias(const char *alias)
+{
+ int i;
+
+ for (i = 0; qdev_alias_table[i].alias; i++) {
+ if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
+ return qdev_alias_table[i].typename;
+ }
+ }
+
+ return NULL;
+}
+
+int qdev_device_help(QemuOpts *opts)
+{
+ const char *driver;
+ Property *prop;
+ ObjectClass *klass;
+ DeviceClass *info;
+
+ driver = qemu_opt_get(opts, "driver");
+ if (driver && !strcmp(driver, "?")) {
+ bool show_no_user = false;
+ object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
+ return 1;
+ }
+
+ if (!driver || !qemu_opt_get(opts, "?")) {
+ return 0;
+ }
+
+ klass = object_class_by_name(driver);
+ if (!klass) {
+ const char *typename = find_typename_by_alias(driver);
+
+ if (typename) {
+ driver = typename;
+ klass = object_class_by_name(driver);
+ }
+ }
+
+ if (!klass) {
+ return 0;
+ }
+ info = DEVICE_CLASS(klass);
+
+ for (prop = info->props; prop && prop->name; prop++) {
+ /*
+ * TODO Properties without a parser are just for dirty hacks.
+ * qdev_prop_ptr is the only such PropertyInfo. It's marked
+ * for removal. This conditional should be removed along with
+ * it.
+ */
+ if (!prop->info->parse) {
+ continue; /* no way to set it, don't show */
+ }
+ error_printf("%s.%s=%s\n", driver, prop->name,
+ prop->info->legacy_name ?: prop->info->name);
+ }
+ if (info->bus_info) {
+ for (prop = info->bus_info->props; prop && prop->name; prop++) {
+ if (!prop->info->parse) {
+ continue; /* no way to set it, don't show */
+ }
+ error_printf("%s.%s=%s\n", driver, prop->name,
+ prop->info->legacy_name ?: prop->info->name);
+ }
+ }
+ return 1;
+}
+
+static Object *qdev_get_peripheral(void)
+{
+ static Object *dev;
+
+ if (dev == NULL) {
+ dev = object_new("container");
+ object_property_add_child(object_get_root(), "peripheral",
+ OBJECT(dev), NULL);
+ }
+
+ return dev;
+}
+
+static Object *qdev_get_peripheral_anon(void)
+{
+ static Object *dev;
+
+ if (dev == NULL) {
+ dev = object_new("container");
+ object_property_add_child(object_get_root(), "peripheral-anon",
+ OBJECT(dev), NULL);
+ }
+
+ return dev;
+}
+
+static void qbus_list_bus(DeviceState *dev)
+{
+ BusState *child;
+ const char *sep = " ";
+
+ error_printf("child busses at \"%s\":",
+ dev->id ? dev->id : object_get_typename(OBJECT(dev)));
+ QLIST_FOREACH(child, &dev->child_bus, sibling) {
+ error_printf("%s\"%s\"", sep, child->name);
+ sep = ", ";
+ }
+ error_printf("\n");
+}
+
+static void qbus_list_dev(BusState *bus)
+{
+ DeviceState *dev;
+ const char *sep = " ";
+
+ error_printf("devices at \"%s\":", bus->name);
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
+ if (dev->id)
+ error_printf("/\"%s\"", dev->id);
+ sep = ", ";
+ }
+ error_printf("\n");
+}
+
+static BusState *qbus_find_bus(DeviceState *dev, char *elem)
+{
+ BusState *child;
+
+ QLIST_FOREACH(child, &dev->child_bus, sibling) {
+ if (strcmp(child->name, elem) == 0) {
+ return child;
+ }
+ }
+ return NULL;
+}
+
+static DeviceState *qbus_find_dev(BusState *bus, char *elem)
+{
+ DeviceState *dev;
+
+ /*
+ * try to match in order:
+ * (1) instance id, if present
+ * (2) driver name
+ * (3) driver alias, if present
+ */
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ if (dev->id && strcmp(dev->id, elem) == 0) {
+ return dev;
+ }
+ }
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
+ return dev;
+ }
+ }
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+ if (qdev_class_has_alias(dc) &&
+ strcmp(qdev_class_get_alias(dc), elem) == 0) {
+ return dev;
+ }
+ }
+ return NULL;
+}
+
+static BusState *qbus_find_recursive(BusState *bus, const char *name,
+ const BusInfo *info)
+{
+ DeviceState *dev;
+ BusState *child, *ret;
+ int match = 1;
+
+ if (name && (strcmp(bus->name, name) != 0)) {
+ match = 0;
+ }
+ if (info && (bus->info != info)) {
+ match = 0;
+ }
+ if (match) {
+ return bus;
+ }
+
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ QLIST_FOREACH(child, &dev->child_bus, sibling) {
+ ret = qbus_find_recursive(child, name, info);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ return NULL;
+}
+
+static BusState *qbus_find(const char *path)
+{
+ DeviceState *dev;
+ BusState *bus;
+ char elem[128];
+ int pos, len;
+
+ /* find start element */
+ if (path[0] == '/') {
+ bus = sysbus_get_default();
+ pos = 0;
+ } else {
+ if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
+ assert(!path[0]);
+ elem[0] = len = 0;
+ }
+ bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
+ if (!bus) {
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
+ return NULL;
+ }
+ pos = len;
+ }
+
+ for (;;) {
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
+ if (path[pos] == '\0') {
+ return bus;
+ }
+
+ /* find device */
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
+ }
+ pos += len;
+ dev = qbus_find_dev(bus, elem);
+ if (!dev) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_dev(bus);
+ }
+ return NULL;
+ }
+
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
+ if (path[pos] == '\0') {
+ /* last specified element is a device. If it has exactly
+ * one child bus accept it nevertheless */
+ switch (dev->num_child_bus) {
+ case 0:
+ qerror_report(QERR_DEVICE_NO_BUS, elem);
+ return NULL;
+ case 1:
+ return QLIST_FIRST(&dev->child_bus);
+ default:
+ qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
+ return NULL;
+ }
+ }
+
+ /* find bus */
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
+ }
+ pos += len;
+ bus = qbus_find_bus(dev, elem);
+ if (!bus) {
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
+ return NULL;
+ }
+ }
+}
+
+DeviceState *qdev_device_add(QemuOpts *opts)
+{
+ ObjectClass *obj;
+ DeviceClass *k;
+ const char *driver, *path, *id;
+ DeviceState *qdev;
+ BusState *bus;
+
+ driver = qemu_opt_get(opts, "driver");
+ if (!driver) {
+ qerror_report(QERR_MISSING_PARAMETER, "driver");
+ return NULL;
+ }
+
+ /* find driver */
+ obj = object_class_by_name(driver);
+ if (!obj) {
+ const char *typename = find_typename_by_alias(driver);
+
+ if (typename) {
+ driver = typename;
+ obj = object_class_by_name(driver);
+ }
+ }
+
+ if (!obj) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
+ return NULL;
+ }
+
+ k = DEVICE_CLASS(obj);
+
+ /* find bus */
+ path = qemu_opt_get(opts, "bus");
+ if (path != NULL) {
+ bus = qbus_find(path);
+ if (!bus) {
+ return NULL;
+ }
+ if (bus->info != k->bus_info) {
+ qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+ driver, bus->info->name);
+ return NULL;
+ }
+ } else {
+ bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info);
+ if (!bus) {
+ qerror_report(QERR_NO_BUS_FOR_DEVICE,
+ driver, k->bus_info->name);
+ return NULL;
+ }
+ }
+ if (qdev_hotplug && !bus->allow_hotplug) {
+ qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
+ return NULL;
+ }
+
+ if (!bus) {
+ bus = sysbus_get_default();
+ }
+
+ /* create device, set properties */
+ qdev = DEVICE(object_new(driver));
+ qdev_set_parent_bus(qdev, bus);
+ qdev_prop_set_globals(qdev);
+
+ id = qemu_opts_id(opts);
+ if (id) {
+ qdev->id = id;
+ object_property_add_child(qdev_get_peripheral(), qdev->id,
+ OBJECT(qdev), NULL);
+ } else {
+ static int anon_count;
+ gchar *name = g_strdup_printf("device[%d]", anon_count++);
+ object_property_add_child(qdev_get_peripheral_anon(), name,
+ OBJECT(qdev), NULL);
+ g_free(name);
+ }
+ if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
+ qdev_free(qdev);
+ return NULL;
+ }
+ if (qdev_init(qdev) < 0) {
+ qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+ return NULL;
+ }
+ qdev->opts = opts;
+ return qdev;
+}
+
+
+#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) {
+ /*
+ * TODO Properties without a print method are just for dirty
+ * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
+ * marked for removal. The test props->info->print should be
+ * removed along with it.
+ */
+ 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)
+{
+ BusState *child;
+ qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
+ dev->id ? dev->id : "");
+ indent += 2;
+ if (dev->num_gpio_in) {
+ qdev_printf("gpio-in %d\n", dev->num_gpio_in);
+ }
+ if (dev->num_gpio_out) {
+ qdev_printf("gpio-out %d\n", dev->num_gpio_out);
+ }
+ qdev_print_props(mon, dev, qdev_get_props(dev), "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);
+ QLIST_FOREACH(child, &dev->child_bus, sibling) {
+ qbus_print(mon, child, indent);
+ }
+}
+
+static void qbus_print(Monitor *mon, BusState *bus, int indent)
+{
+ struct DeviceState *dev;
+
+ qdev_printf("bus: %s\n", bus->name);
+ indent += 2;
+ qdev_printf("type %s\n", bus->info->name);
+ QTAILQ_FOREACH(dev, &bus->children, sibling) {
+ qdev_print(mon, dev, indent);
+ }
+}
+#undef qdev_printf
+
+void do_info_qtree(Monitor *mon)
+{
+ if (sysbus_get_default())
+ qbus_print(mon, sysbus_get_default(), 0);
+}
+
+void do_info_qdm(Monitor *mon)
+{
+ object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
+}
+
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ QemuOpts *opts;
+
+ opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
+ if (!opts) {
+ return -1;
+ }
+ if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
+ qemu_opts_del(opts);
+ return 0;
+ }
+ if (!qdev_device_add(opts)) {
+ qemu_opts_del(opts);
+ return -1;
+ }
+ return 0;
+}
+
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ const char *id = qdict_get_str(qdict, "id");
+ DeviceState *dev;
+
+ dev = qdev_find_recursive(sysbus_get_default(), id);
+ if (NULL == dev) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, id);
+ return -1;
+ }
+ return qdev_unplug(dev);
+}
+
+void qdev_machine_init(void)
+{
+ qdev_get_peripheral_anon();
+ qdev_get_peripheral();
+}
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 02f0dae0bc..c4583a14d7 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -40,9 +40,9 @@ static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
/* Bit */
static int parse_bit(DeviceState *dev, Property *prop, const char *str)
{
- if (!strncasecmp(str, "on", 2))
+ if (!strcasecmp(str, "on"))
bit_prop_set(dev, prop, true);
- else if (!strncasecmp(str, "off", 3))
+ else if (!strcasecmp(str, "off"))
bit_prop_set(dev, prop, false);
else
return -EINVAL;
@@ -55,9 +55,10 @@ static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
}
-static void get_bit(DeviceState *dev, Visitor *v, void *opaque,
+static void get_bit(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
uint32_t *p = qdev_get_prop_ptr(dev, prop);
bool value = (*p & qdev_get_prop_mask(prop)) != 0;
@@ -65,9 +66,10 @@ static void get_bit(DeviceState *dev, Visitor *v, void *opaque,
visit_type_bool(v, &value, name, errp);
}
-static void set_bit(DeviceState *dev, Visitor *v, void *opaque,
+static void set_bit(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
Error *local_err = NULL;
bool value;
@@ -118,9 +120,10 @@ static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
return snprintf(dest, len, "%" PRIu8, *ptr);
}
-static void get_int8(DeviceState *dev, Visitor *v, void *opaque,
+static void get_int8(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int8_t *ptr = qdev_get_prop_ptr(dev, prop);
int64_t value;
@@ -129,9 +132,10 @@ static void get_int8(DeviceState *dev, Visitor *v, void *opaque,
visit_type_int(v, &value, name, errp);
}
-static void set_int8(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void set_int8(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int8_t *ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
@@ -224,9 +228,10 @@ static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len
return snprintf(dest, len, "%" PRIu16, *ptr);
}
-static void get_int16(DeviceState *dev, Visitor *v, void *opaque,
+static void get_int16(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int16_t *ptr = qdev_get_prop_ptr(dev, prop);
int64_t value;
@@ -235,9 +240,10 @@ static void get_int16(DeviceState *dev, Visitor *v, void *opaque,
visit_type_int(v, &value, name, errp);
}
-static void set_int16(DeviceState *dev, Visitor *v, void *opaque,
+static void set_int16(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int16_t *ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
@@ -296,9 +302,10 @@ static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len
return snprintf(dest, len, "%" PRIu32, *ptr);
}
-static void get_int32(DeviceState *dev, Visitor *v, void *opaque,
+static void get_int32(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
int64_t value;
@@ -307,9 +314,10 @@ static void get_int32(DeviceState *dev, Visitor *v, void *opaque,
visit_type_int(v, &value, name, errp);
}
-static void set_int32(DeviceState *dev, Visitor *v, void *opaque,
+static void set_int32(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
@@ -433,18 +441,20 @@ static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len
return snprintf(dest, len, "%" PRIu64, *ptr);
}
-static void get_int64(DeviceState *dev, Visitor *v, void *opaque,
+static void get_int64(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int64_t *ptr = qdev_get_prop_ptr(dev, prop);
visit_type_int(v, ptr, name, errp);
}
-static void set_int64(DeviceState *dev, Visitor *v, void *opaque,
+static void set_int64(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int64_t *ptr = qdev_get_prop_ptr(dev, prop);
@@ -523,9 +533,10 @@ static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len
return snprintf(dest, len, "\"%s\"", *ptr);
}
-static void get_string(DeviceState *dev, Visitor *v, void *opaque,
+static void get_string(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
char **ptr = qdev_get_prop_ptr(dev, prop);
@@ -537,9 +548,10 @@ static void get_string(DeviceState *dev, Visitor *v, void *opaque,
}
}
-static void set_string(DeviceState *dev, Visitor *v, void *opaque,
+static void set_string(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
char **ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
@@ -609,9 +621,10 @@ static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
*ptr ? bdrv_get_device_name(*ptr) : "<null>");
}
-static void get_generic(DeviceState *dev, Visitor *v, void *opaque,
+static void get_generic(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
void **ptr = qdev_get_prop_ptr(dev, prop);
char buffer[1024];
@@ -624,9 +637,10 @@ static void get_generic(DeviceState *dev, Visitor *v, void *opaque,
visit_type_str(v, &p, name, errp);
}
-static void set_generic(DeviceState *dev, Visitor *v, void *opaque,
+static void set_generic(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
Error *local_err = NULL;
char *str;
@@ -774,9 +788,10 @@ static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
}
}
-static void get_vlan(DeviceState *dev, Visitor *v, void *opaque,
+static void get_vlan(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
VLANState **ptr = qdev_get_prop_ptr(dev, prop);
int64_t id;
@@ -785,9 +800,10 @@ static void get_vlan(DeviceState *dev, Visitor *v, void *opaque,
visit_type_int(v, &id, name, errp);
}
-static void set_vlan(DeviceState *dev, Visitor *v, void *opaque,
+static void set_vlan(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
VLANState **ptr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
@@ -885,6 +901,55 @@ PropertyInfo qdev_prop_macaddr = {
.set = set_generic,
};
+
+/* --- lost tick policy --- */
+
+static const struct {
+ const char *name;
+ LostTickPolicy code;
+} lost_tick_policy_table[] = {
+ { .name = "discard", .code = LOST_TICK_DISCARD },
+ { .name = "delay", .code = LOST_TICK_DELAY },
+ { .name = "merge", .code = LOST_TICK_MERGE },
+ { .name = "slew", .code = LOST_TICK_SLEW },
+};
+
+static int parse_lost_tick_policy(DeviceState *dev, Property *prop,
+ const char *str)
+{
+ LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lost_tick_policy_table); i++) {
+ if (!strcasecmp(str, lost_tick_policy_table[i].name)) {
+ *ptr = lost_tick_policy_table[i].code;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(lost_tick_policy_table)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int print_lost_tick_policy(DeviceState *dev, Property *prop, char *dest,
+ size_t len)
+{
+ LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
+
+ return snprintf(dest, len, "%s", lost_tick_policy_table[*ptr].name);
+}
+
+PropertyInfo qdev_prop_losttickpolicy = {
+ .name = "lost_tick_policy",
+ .type = PROP_TYPE_LOSTTICKPOLICY,
+ .size = sizeof(LostTickPolicy),
+ .parse = parse_lost_tick_policy,
+ .print = print_lost_tick_policy,
+ .get = get_generic,
+ .set = set_generic,
+};
+
/* --- pci address --- */
/*
@@ -922,9 +987,10 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t
}
}
-static void get_pci_devfn(DeviceState *dev, Visitor *v, void *opaque,
+static void get_pci_devfn(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
char buffer[32];
@@ -966,7 +1032,7 @@ static Property *qdev_prop_find(DeviceState *dev, const char *name)
Property *prop;
/* device properties */
- prop = qdev_prop_walk(dev->info->props, name);
+ prop = qdev_prop_walk(qdev_get_props(dev), name);
if (prop)
return prop;
@@ -989,16 +1055,16 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
switch (ret) {
case -EEXIST:
error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
- dev->info->name, prop->name, value);
+ object_get_typename(OBJECT(dev)), prop->name, value);
break;
default:
case -EINVAL:
error_set(errp, QERR_PROPERTY_VALUE_BAD,
- dev->info->name, prop->name, value);
+ object_get_typename(OBJECT(dev)), prop->name, value);
break;
case -ENOENT:
error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
- dev->info->name, prop->name, value);
+ object_get_typename(OBJECT(dev)), prop->name, value);
break;
case 0:
break;
@@ -1018,7 +1084,7 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
* removed along with it.
*/
if (!prop || !prop->info->parse) {
- qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name);
+ qerror_report(QERR_PROPERTY_NOT_FOUND, object_get_typename(OBJECT(dev)), name);
return -1;
}
ret = prop->info->parse(dev, prop, value);
@@ -1039,12 +1105,12 @@ void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyT
prop = qdev_prop_find(dev, name);
if (!prop) {
fprintf(stderr, "%s: property \"%s.%s\" not found\n",
- __FUNCTION__, dev->info->name, name);
+ __FUNCTION__, object_get_typename(OBJECT(dev)), name);
abort();
}
if (prop->info->type != type) {
fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
- __FUNCTION__, dev->info->name, name);
+ __FUNCTION__, object_get_typename(OBJECT(dev)), name);
abort();
}
qdev_prop_cpy(dev, prop, src);
@@ -1093,7 +1159,7 @@ int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *va
if (res < 0) {
error_report("Can't attach drive %s to %s.%s: %s",
bdrv_get_device_name(value),
- dev->id ? dev->id : dev->info->name,
+ dev->id ? dev->id : object_get_typename(OBJECT(dev)),
name, strerror(-res));
return -1;
}
@@ -1127,6 +1193,12 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
}
+void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
+ LostTickPolicy *value)
+{
+ qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
+}
+
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
@@ -1165,8 +1237,8 @@ void qdev_prop_set_globals(DeviceState *dev)
GlobalProperty *prop;
QTAILQ_FOREACH(prop, &global_props, next) {
- if (strcmp(dev->info->name, prop->driver) != 0 &&
- strcmp(dev->info->bus_info->name, prop->driver) != 0) {
+ if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
+ strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
continue;
}
if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
diff --git a/hw/qdev.c b/hw/qdev.c
index e59f3455d7..e3b53b7f62 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -28,9 +28,8 @@
#include "net.h"
#include "qdev.h"
#include "sysemu.h"
-#include "monitor.h"
-static int qdev_hotplug = 0;
+int qdev_hotplug = 0;
static bool qdev_hot_added = false;
static bool qdev_hot_removed = false;
@@ -38,86 +37,60 @@ static bool qdev_hot_removed = false;
static BusState *main_system_bus;
static void main_system_bus_create(void);
-DeviceInfo *device_info_list;
-
-static BusState *qbus_find_recursive(BusState *bus, const char *name,
- const BusInfo *info);
-static BusState *qbus_find(const char *path);
-
/* Register a new device type. */
-void qdev_register(DeviceInfo *info)
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ return dc->vmsd;
+}
+
+BusInfo *qdev_get_bus_info(DeviceState *dev)
{
- assert(info->size >= sizeof(DeviceState));
- assert(!info->next);
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ return dc->bus_info;
+}
- info->next = device_info_list;
- device_info_list = info;
+Property *qdev_get_props(DeviceState *dev)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+ return dc->props;
}
-static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
+const char *qdev_fw_name(DeviceState *dev)
{
- 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;
- if (strcmp(info->name, name) != 0)
- continue;
- return info;
- }
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
- /* 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;
+ if (dc->fw_name) {
+ return dc->fw_name;
}
- return NULL;
+
+ return object_get_typename(OBJECT(dev));
+}
+
+bool qdev_exists(const char *name)
+{
+ return !!object_class_by_name(name);
}
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
Error **errp);
-static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
{
- DeviceState *dev;
Property *prop;
- assert(bus->info == info->bus_info);
- dev = g_malloc0(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);
- qdev_prop_set_globals(dev);
- QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
if (qdev_hotplug) {
assert(bus->allow_hotplug);
- dev->hotplugged = 1;
- qdev_hot_added = true;
}
- dev->instance_id_alias = -1;
- QTAILQ_INIT(&dev->properties);
- dev->state = DEV_STATE_CREATED;
- for (prop = dev->info->props; prop && prop->name; prop++) {
- qdev_property_add_legacy(dev, prop, NULL);
- qdev_property_add_static(dev, prop, NULL);
- }
+ dev->parent_bus = bus;
+ QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
- for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
+ qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
+ for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
qdev_property_add_static(dev, prop, NULL);
}
-
- qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
-
- return dev;
}
/* Create a new device. This only initializes the device state structure
@@ -142,197 +115,23 @@ DeviceState *qdev_create(BusState *bus, const char *name)
DeviceState *qdev_try_create(BusState *bus, const char *name)
{
- DeviceInfo *info;
-
- if (!bus) {
- bus = sysbus_get_default();
- }
+ DeviceState *dev;
- info = qdev_find_info(bus->info, name);
- if (!info) {
+ dev = DEVICE(object_new(name));
+ if (!dev) {
return NULL;
}
- return qdev_create_from_info(bus, info);
-}
-
-static void qdev_print_devinfo(DeviceInfo *info)
-{
- error_printf("name \"%s\", bus %s",
- info->name, info->bus_info->name);
- if (info->alias) {
- error_printf(", alias \"%s\"", info->alias);
- }
- if (info->desc) {
- error_printf(", desc \"%s\"", info->desc);
- }
- if (info->no_user) {
- error_printf(", no-user");
- }
- error_printf("\n");
-}
-
-static int set_property(const char *name, const char *value, void *opaque)
-{
- DeviceState *dev = opaque;
-
- if (strcmp(name, "driver") == 0)
- return 0;
- if (strcmp(name, "bus") == 0)
- return 0;
-
- if (qdev_prop_parse(dev, name, value) == -1) {
- return -1;
- }
- return 0;
-}
-
-int qdev_device_help(QemuOpts *opts)
-{
- const char *driver;
- DeviceInfo *info;
- Property *prop;
-
- driver = qemu_opt_get(opts, "driver");
- if (driver && !strcmp(driver, "?")) {
- for (info = device_info_list; info != NULL; info = info->next) {
- if (info->no_user) {
- continue; /* not available, don't show */
- }
- qdev_print_devinfo(info);
- }
- return 1;
- }
-
- if (!driver || !qemu_opt_get(opts, "?")) {
- return 0;
- }
-
- info = qdev_find_info(NULL, driver);
- if (!info) {
- return 0;
- }
-
- for (prop = info->props; prop && prop->name; prop++) {
- /*
- * TODO Properties without a parser are just for dirty hacks.
- * qdev_prop_ptr is the only such PropertyInfo. It's marked
- * for removal. This conditional should be removed along with
- * it.
- */
- if (!prop->info->parse) {
- continue; /* no way to set it, don't show */
- }
- error_printf("%s.%s=%s\n", info->name, prop->name,
- prop->info->legacy_name ?: prop->info->name);
- }
- for (prop = info->bus_info->props; prop && prop->name; prop++) {
- if (!prop->info->parse) {
- continue; /* no way to set it, don't show */
- }
- error_printf("%s.%s=%s\n", info->name, prop->name,
- prop->info->legacy_name ?: prop->info->name);
- }
- return 1;
-}
-
-static DeviceState *qdev_get_peripheral(void)
-{
- static DeviceState *dev;
-
- if (dev == NULL) {
- dev = qdev_create(NULL, "container");
- qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
- qdev_init_nofail(dev);
+ if (!bus) {
+ bus = sysbus_get_default();
}
- return dev;
-}
-
-static DeviceState *qdev_get_peripheral_anon(void)
-{
- static DeviceState *dev;
-
- if (dev == NULL) {
- dev = qdev_create(NULL, "container");
- qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
- qdev_init_nofail(dev);
- }
+ qdev_set_parent_bus(dev, bus);
+ qdev_prop_set_globals(dev);
return dev;
}
-DeviceState *qdev_device_add(QemuOpts *opts)
-{
- const char *driver, *path, *id;
- DeviceInfo *info;
- DeviceState *qdev;
- BusState *bus;
-
- driver = qemu_opt_get(opts, "driver");
- if (!driver) {
- qerror_report(QERR_MISSING_PARAMETER, "driver");
- return NULL;
- }
-
- /* find driver */
- info = qdev_find_info(NULL, driver);
- if (!info || info->no_user) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
- error_printf_unless_qmp("Try with argument '?' for a list.\n");
- return NULL;
- }
-
- /* find bus */
- path = qemu_opt_get(opts, "bus");
- if (path != NULL) {
- bus = qbus_find(path);
- if (!bus) {
- return NULL;
- }
- if (bus->info != info->bus_info) {
- qerror_report(QERR_BAD_BUS_FOR_DEVICE,
- driver, bus->info->name);
- return NULL;
- }
- } else {
- bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
- if (!bus) {
- qerror_report(QERR_NO_BUS_FOR_DEVICE,
- info->name, info->bus_info->name);
- return NULL;
- }
- }
- if (qdev_hotplug && !bus->allow_hotplug) {
- qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
- return NULL;
- }
-
- /* create device, set properties */
- qdev = qdev_create_from_info(bus, info);
- id = qemu_opts_id(opts);
- if (id) {
- qdev->id = id;
- qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
- } else {
- static int anon_count;
- gchar *name = g_strdup_printf("device[%d]", anon_count++);
- qdev_property_add_child(qdev_get_peripheral_anon(), name,
- qdev, NULL);
- g_free(name);
- }
- if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
- qdev_free(qdev);
- return NULL;
- }
- if (qdev_init(qdev) < 0) {
- qerror_report(QERR_DEVICE_INIT_FAILED, driver);
- return NULL;
- }
- qdev->opts = opts;
- 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.
@@ -340,22 +139,24 @@ DeviceState *qdev_device_add(QemuOpts *opts)
Return 0 on success. */
int qdev_init(DeviceState *dev)
{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
int rc;
assert(dev->state == DEV_STATE_CREATED);
- rc = dev->info->init(dev, dev->info);
+
+ rc = dc->init(dev);
if (rc < 0) {
qdev_free(dev);
return rc;
}
- if (dev->info->vmsd) {
- vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
+ if (qdev_get_vmsd(dev)) {
+ vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
dev->instance_id_alias,
dev->alias_required_for_version);
}
dev->state = DEV_STATE_INITIALIZED;
- if (dev->hotplugged && dev->info->reset) {
- dev->info->reset(dev);
+ if (dev->hotplugged) {
+ device_reset(dev);
}
return 0;
}
@@ -370,22 +171,22 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int qdev_unplug(DeviceState *dev)
{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
if (!dev->parent_bus->allow_hotplug) {
qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
return -1;
}
- assert(dev->info->unplug != NULL);
+ assert(dc->unplug != NULL);
qdev_hot_removed = true;
- return dev->info->unplug(dev);
+ return dc->unplug(dev);
}
static int qdev_reset_one(DeviceState *dev, void *opaque)
{
- if (dev->info->reset) {
- dev->info->reset(dev);
- }
+ device_reset(dev);
return 0;
}
@@ -421,6 +222,7 @@ void qbus_reset_all_fn(void *opaque)
int qdev_simple_unplug_cb(DeviceState *dev)
{
/* just zap it */
+ object_unparent(OBJECT(dev));
qdev_free(dev);
return 0;
}
@@ -435,87 +237,17 @@ int qdev_simple_unplug_cb(DeviceState *dev)
way is somewhat unclean, and best avoided. */
void qdev_init_nofail(DeviceState *dev)
{
- DeviceInfo *info = dev->info;
-
if (qdev_init(dev) < 0) {
- error_report("Initialization of device %s failed", info->name);
+ error_report("Initialization of device %s failed",
+ object_get_typename(OBJECT(dev)));
exit(1);
}
}
-static void qdev_property_del_all(DeviceState *dev)
-{
- while (!QTAILQ_EMPTY(&dev->properties)) {
- DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
-
- QTAILQ_REMOVE(&dev->properties, prop, node);
-
- if (prop->release) {
- prop->release(dev, prop->name, prop->opaque);
- }
-
- g_free(prop->name);
- g_free(prop->type);
- g_free(prop);
- }
-}
-
-static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
-{
- DeviceProperty *prop;
-
- QTAILQ_FOREACH(prop, &dev->properties, node) {
- if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
- break;
- }
- }
-
- g_assert(prop != NULL);
-
- QTAILQ_REMOVE(&dev->properties, prop, node);
-
- if (prop->release) {
- prop->release(dev, prop->name, prop->opaque);
- }
-
- g_free(prop->name);
- g_free(prop->type);
- g_free(prop);
-}
-
/* Unlink device from bus and free the structure. */
void qdev_free(DeviceState *dev)
{
- BusState *bus;
- Property *prop;
-
- qdev_property_del_all(dev);
-
- if (dev->state == DEV_STATE_INITIALIZED) {
- while (dev->num_child_bus) {
- bus = QLIST_FIRST(&dev->child_bus);
- qbus_free(bus);
- }
- if (dev->info->vmsd)
- vmstate_unregister(dev, dev->info->vmsd, dev);
- if (dev->info->exit)
- dev->info->exit(dev);
- if (dev->opts)
- qemu_opts_del(dev->opts);
- }
- QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
- for (prop = dev->info->props; prop && prop->name; prop++) {
- if (prop->info->free) {
- prop->info->free(dev, prop);
- }
- }
- if (dev->parent) {
- qdev_property_del_child(dev->parent, dev, NULL);
- }
- if (dev->ref != 0) {
- qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
- }
- g_free(dev);
+ object_delete(OBJECT(dev));
}
void qdev_machine_creation_done(void)
@@ -532,15 +264,6 @@ bool qdev_machine_modified(void)
return qdev_hot_added || qdev_hot_removed;
}
-/* Get a character (serial) device interface. */
-CharDriverState *qdev_init_chardev(DeviceState *dev)
-{
- static int next_serial;
-
- /* FIXME: This function needs to go away: use chardev properties! */
- return serial_hds[next_serial++];
-}
-
BusState *qdev_get_parent_bus(DeviceState *dev)
{
return dev->parent_bus;
@@ -644,34 +367,6 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
return 0;
}
-static BusState *qbus_find_recursive(BusState *bus, const char *name,
- const BusInfo *info)
-{
- DeviceState *dev;
- BusState *child, *ret;
- int match = 1;
-
- if (name && (strcmp(bus->name, name) != 0)) {
- match = 0;
- }
- if (info && (bus->info != info)) {
- match = 0;
- }
- if (match) {
- return bus;
- }
-
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- QLIST_FOREACH(child, &dev->child_bus, sibling) {
- ret = qbus_find_recursive(child, name, info);
- if (ret) {
- return ret;
- }
- }
- }
- return NULL;
-}
-
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
{
DeviceState *dev, *ret;
@@ -690,162 +385,6 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
return NULL;
}
-static void qbus_list_bus(DeviceState *dev)
-{
- BusState *child;
- const char *sep = " ";
-
- error_printf("child busses at \"%s\":",
- dev->id ? dev->id : dev->info->name);
- QLIST_FOREACH(child, &dev->child_bus, sibling) {
- error_printf("%s\"%s\"", sep, child->name);
- sep = ", ";
- }
- error_printf("\n");
-}
-
-static void qbus_list_dev(BusState *bus)
-{
- DeviceState *dev;
- const char *sep = " ";
-
- error_printf("devices at \"%s\":", bus->name);
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- error_printf("%s\"%s\"", sep, dev->info->name);
- if (dev->id)
- error_printf("/\"%s\"", dev->id);
- sep = ", ";
- }
- error_printf("\n");
-}
-
-static BusState *qbus_find_bus(DeviceState *dev, char *elem)
-{
- BusState *child;
-
- QLIST_FOREACH(child, &dev->child_bus, sibling) {
- if (strcmp(child->name, elem) == 0) {
- return child;
- }
- }
- return NULL;
-}
-
-static DeviceState *qbus_find_dev(BusState *bus, char *elem)
-{
- DeviceState *dev;
-
- /*
- * try to match in order:
- * (1) instance id, if present
- * (2) driver name
- * (3) driver alias, if present
- */
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (dev->id && strcmp(dev->id, elem) == 0) {
- return dev;
- }
- }
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (strcmp(dev->info->name, elem) == 0) {
- return dev;
- }
- }
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
- return dev;
- }
- }
- return NULL;
-}
-
-static BusState *qbus_find(const char *path)
-{
- DeviceState *dev;
- BusState *bus;
- char elem[128];
- int pos, len;
-
- /* find start element */
- if (path[0] == '/') {
- bus = main_system_bus;
- pos = 0;
- } else {
- if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
- assert(!path[0]);
- elem[0] = len = 0;
- }
- bus = qbus_find_recursive(main_system_bus, elem, NULL);
- if (!bus) {
- qerror_report(QERR_BUS_NOT_FOUND, elem);
- return NULL;
- }
- pos = len;
- }
-
- for (;;) {
- assert(path[pos] == '/' || !path[pos]);
- while (path[pos] == '/') {
- pos++;
- }
- if (path[pos] == '\0') {
- return bus;
- }
-
- /* find device */
- if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
- assert(0);
- elem[0] = len = 0;
- }
- pos += len;
- dev = qbus_find_dev(bus, elem);
- if (!dev) {
- qerror_report(QERR_DEVICE_NOT_FOUND, elem);
- if (!monitor_cur_is_qmp()) {
- qbus_list_dev(bus);
- }
- return NULL;
- }
-
- assert(path[pos] == '/' || !path[pos]);
- while (path[pos] == '/') {
- pos++;
- }
- if (path[pos] == '\0') {
- /* last specified element is a device. If it has exactly
- * one child bus accept it nevertheless */
- switch (dev->num_child_bus) {
- case 0:
- qerror_report(QERR_DEVICE_NO_BUS, elem);
- return NULL;
- case 1:
- return QLIST_FIRST(&dev->child_bus);
- default:
- qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
- if (!monitor_cur_is_qmp()) {
- qbus_list_bus(dev);
- }
- return NULL;
- }
- }
-
- /* find bus */
- if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
- assert(0);
- elem[0] = len = 0;
- }
- pos += len;
- bus = qbus_find_bus(dev, elem);
- if (!bus) {
- qerror_report(QERR_BUS_NOT_FOUND, elem);
- if (!monitor_cur_is_qmp()) {
- qbus_list_bus(dev);
- }
- return NULL;
- }
- }
-}
-
void qbus_create_inplace(BusState *bus, BusInfo *info,
DeviceState *parent, const char *name)
{
@@ -926,112 +465,6 @@ void qbus_free(BusState *bus)
}
}
-#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) {
- /*
- * TODO Properties without a print method are just for dirty
- * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
- * marked for removal. The test props->info->print should be
- * removed along with it.
- */
- 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)
-{
- BusState *child;
- qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
- dev->id ? dev->id : "");
- indent += 2;
- if (dev->num_gpio_in) {
- qdev_printf("gpio-in %d\n", dev->num_gpio_in);
- }
- if (dev->num_gpio_out) {
- qdev_printf("gpio-out %d\n", dev->num_gpio_out);
- }
- 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);
- QLIST_FOREACH(child, &dev->child_bus, sibling) {
- qbus_print(mon, child, indent);
- }
-}
-
-static void qbus_print(Monitor *mon, BusState *bus, int indent)
-{
- struct DeviceState *dev;
-
- qdev_printf("bus: %s\n", bus->name);
- indent += 2;
- qdev_printf("type %s\n", bus->info->name);
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- qdev_print(mon, dev, indent);
- }
-}
-#undef qdev_printf
-
-void do_info_qtree(Monitor *mon)
-{
- if (main_system_bus)
- qbus_print(mon, main_system_bus, 0);
-}
-
-void do_info_qdm(Monitor *mon)
-{
- DeviceInfo *info;
-
- for (info = device_info_list; info != NULL; info = info->next) {
- qdev_print_devinfo(info);
- }
-}
-
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- QemuOpts *opts;
-
- opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
- if (!opts) {
- return -1;
- }
- if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
- qemu_opts_del(opts);
- return 0;
- }
- if (!qdev_device_add(opts)) {
- qemu_opts_del(opts);
- return -1;
- }
- return 0;
-}
-
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- const char *id = qdict_get_str(qdict, "id");
- DeviceState *dev;
-
- dev = qdev_find_recursive(main_system_bus, id);
- if (NULL == dev) {
- qerror_report(QERR_DEVICE_NOT_FOUND, id);
- return -1;
- }
- return qdev_unplug(dev);
-}
-
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
{
int l = 0;
@@ -1044,7 +477,7 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
l += snprintf(p + l, size - l, "%s", d);
g_free(d);
} else {
- l += snprintf(p + l, size - l, "%s", dev->info->name);
+ l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
}
}
l += snprintf(p + l , size - l, "/");
@@ -1064,106 +497,19 @@ char* qdev_get_fw_dev_path(DeviceState *dev)
return strdup(path);
}
-char *qdev_get_type(DeviceState *dev, Error **errp)
+static char *qdev_get_type(Object *obj, Error **errp)
{
- return g_strdup(dev->info->name);
-}
-
-void qdev_ref(DeviceState *dev)
-{
- dev->ref++;
-}
-
-void qdev_unref(DeviceState *dev)
-{
- g_assert(dev->ref > 0);
- dev->ref--;
-}
-
-void qdev_property_add(DeviceState *dev, const char *name, const char *type,
- DevicePropertyAccessor *get, DevicePropertyAccessor *set,
- DevicePropertyRelease *release,
- void *opaque, Error **errp)
-{
- DeviceProperty *prop = g_malloc0(sizeof(*prop));
-
- prop->name = g_strdup(name);
- prop->type = g_strdup(type);
-
- prop->get = get;
- prop->set = set;
- prop->release = release;
- prop->opaque = opaque;
-
- QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
-}
-
-static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
-{
- DeviceProperty *prop;
-
- QTAILQ_FOREACH(prop, &dev->properties, node) {
- if (strcmp(prop->name, name) == 0) {
- return prop;
- }
- }
-
- return NULL;
-}
-
-void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
- Error **errp)
-{
- DeviceProperty *prop = qdev_property_find(dev, name);
-
- if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
- return;
- }
-
- if (!prop->get) {
- error_set(errp, QERR_PERMISSION_DENIED);
- } else {
- prop->get(dev, v, prop->opaque, name, errp);
- }
-}
-
-void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
- Error **errp)
-{
- DeviceProperty *prop = qdev_property_find(dev, name);
-
- if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
- return;
- }
-
- if (!prop->set) {
- error_set(errp, QERR_PERMISSION_DENIED);
- } else {
- prop->set(dev, v, prop->opaque, name, errp);
- }
-}
-
-const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
-{
- DeviceProperty *prop = qdev_property_find(dev, name);
-
- if (prop == NULL) {
- error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
- return NULL;
- }
-
- return prop->type;
+ return g_strdup(object_get_typename(obj));
}
/**
* Legacy property handling
*/
-static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
char buffer[1024];
@@ -1173,9 +519,10 @@ static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
visit_type_str(v, &ptr, name, errp);
}
-static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
+static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
Error *local_err = NULL;
char *ptr = NULL;
@@ -1215,11 +562,11 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
type = g_strdup_printf("legacy<%s>",
prop->info->legacy_name ?: prop->info->name);
- qdev_property_add(dev, name, type,
- prop->info->print ? qdev_get_legacy_property : NULL,
- prop->info->parse ? qdev_set_legacy_property : NULL,
- NULL,
- prop, errp);
+ object_property_add(OBJECT(dev), name, type,
+ prop->info->print ? qdev_get_legacy_property : NULL,
+ prop->info->parse ? qdev_set_legacy_property : NULL,
+ NULL,
+ prop, errp);
g_free(type);
g_free(name);
@@ -1234,337 +581,87 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
void qdev_property_add_static(DeviceState *dev, Property *prop,
Error **errp)
{
- qdev_property_add(dev, prop->name, prop->info->name,
- prop->info->get, prop->info->set,
- NULL,
- prop, errp);
-}
-
-DeviceState *qdev_get_root(void)
-{
- static DeviceState *qdev_root;
-
- if (!qdev_root) {
- qdev_root = qdev_create(NULL, "container");
- qdev_init_nofail(qdev_root);
- }
-
- return qdev_root;
-}
-
-static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState *child = opaque;
- gchar *path;
-
- path = qdev_get_canonical_path(child);
- visit_type_str(v, &path, name, errp);
- g_free(path);
+ object_property_add(OBJECT(dev), prop->name, prop->info->name,
+ prop->info->get, prop->info->set,
+ NULL,
+ prop, errp);
}
-static void qdev_release_child_property(DeviceState *dev, const char *name,
- void *opaque)
+static void device_initfn(Object *obj)
{
- DeviceState *child = opaque;
-
- qdev_unref(child);
-}
-
-void qdev_property_add_child(DeviceState *dev, const char *name,
- DeviceState *child, Error **errp)
-{
- gchar *type;
-
- type = g_strdup_printf("child<%s>", child->info->name);
-
- qdev_property_add(dev, name, type, qdev_get_child_property,
- NULL, qdev_release_child_property,
- child, errp);
-
- qdev_ref(child);
- g_assert(child->parent == NULL);
- child->parent = dev;
-
- g_free(type);
-}
-
-static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState **child = opaque;
- gchar *path;
-
- if (*child) {
- path = qdev_get_canonical_path(*child);
- visit_type_str(v, &path, name, errp);
- g_free(path);
- } else {
- path = (gchar *)"";
- visit_type_str(v, &path, name, errp);
- }
-}
-
-static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState **child = opaque;
- bool ambiguous = false;
- const char *type;
- char *path;
-
- type = qdev_property_get_type(dev, name, NULL);
-
- visit_type_str(v, &path, name, errp);
-
- if (*child) {
- qdev_unref(*child);
- }
-
- if (strcmp(path, "") != 0) {
- DeviceState *target;
-
- target = qdev_resolve_path(path, &ambiguous);
- if (target) {
- gchar *target_type;
-
- target_type = g_strdup_printf("link<%s>", target->info->name);
- if (strcmp(target_type, type) == 0) {
- *child = target;
- qdev_ref(target);
- } else {
- error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
- }
+ DeviceState *dev = DEVICE(obj);
+ Property *prop;
- g_free(target_type);
- } else {
- error_set(errp, QERR_DEVICE_NOT_FOUND, path);
- }
- } else {
- *child = NULL;
+ if (qdev_hotplug) {
+ dev->hotplugged = 1;
+ qdev_hot_added = true;
}
- g_free(path);
-}
-
-void qdev_property_add_link(DeviceState *dev, const char *name,
- const char *type, DeviceState **child,
- Error **errp)
-{
- gchar *full_type;
-
- full_type = g_strdup_printf("link<%s>", type);
-
- qdev_property_add(dev, name, full_type,
- qdev_get_link_property,
- qdev_set_link_property,
- NULL, child, errp);
-
- g_free(full_type);
-}
-
-gchar *qdev_get_canonical_path(DeviceState *dev)
-{
- DeviceState *root = qdev_get_root();
- char *newpath = NULL, *path = NULL;
-
- while (dev != root) {
- DeviceProperty *prop = NULL;
-
- g_assert(dev->parent != NULL);
-
- QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
- continue;
- }
-
- if (prop->opaque == dev) {
- if (path) {
- newpath = g_strdup_printf("%s/%s", prop->name, path);
- g_free(path);
- path = newpath;
- } else {
- path = g_strdup(prop->name);
- }
- break;
- }
- }
-
- g_assert(prop != NULL);
+ dev->instance_id_alias = -1;
+ dev->state = DEV_STATE_CREATED;
- dev = dev->parent;
+ qdev_prop_set_defaults(dev, qdev_get_props(dev));
+ for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
+ qdev_property_add_legacy(dev, prop, NULL);
+ qdev_property_add_static(dev, prop, NULL);
}
- newpath = g_strdup_printf("/%s", path);
- g_free(path);
-
- return newpath;
+ object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
}
-static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
- gchar **parts,
- int index)
+/* Unlink device from bus and free the structure. */
+static void device_finalize(Object *obj)
{
- DeviceProperty *prop;
- DeviceState *child;
-
- if (parts[index] == NULL) {
- return parent;
- }
-
- if (strcmp(parts[index], "") == 0) {
- return qdev_resolve_abs_path(parent, parts, index + 1);
- }
-
- prop = qdev_property_find(parent, parts[index]);
- if (prop == NULL) {
- return NULL;
- }
+ DeviceState *dev = DEVICE(obj);
+ BusState *bus;
+ Property *prop;
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
- child = NULL;
- if (strstart(prop->type, "link<", NULL)) {
- DeviceState **pchild = prop->opaque;
- if (*pchild) {
- child = *pchild;
+ if (dev->state == DEV_STATE_INITIALIZED) {
+ while (dev->num_child_bus) {
+ bus = QLIST_FIRST(&dev->child_bus);
+ qbus_free(bus);
}
- } else if (strstart(prop->type, "child<", NULL)) {
- child = prop->opaque;
- }
-
- if (!child) {
- return NULL;
- }
-
- return qdev_resolve_abs_path(child, parts, index + 1);
-}
-
-static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
- gchar **parts,
- bool *ambiguous)
-{
- DeviceState *dev;
- DeviceProperty *prop;
-
- dev = qdev_resolve_abs_path(parent, parts, 0);
-
- QTAILQ_FOREACH(prop, &parent->properties, node) {
- DeviceState *found;
-
- if (!strstart(prop->type, "child<", NULL)) {
- continue;
+ if (qdev_get_vmsd(dev)) {
+ vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
}
-
- found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
- if (found) {
- if (dev) {
- if (ambiguous) {
- *ambiguous = true;
- }
- return NULL;
- }
- dev = found;
+ if (dc->exit) {
+ dc->exit(dev);
}
-
- if (ambiguous && *ambiguous) {
- return NULL;
+ if (dev->opts) {
+ qemu_opts_del(dev->opts);
}
}
-
- return dev;
-}
-
-DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
-{
- bool partial_path = true;
- DeviceState *dev;
- gchar **parts;
-
- parts = g_strsplit(path, "/", 0);
- if (parts == NULL || parts[0] == NULL) {
- g_strfreev(parts);
- return qdev_get_root();
- }
-
- if (strcmp(parts[0], "") == 0) {
- partial_path = false;
- }
-
- if (partial_path) {
- if (ambiguous) {
- *ambiguous = false;
+ QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
+ for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
+ if (prop->info->free) {
+ prop->info->free(dev, prop);
}
- dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
- } else {
- dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
- }
-
- g_strfreev(parts);
-
- return dev;
-}
-
-typedef struct StringProperty
-{
- char *(*get)(DeviceState *, Error **);
- void (*set)(DeviceState *, const char *, Error **);
-} StringProperty;
-
-static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- StringProperty *prop = opaque;
- char *value;
-
- value = prop->get(dev, errp);
- if (value) {
- visit_type_str(v, &value, name, errp);
- g_free(value);
}
}
-static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
- const char *name, Error **errp)
+void device_reset(DeviceState *dev)
{
- StringProperty *prop = opaque;
- char *value;
- Error *local_err = NULL;
+ DeviceClass *klass = DEVICE_GET_CLASS(dev);
- visit_type_str(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ if (klass->reset) {
+ klass->reset(dev);
}
-
- prop->set(dev, value, errp);
- g_free(value);
}
-static void qdev_property_release_str(DeviceState *dev, const char *name,
- void *opaque)
-{
- StringProperty *prop = opaque;
- g_free(prop);
-}
+static TypeInfo device_type_info = {
+ .name = TYPE_DEVICE,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(DeviceState),
+ .instance_init = device_initfn,
+ .instance_finalize = device_finalize,
+ .abstract = true,
+ .class_size = sizeof(DeviceClass),
+};
-void qdev_property_add_str(DeviceState *dev, const char *name,
- char *(*get)(DeviceState *, Error **),
- void (*set)(DeviceState *, const char *, Error **),
- Error **errp)
+static void init_qdev(void)
{
- StringProperty *prop = g_malloc0(sizeof(*prop));
-
- prop->get = get;
- prop->set = set;
-
- qdev_property_add(dev, name, "string",
- get ? qdev_property_get_str : NULL,
- set ? qdev_property_set_str : NULL,
- qdev_property_release_str,
- prop, errp);
+ type_register_static(&device_type_info);
}
-void qdev_machine_init(void)
-{
- qdev_get_peripheral_anon();
- qdev_get_peripheral();
-}
+device_init(init_qdev);
diff --git a/hw/qdev.h b/hw/qdev.h
index 2abb767389..ab53273632 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -6,6 +6,7 @@
#include "qemu-char.h"
#include "qemu-option.h"
#include "qapi/qapi-visit-core.h"
+#include "qemu/object.h"
typedef struct Property Property;
@@ -13,8 +14,6 @@ typedef struct PropertyInfo PropertyInfo;
typedef struct CompatProperty CompatProperty;
-typedef struct DeviceInfo DeviceInfo;
-
typedef struct BusState BusState;
typedef struct BusInfo BusInfo;
@@ -28,52 +27,45 @@ enum {
DEV_NVECTORS_UNSPECIFIED = -1,
};
-/**
- * @DevicePropertyAccessor - called when trying to get/set a property
- *
- * @dev the device that owns the property
- * @v the visitor that contains the property data
- * @opaque the device property opaque
- * @name the name of the property
- * @errp a pointer to an Error that is filled if getting/setting fails.
- */
-typedef void (DevicePropertyAccessor)(DeviceState *dev,
- Visitor *v,
- void *opaque,
- const char *name,
- Error **errp);
+#define TYPE_DEVICE "device"
+#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE)
+#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
+#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
-/**
- * @DevicePropertyRelease - called when a property is removed from a device
- *
- * @dev the device that owns the property
- * @name the name of the property
- * @opaque the opaque registered with the property
- */
-typedef void (DevicePropertyRelease)(DeviceState *dev,
- const char *name,
- void *opaque);
-
-typedef struct DeviceProperty
-{
- gchar *name;
- gchar *type;
- DevicePropertyAccessor *get;
- DevicePropertyAccessor *set;
- DevicePropertyRelease *release;
- void *opaque;
-
- QTAILQ_ENTRY(DeviceProperty) node;
-} DeviceProperty;
+typedef int (*qdev_initfn)(DeviceState *dev);
+typedef int (*qdev_event)(DeviceState *dev);
+typedef void (*qdev_resetfn)(DeviceState *dev);
+
+typedef struct DeviceClass {
+ ObjectClass parent_class;
+
+ const char *fw_name;
+ const char *desc;
+ Property *props;
+ int no_user;
+
+ /* callbacks */
+ void (*reset)(DeviceState *dev);
+
+ /* device state */
+ const VMStateDescription *vmsd;
+
+ /* Private to qdev / bus. */
+ qdev_initfn init;
+ qdev_event unplug;
+ qdev_event exit;
+ BusInfo *bus_info;
+} DeviceClass;
/* This structure should not be accessed directly. We declare it here
so that it can be embedded in individual device state structures. */
struct DeviceState {
+ Object parent_obj;
+
const char *id;
enum DevState state;
QemuOpts *opts;
int hotplugged;
- DeviceInfo *info;
BusState *parent_bus;
int num_gpio_out;
qemu_irq *gpio_out;
@@ -84,18 +76,6 @@ struct DeviceState {
QTAILQ_ENTRY(DeviceState) sibling;
int instance_id_alias;
int alias_required_for_version;
-
- /**
- * This tracks the number of references between devices. See @qdev_ref for
- * more information.
- */
- uint32_t ref;
-
- QTAILQ_HEAD(, DeviceProperty) properties;
-
- /* Do not, under any circumstance, use this parent link below anywhere
- * outside of qdev.c. You have been warned. */
- DeviceState *parent;
};
typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
@@ -145,6 +125,7 @@ enum PropertyType {
PROP_TYPE_UINT64,
PROP_TYPE_TADDR,
PROP_TYPE_MACADDR,
+ PROP_TYPE_LOSTTICKPOLICY,
PROP_TYPE_DRIVE,
PROP_TYPE_CHR,
PROP_TYPE_STRING,
@@ -164,8 +145,8 @@ struct PropertyInfo {
int (*parse)(DeviceState *dev, Property *prop, const char *str);
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
void (*free)(DeviceState *dev, Property *prop);
- DevicePropertyAccessor *get;
- DevicePropertyAccessor *set;
+ ObjectPropertyAccessor *get;
+ ObjectPropertyAccessor *set;
};
typedef struct GlobalProperty {
@@ -179,6 +160,7 @@ typedef struct GlobalProperty {
DeviceState *qdev_create(BusState *bus, const char *name);
DeviceState *qdev_try_create(BusState *bus, const char *name);
+bool qdev_exists(const char *name);
int qdev_device_help(QemuOpts *opts);
DeviceState *qdev_device_add(QemuOpts *opts);
int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
@@ -198,43 +180,11 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
/*** Device API. ***/
-typedef int (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
-typedef int (*qdev_event)(DeviceState *dev);
-typedef void (*qdev_resetfn)(DeviceState *dev);
-
-struct DeviceInfo {
- const char *name;
- const char *fw_name;
- const char *alias;
- const char *desc;
- size_t size;
- Property *props;
- int no_user;
-
- /* callbacks */
- qdev_resetfn reset;
-
- /* device state */
- const VMStateDescription *vmsd;
-
- /* Private to qdev / bus. */
- qdev_initfn init;
- qdev_event unplug;
- qdev_event exit;
- BusInfo *bus_info;
- struct DeviceInfo *next;
-};
-extern DeviceInfo *device_info_list;
-
-void qdev_register(DeviceInfo *info);
-
/* Register device properties. */
/* GPIO inputs also double as IRQ sinks. */
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
-CharDriverState *qdev_init_chardev(DeviceState *dev);
-
BusState *qdev_get_parent_bus(DeviceState *dev);
/*** BUS API. ***/
@@ -287,6 +237,7 @@ extern PropertyInfo qdev_prop_string;
extern PropertyInfo qdev_prop_chr;
extern PropertyInfo qdev_prop_ptr;
extern PropertyInfo qdev_prop_macaddr;
+extern PropertyInfo qdev_prop_losttickpolicy;
extern PropertyInfo qdev_prop_drive;
extern PropertyInfo qdev_prop_netdev;
extern PropertyInfo qdev_prop_vlan;
@@ -347,6 +298,9 @@ extern PropertyInfo qdev_prop_pci_devfn;
DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
#define DEFINE_PROP_MACADDR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
+#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
+ LostTickPolicy)
#define DEFINE_PROP_END_OF_LIST() \
{}
@@ -369,6 +323,8 @@ void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
+void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
+ LostTickPolicy *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);
@@ -378,250 +334,43 @@ void qdev_prop_set_globals(DeviceState *dev);
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
Property *prop, const char *value);
-static inline const char *qdev_fw_name(DeviceState *dev)
-{
- return dev->info->fw_name ? : dev->info->alias ? : dev->info->name;
-}
-
char *qdev_get_fw_dev_path(DeviceState *dev);
+
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
extern struct BusInfo system_bus_info;
/**
- * @qdev_ref
- *
- * Increase the reference count of a device. A device cannot be freed as long
- * as its reference count is greater than zero.
- *
- * @dev - the device
- */
-void qdev_ref(DeviceState *dev);
-
-/**
- * @qdef_unref
- *
- * Decrease the reference count of a device. A device cannot be freed as long
- * as its reference count is greater than zero.
- *
- * @dev - the device
- */
-void qdev_unref(DeviceState *dev);
-
-/**
- * @qdev_property_add - add a new property to a device
- *
- * @dev - the device to add a property to
- *
- * @name - the name of the property. This can contain any character except for
- * a forward slash. In general, you should use hyphens '-' instead of
- * underscores '_' when naming properties.
- *
- * @type - the type name of the property. This namespace is pretty loosely
- * defined. Sub namespaces are constructed by using a prefix and then
- * to angle brackets. For instance, the type 'virtio-net-pci' in the
- * 'link' namespace would be 'link<virtio-net-pci>'.
- *
- * @get - the getter to be called to read a property. If this is NULL, then
- * the property cannot be read.
- *
- * @set - the setter to be called to write a property. If this is NULL,
- * then the property cannot be written.
- *
- * @release - called when the property is removed from the device. This is
- * meant to allow a property to free its opaque upon device
- * destruction. This may be NULL.
- *
- * @opaque - an opaque pointer to pass to the callbacks for the property
- *
- * @errp - returns an error if this function fails
- */
-void qdev_property_add(DeviceState *dev, const char *name, const char *type,
- DevicePropertyAccessor *get, DevicePropertyAccessor *set,
- DevicePropertyRelease *release,
- void *opaque, Error **errp);
-
-/**
- * @qdev_property_get - reads a property from a device
- *
- * @dev - the device
- *
- * @v - the visitor that will receive the property value. This should be an
- * Output visitor and the data will be written with @name as the name.
- *
- * @name - the name of the property
- *
- * @errp - returns an error if this function fails
- */
-void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
- Error **errp);
-
-/**
- * @qdev_property_set - writes a property to a device
- *
- * @dev - the device
- *
- * @v - the visitor that will be used to write the property value. This should
- * be an Input visitor and the data will be first read with @name as the
- * name and then written as the property value.
- *
- * @name - the name of the property
- *
- * @errp - returns an error if this function fails
- */
-void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
- Error **errp);
-
-/**
- * @qdev_property_get_type - returns the type of a property
- *
- * @dev - the device
- *
- * @name - the name of the property
- *
- * @errp - returns an error if this function fails
- *
- * Returns:
- * The type name of the property.
- */
-const char *qdev_property_get_type(DeviceState *dev, const char *name,
- Error **errp);
-
-/**
* @qdev_property_add_static - add a @Property to a device referencing a
* field in a struct.
*/
void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
/**
- * @qdev_get_root - returns the root device of the composition tree
+ * @qdev_machine_init
*
- * Returns:
- * The root of the composition tree.
+ * Initialize platform devices before machine init. This is a hack until full
+ * support for composition is added.
*/
-DeviceState *qdev_get_root(void);
+void qdev_machine_init(void);
/**
- * @qdev_get_canonical_path - returns the canonical path for a device. This
- * is the path within the composition tree starting from the root.
+ * @device_reset
*
- * Returns:
- * The canonical path in the composition tree.
+ * Reset a single device (by calling the reset method).
*/
-gchar *qdev_get_canonical_path(DeviceState *dev);
+void device_reset(DeviceState *dev);
-/**
- * @qdev_resolve_path - resolves a path returning a device
- *
- * There are two types of supported paths--absolute paths and partial paths.
- *
- * Absolute paths are derived from the root device and can follow child<> or
- * link<> properties. Since they can follow link<> properties, they can be
- * arbitrarily long. Absolute paths look like absolute filenames and are
- * prefixed with a leading slash.
- *
- * Partial paths look like relative filenames. They do not begin with a
- * prefix. The matching rules for partial paths are subtle but designed to make
- * specifying devices easy. At each level of the composition tree, the partial
- * path is matched as an absolute path. The first match is not returned. At
- * least two matches are searched for. A successful result is only returned if
- * only one match is founded. If more than one match is found, a flag is
- * return to indicate that the match was ambiguous.
- *
- * @path - the path to resolve
- *
- * @ambiguous - returns true if the path resolution failed because of an
- * ambiguous match
- *
- * Returns:
- * The matched device or NULL on path lookup failure.
- */
-DeviceState *qdev_resolve_path(const char *path, bool *ambiguous);
+const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
-/**
- * @qdev_property_add_child - Add a child property to a device
- *
- * Child properties form the composition tree. All devices need to be a child
- * of another device. Devices can only be a child of one device.
- *
- * There is no way for a child to determine what its parent is. It is not
- * a bidirectional relationship. This is by design.
- *
- * @dev - the device to add a property to
- *
- * @name - the name of the property
- *
- * @child - the child device
- *
- * @errp - if an error occurs, a pointer to an area to store the area
- */
-void qdev_property_add_child(DeviceState *dev, const char *name,
- DeviceState *child, Error **errp);
+const char *qdev_fw_name(DeviceState *dev);
-/**
- * @qdev_property_add_link - Add a link property to a device
- *
- * Links establish relationships between devices. Links are unidirectional
- * although two links can be combined to form a bidirectional relationship
- * between devices.
- *
- * Links form the graph in the device model.
- *
- * @dev - the device to add a property to
- *
- * @name - the name of the property
- *
- * @type - the qdev type of the link
- *
- * @child - a pointer to where the link device reference is stored
- *
- * @errp - if an error occurs, a pointer to an area to store the area
- */
-void qdev_property_add_link(DeviceState *dev, const char *name,
- const char *type, DeviceState **child,
- Error **errp);
+BusInfo *qdev_get_bus_info(DeviceState *dev);
-/**
- * @qdev_property_add_str
- *
- * Add a string property using getters/setters. This function will add a
- * property of type 'string'.
- *
- * @dev - the device to add a property to
- *
- * @name - the name of the property
- *
- * @get - the getter or NULL if the property is write-only. This function must
- * return a string to be freed by @g_free().
- *
- * @set - the setter or NULL if the property is read-only
- *
- * @errp - if an error occurs, a pointer to an area to store the error
- */
-void qdev_property_add_str(DeviceState *dev, const char *name,
- char *(*get)(DeviceState *, Error **),
- void (*set)(DeviceState *, const char *, Error **),
- Error **errp);
+Property *qdev_get_props(DeviceState *dev);
-/**
- * @qdev_get_type
- *
- * Returns the string representation of the type of this object.
- *
- * @dev - the device
- *
- * @errp - if an error occurs, a pointer to an area to store the error
- *
- * Returns: a string representing the type. This must be freed by the caller
- * with g_free().
- */
-char *qdev_get_type(DeviceState *dev, Error **errp);
+/* FIXME: make this a link<> */
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
-/**
- * @qdev_machine_init
- *
- * Initialize platform devices before machine init. This is a hack until full
- * support for composition is added.
- */
-void qdev_machine_init(void);
+extern int qdev_hotplug;
#endif
diff --git a/hw/qxl.c b/hw/qxl.c
index ac819271b2..bc03c1dc77 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -343,10 +343,7 @@ static void init_qxl_ram(PCIQXLDevice *d)
/* can be called from spice server thread context */
static void qxl_set_dirty(MemoryRegion *mr, ram_addr_t addr, ram_addr_t end)
{
- while (addr < end) {
- memory_region_set_dirty(mr, addr);
- addr += TARGET_PAGE_SIZE;
- }
+ memory_region_set_dirty(mr, addr, end - addr);
}
static void qxl_rom_set_dirty(PCIQXLDevice *qxl)
@@ -1020,7 +1017,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
case MEMSLOT_GROUP_HOST:
return (void*)offset;
case MEMSLOT_GROUP_GUEST:
- PANIC_ON(slot > NUM_MEMSLOTS);
+ PANIC_ON(slot >= NUM_MEMSLOTS);
PANIC_ON(!qxl->guest_slots[slot].active);
PANIC_ON(offset < qxl->guest_slots[slot].delta);
offset -= qxl->guest_slots[slot].delta;
@@ -1827,38 +1824,56 @@ static Property qxl_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static PCIDeviceInfo qxl_info_primary = {
- .qdev.name = "qxl-vga",
- .qdev.desc = "Spice QXL GPU (primary, vga compatible)",
- .qdev.size = sizeof(PCIQXLDevice),
- .qdev.reset = qxl_reset_handler,
- .qdev.vmsd = &qxl_vmstate,
- .no_hotplug = 1,
- .init = qxl_init_primary,
- .romfile = "vgabios-qxl.bin",
- .vendor_id = REDHAT_PCI_VENDOR_ID,
- .device_id = QXL_DEVICE_ID_STABLE,
- .class_id = PCI_CLASS_DISPLAY_VGA,
- .qdev.props = qxl_properties,
+static void qxl_primary_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = qxl_init_primary;
+ k->romfile = "vgabios-qxl.bin";
+ k->vendor_id = REDHAT_PCI_VENDOR_ID;
+ k->device_id = QXL_DEVICE_ID_STABLE;
+ k->class_id = PCI_CLASS_DISPLAY_VGA;
+ dc->desc = "Spice QXL GPU (primary, vga compatible)";
+ dc->reset = qxl_reset_handler;
+ dc->vmsd = &qxl_vmstate;
+ dc->props = qxl_properties;
+}
+
+static TypeInfo qxl_primary_info = {
+ .name = "qxl-vga",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIQXLDevice),
+ .class_init = qxl_primary_class_init,
};
-static PCIDeviceInfo qxl_info_secondary = {
- .qdev.name = "qxl",
- .qdev.desc = "Spice QXL GPU (secondary)",
- .qdev.size = sizeof(PCIQXLDevice),
- .qdev.reset = qxl_reset_handler,
- .qdev.vmsd = &qxl_vmstate,
- .init = qxl_init_secondary,
- .vendor_id = REDHAT_PCI_VENDOR_ID,
- .device_id = QXL_DEVICE_ID_STABLE,
- .class_id = PCI_CLASS_DISPLAY_OTHER,
- .qdev.props = qxl_properties,
+static void qxl_secondary_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = qxl_init_secondary;
+ k->vendor_id = REDHAT_PCI_VENDOR_ID;
+ k->device_id = QXL_DEVICE_ID_STABLE;
+ k->class_id = PCI_CLASS_DISPLAY_OTHER;
+ dc->desc = "Spice QXL GPU (secondary)";
+ dc->reset = qxl_reset_handler;
+ dc->vmsd = &qxl_vmstate;
+ dc->props = qxl_properties;
+}
+
+static TypeInfo qxl_secondary_info = {
+ .name = "qxl",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIQXLDevice),
+ .class_init = qxl_secondary_class_init,
};
static void qxl_register(void)
{
- pci_qdev_register(&qxl_info_primary);
- pci_qdev_register(&qxl_info_secondary);
+ type_register_static(&qxl_primary_info);
+ type_register_static(&qxl_secondary_info);
}
device_init(qxl_register);
diff --git a/hw/realview.c b/hw/realview.c
index 3f35118f21..821e627560 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -82,15 +82,23 @@ static int realview_i2c_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo realview_i2c_info = {
- .init = realview_i2c_init,
- .qdev.name = "realview_i2c",
- .qdev.size = sizeof(RealViewI2CState),
+static void realview_i2c_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = realview_i2c_init;
+}
+
+static TypeInfo realview_i2c_info = {
+ .name = "realview_i2c",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RealViewI2CState),
+ .class_init = realview_i2c_class_init,
};
static void realview_register_devices(void)
{
- sysbus_register_withprop(&realview_i2c_info);
+ type_register_static(&realview_i2c_info);
}
/* Board init. */
@@ -227,6 +235,8 @@ static void realview_init(ram_addr_t ram_size,
for (n = 0; n < smp_cpus; n++) {
sysbus_connect_irq(busdev, n, cpu_irq[n]);
}
+ sysbus_create_varargs("l2x0", realview_binfo.smp_priv_base + 0x2000,
+ NULL);
} else {
uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
/* For now just create the nIRQ GIC, and ignore the others. */
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509ee7..4121502c7b 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
#include "sysbus.h"
-#define GIC_NIRQ 96
#define NCPU 1
/* Only a single "CPU" interface is present. */
@@ -37,16 +36,33 @@ static int realview_gic_init(SysBusDevice *dev)
{
RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
- gic_init(&s->gic);
+ /* The GICs on the RealView boards have a fixed nonconfigurable
+ * number of interrupt lines, so we don't need to expose this as
+ * a qdev property.
+ */
+ gic_init(&s->gic, 96);
realview_gic_map_setup(s);
sysbus_init_mmio(dev, &s->container);
return 0;
}
+static void realview_gic_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = realview_gic_init;
+}
+
+static TypeInfo realview_gic_info = {
+ .name = "realview_gic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RealViewGICState),
+ .class_init = realview_gic_class_init,
+};
+
static void realview_gic_register_devices(void)
{
- sysbus_register_dev("realview_gic", sizeof(RealViewGICState),
- realview_gic_init);
+ type_register_static(&realview_gic_info);
}
device_init(realview_gic_register_devices)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 0ae9f5774b..1668390e1f 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3478,7 +3478,7 @@ static int pci_rtl8139_init(PCIDevice *dev)
s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
s->cplus_txbuffer = NULL;
@@ -3494,27 +3494,38 @@ static int pci_rtl8139_init(PCIDevice *dev)
return 0;
}
-static PCIDeviceInfo rtl8139_info = {
- .qdev.name = "rtl8139",
- .qdev.size = sizeof(RTL8139State),
- .qdev.reset = rtl8139_reset,
- .qdev.vmsd = &vmstate_rtl8139,
- .init = pci_rtl8139_init,
- .exit = pci_rtl8139_uninit,
- .romfile = "pxe-rtl8139.rom",
- .vendor_id = PCI_VENDOR_ID_REALTEK,
- .device_id = PCI_DEVICE_ID_REALTEK_8139,
- .revision = RTL8139_PCI_REVID, /* >=0x20 is for 8139C+ */
- .class_id = PCI_CLASS_NETWORK_ETHERNET,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(RTL8139State, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property rtl8139_properties[] = {
+ DEFINE_NIC_PROPERTIES(RTL8139State, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void rtl8139_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_rtl8139_init;
+ k->exit = pci_rtl8139_uninit;
+ k->romfile = "pxe-rtl8139.rom";
+ k->vendor_id = PCI_VENDOR_ID_REALTEK;
+ k->device_id = PCI_DEVICE_ID_REALTEK_8139;
+ k->revision = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ dc->reset = rtl8139_reset;
+ dc->vmsd = &vmstate_rtl8139;
+ dc->props = rtl8139_properties;
+}
+
+static TypeInfo rtl8139_info = {
+ .name = "rtl8139",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(RTL8139State),
+ .class_init = rtl8139_class_init,
};
static void rtl8139_register_devices(void)
{
- pci_qdev_register(&rtl8139_info);
+ type_register_static(&rtl8139_info);
}
device_init(rtl8139_register_devices)
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 2efea9f184..49140f8a9e 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -50,12 +50,6 @@ struct BusInfo s390_virtio_bus_info = {
.size = sizeof(VirtIOS390Bus),
};
-typedef struct {
- DeviceInfo qdev;
- int (*init)(VirtIOS390Device *dev);
-} VirtIOS390DeviceInfo;
-
-
static const VirtIOBindings virtio_s390_bindings;
static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);
@@ -343,69 +337,108 @@ static const VirtIOBindings virtio_s390_bindings = {
.get_features = virtio_s390_get_features,
};
-static VirtIOS390DeviceInfo s390_virtio_net = {
- .init = s390_virtio_net_init,
- .qdev.name = "virtio-net-s390",
- .qdev.alias = "virtio-net",
- .qdev.size = sizeof(VirtIOS390Device),
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
- DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
- net.txtimer, TX_TIMER_INTERVAL),
- DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
- net.txburst, TX_BURST),
- DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property s390_virtio_net_properties[] = {
+ DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
+ DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
+ net.txtimer, TX_TIMER_INTERVAL),
+ DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
+ net.txburst, TX_BURST),
+ DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+ k->init = s390_virtio_net_init;
+ dc->props = s390_virtio_net_properties;
+}
+
+static TypeInfo s390_virtio_net = {
+ .name = "virtio-net-s390",
+ .parent = TYPE_VIRTIO_S390_DEVICE,
+ .instance_size = sizeof(VirtIOS390Device),
+ .class_init = s390_virtio_net_class_init,
+};
+
+static Property s390_virtio_blk_properties[] = {
+ DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
+ DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+ k->init = s390_virtio_blk_init;
+ dc->props = s390_virtio_blk_properties;
+}
+
+static TypeInfo s390_virtio_blk = {
+ .name = "virtio-blk-s390",
+ .parent = TYPE_VIRTIO_S390_DEVICE,
+ .instance_size = sizeof(VirtIOS390Device),
+ .class_init = s390_virtio_blk_class_init,
};
-static VirtIOS390DeviceInfo s390_virtio_blk = {
- .init = s390_virtio_blk_init,
- .qdev.name = "virtio-blk-s390",
- .qdev.alias = "virtio-blk",
- .qdev.size = sizeof(VirtIOS390Device),
- .qdev.props = (Property[]) {
- DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
- DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property s390_virtio_serial_properties[] = {
+ DEFINE_PROP_UINT32("max_ports", VirtIOS390Device,
+ serial.max_virtserial_ports, 31),
+ DEFINE_PROP_END_OF_LIST(),
};
-static VirtIOS390DeviceInfo s390_virtio_serial = {
- .init = s390_virtio_serial_init,
- .qdev.name = "virtio-serial-s390",
- .qdev.alias = "virtio-serial",
- .qdev.size = sizeof(VirtIOS390Device),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("max_ports", VirtIOS390Device,
- serial.max_virtserial_ports, 31),
- DEFINE_PROP_END_OF_LIST(),
- },
+static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+ k->init = s390_virtio_serial_init;
+ dc->props = s390_virtio_serial_properties;
+}
+
+static TypeInfo s390_virtio_serial = {
+ .name = "virtio-serial-s390",
+ .parent = TYPE_VIRTIO_S390_DEVICE,
+ .instance_size = sizeof(VirtIOS390Device),
+ .class_init = s390_virtio_serial_class_init,
};
-static int s390_virtio_busdev_init(DeviceState *dev, DeviceInfo *info)
+static int s390_virtio_busdev_init(DeviceState *dev)
{
- VirtIOS390DeviceInfo *_info = (VirtIOS390DeviceInfo *)info;
VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
+ VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
return _info->init(_dev);
}
-static void s390_virtio_bus_register_withprop(VirtIOS390DeviceInfo *info)
+static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
{
- info->qdev.init = s390_virtio_busdev_init;
- info->qdev.bus_info = &s390_virtio_bus_info;
- info->qdev.unplug = qdev_simple_unplug_cb;
+ DeviceClass *dc = DEVICE_CLASS(klass);
- assert(info->qdev.size >= sizeof(VirtIOS390Device));
- qdev_register(&info->qdev);
+ dc->init = s390_virtio_busdev_init;
+ dc->bus_info = &s390_virtio_bus_info;
+ dc->unplug = qdev_simple_unplug_cb;
}
+static TypeInfo virtio_s390_device_info = {
+ .name = TYPE_VIRTIO_S390_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIOS390Device),
+ .class_init = virtio_s390_device_class_init,
+ .class_size = sizeof(VirtIOS390DeviceClass),
+ .abstract = true,
+};
+
static void s390_virtio_register(void)
{
- s390_virtio_bus_register_withprop(&s390_virtio_serial);
- s390_virtio_bus_register_withprop(&s390_virtio_blk);
- s390_virtio_bus_register_withprop(&s390_virtio_net);
+ type_register_static(&virtio_s390_device_info);
+ type_register_static(&s390_virtio_serial);
+ type_register_static(&s390_virtio_blk);
+ type_register_static(&s390_virtio_net);
}
device_init(s390_virtio_register);
@@ -419,16 +452,25 @@ static int s390_virtio_bridge_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo s390_virtio_bridge_info = {
- .init = s390_virtio_bridge_init,
- .qdev.name = "s390-virtio-bridge",
- .qdev.size = sizeof(SysBusDevice),
- .qdev.no_user = 1,
+static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = s390_virtio_bridge_init;
+ dc->no_user = 1;
+}
+
+static TypeInfo s390_virtio_bridge_info = {
+ .name = "s390-virtio-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = s390_virtio_bridge_class_init,
};
static void s390_virtio_register_devices(void)
{
- sysbus_register_withprop(&s390_virtio_bridge_info);
+ type_register_static(&s390_virtio_bridge_info);
}
device_init(s390_virtio_register_devices)
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index d02a90709d..b5e59b7d4b 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -40,7 +40,22 @@
#define VIRTIO_PARAM_CONFIG_CHANGED 0x1
#define VIRTIO_PARAM_DEV_ADD 0x2
-typedef struct VirtIOS390Device {
+#define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device"
+#define VIRTIO_S390_DEVICE(obj) \
+ OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE)
+#define VIRTIO_S390_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VirtIOS390DeviceClass, (klass), TYPE_VIRTIO_S390_DEVICE)
+#define VIRTIO_S390_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE)
+
+typedef struct VirtIOS390Device VirtIOS390Device;
+
+typedef struct VirtIOS390DeviceClass {
+ DeviceClass qdev;
+ int (*init)(VirtIOS390Device *dev);
+} VirtIOS390DeviceClass;
+
+struct VirtIOS390Device {
DeviceState qdev;
ram_addr_t dev_offs;
ram_addr_t feat_offs;
@@ -52,7 +67,7 @@ typedef struct VirtIOS390Device {
uint32_t host_features;
virtio_serial_conf serial;
virtio_net_conf net;
-} VirtIOS390Device;
+};
typedef struct VirtIOS390Bus {
BusState bus;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 2210b8ac7e..51123a7535 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -317,7 +317,6 @@ static QEMUMachine s390_machine = {
.no_serial = 1,
.no_parallel = 1,
.use_virtcon = 1,
- .no_vga = 1,
.max_cpus = 255,
.is_default = 1,
};
diff --git a/hw/sb16.c b/hw/sb16.c
index 887b32e794..db8929b98e 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1289,55 +1289,55 @@ static const VMStateDescription vmstate_sb16 = {
.minimum_version_id_old = 1,
.post_load = sb16_post_load,
.fields = (VMStateField []) {
- VMSTATE_UINT32(irq, SB16State),
- VMSTATE_UINT32(dma, SB16State),
- VMSTATE_UINT32(hdma, SB16State),
- VMSTATE_UINT32(port, SB16State),
- VMSTATE_UINT32(ver, SB16State),
- VMSTATE_INT32(in_index, SB16State),
- VMSTATE_INT32(out_data_len, SB16State),
- VMSTATE_INT32(fmt_stereo, SB16State),
- VMSTATE_INT32(fmt_signed, SB16State),
- VMSTATE_INT32(fmt_bits, SB16State),
- VMSTATE_UINT32(fmt, SB16State),
- VMSTATE_INT32(dma_auto, SB16State),
- VMSTATE_INT32(block_size, SB16State),
- VMSTATE_INT32(fifo, SB16State),
- VMSTATE_INT32(freq, SB16State),
- VMSTATE_INT32(time_const, SB16State),
- VMSTATE_INT32(speaker, SB16State),
- VMSTATE_INT32(needed_bytes, SB16State),
- VMSTATE_INT32(cmd, SB16State),
- VMSTATE_INT32(use_hdma, SB16State),
- VMSTATE_INT32(highspeed, SB16State),
- VMSTATE_INT32(can_write, SB16State),
- VMSTATE_INT32(v2x6, SB16State),
-
- VMSTATE_UINT8(csp_param, SB16State),
- VMSTATE_UINT8(csp_value, SB16State),
- VMSTATE_UINT8(csp_mode, SB16State),
- VMSTATE_UINT8(csp_param, SB16State),
- VMSTATE_BUFFER(csp_regs, SB16State),
- VMSTATE_UINT8(csp_index, SB16State),
- VMSTATE_BUFFER(csp_reg83, SB16State),
- VMSTATE_INT32(csp_reg83r, SB16State),
- VMSTATE_INT32(csp_reg83w, SB16State),
-
- VMSTATE_BUFFER(in2_data, SB16State),
- VMSTATE_BUFFER(out_data, SB16State),
- VMSTATE_UINT8(test_reg, SB16State),
- VMSTATE_UINT8(last_read_byte, SB16State),
-
- VMSTATE_INT32(nzero, SB16State),
- VMSTATE_INT32(left_till_irq, SB16State),
- VMSTATE_INT32(dma_running, SB16State),
- VMSTATE_INT32(bytes_per_second, SB16State),
- VMSTATE_INT32(align, SB16State),
-
- VMSTATE_INT32(mixer_nreg, SB16State),
- VMSTATE_BUFFER(mixer_regs, SB16State),
-
- VMSTATE_END_OF_LIST()
+ VMSTATE_UINT32 (irq, SB16State),
+ VMSTATE_UINT32 (dma, SB16State),
+ VMSTATE_UINT32 (hdma, SB16State),
+ VMSTATE_UINT32 (port, SB16State),
+ VMSTATE_UINT32 (ver, SB16State),
+ VMSTATE_INT32 (in_index, SB16State),
+ VMSTATE_INT32 (out_data_len, SB16State),
+ VMSTATE_INT32 (fmt_stereo, SB16State),
+ VMSTATE_INT32 (fmt_signed, SB16State),
+ VMSTATE_INT32 (fmt_bits, SB16State),
+ VMSTATE_UINT32 (fmt, SB16State),
+ VMSTATE_INT32 (dma_auto, SB16State),
+ VMSTATE_INT32 (block_size, SB16State),
+ VMSTATE_INT32 (fifo, SB16State),
+ VMSTATE_INT32 (freq, SB16State),
+ VMSTATE_INT32 (time_const, SB16State),
+ VMSTATE_INT32 (speaker, SB16State),
+ VMSTATE_INT32 (needed_bytes, SB16State),
+ VMSTATE_INT32 (cmd, SB16State),
+ VMSTATE_INT32 (use_hdma, SB16State),
+ VMSTATE_INT32 (highspeed, SB16State),
+ VMSTATE_INT32 (can_write, SB16State),
+ VMSTATE_INT32 (v2x6, SB16State),
+
+ VMSTATE_UINT8 (csp_param, SB16State),
+ VMSTATE_UINT8 (csp_value, SB16State),
+ VMSTATE_UINT8 (csp_mode, SB16State),
+ VMSTATE_UINT8 (csp_param, SB16State),
+ VMSTATE_BUFFER (csp_regs, SB16State),
+ VMSTATE_UINT8 (csp_index, SB16State),
+ VMSTATE_BUFFER (csp_reg83, SB16State),
+ VMSTATE_INT32 (csp_reg83r, SB16State),
+ VMSTATE_INT32 (csp_reg83w, SB16State),
+
+ VMSTATE_BUFFER (in2_data, SB16State),
+ VMSTATE_BUFFER (out_data, SB16State),
+ VMSTATE_UINT8 (test_reg, SB16State),
+ VMSTATE_UINT8 (last_read_byte, SB16State),
+
+ VMSTATE_INT32 (nzero, SB16State),
+ VMSTATE_INT32 (left_till_irq, SB16State),
+ VMSTATE_INT32 (dma_running, SB16State),
+ VMSTATE_INT32 (bytes_per_second, SB16State),
+ VMSTATE_INT32 (align, SB16State),
+
+ VMSTATE_INT32 (mixer_nreg, SB16State),
+ VMSTATE_BUFFER (mixer_regs, SB16State),
+
+ VMSTATE_END_OF_LIST ()
}
};
@@ -1349,7 +1349,7 @@ static const MemoryRegionPortio sb16_ioport_list[] = {
{ 10, 1, 1, .read = dsp_read },
{ 12, 1, 1, .write = dsp_write },
{ 12, 4, 1, .read = dsp_read },
- PORTIO_END_OF_LIST(),
+ PORTIO_END_OF_LIST (),
};
@@ -1391,24 +1391,34 @@ int SB16_init (ISABus *bus)
return 0;
}
-static ISADeviceInfo sb16_info = {
- .qdev.name = "sb16",
- .qdev.desc = "Creative Sound Blaster 16",
- .qdev.size = sizeof (SB16State),
- .qdev.vmsd = &vmstate_sb16,
- .init = sb16_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32 ("version", SB16State, ver, 0x0405), /* 4.5 */
- DEFINE_PROP_HEX32 ("iobase", SB16State, port, 0x220),
- DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
- DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
- DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
- DEFINE_PROP_END_OF_LIST (),
- },
+static Property sb16_properties[] = {
+ DEFINE_PROP_HEX32 ("version", SB16State, ver, 0x0405), /* 4.5 */
+ DEFINE_PROP_HEX32 ("iobase", SB16State, port, 0x220),
+ DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
+ DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
+ DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
+ DEFINE_PROP_END_OF_LIST (),
+};
+
+static void sb16_class_initfn (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
+ ic->init = sb16_initfn;
+ dc->desc = "Creative Sound Blaster 16";
+ dc->vmsd = &vmstate_sb16;
+ dc->props = sb16_properties;
+}
+
+static TypeInfo sb16_info = {
+ .name = "sb16",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof (SB16State),
+ .class_init = sb16_class_initfn,
};
static void sb16_register (void)
{
- isa_qdev_register (&sb16_info);
+ type_register_static (&sb16_info);
}
device_init (sb16_register)
diff --git a/hw/sbi.c b/hw/sbi.c
index 8965a71771..847a4dde84 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -131,17 +131,26 @@ static int sbi_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo sbi_info = {
- .init = sbi_init1,
- .qdev.name = "sbi",
- .qdev.size = sizeof(SBIState),
- .qdev.vmsd = &vmstate_sbi,
- .qdev.reset = sbi_reset,
+static void sbi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sbi_init1;
+ dc->reset = sbi_reset;
+ dc->vmsd = &vmstate_sbi;
+}
+
+static TypeInfo sbi_info = {
+ .name = "sbi",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SBIState),
+ .class_init = sbi_class_init,
};
static void sbi_register_devices(void)
{
- sysbus_register_withprop(&sbi_info);
+ type_register_static(&sbi_info);
}
device_init(sbi_register_devices)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 64e709ee9f..0ee50a8360 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -23,6 +23,42 @@ static struct BusInfo scsi_bus_info = {
};
static int next_scsi_bus;
+static int scsi_device_init(SCSIDevice *s)
+{
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
+ if (sc->init) {
+ return sc->init(s);
+ }
+ return 0;
+}
+
+static void scsi_device_destroy(SCSIDevice *s)
+{
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
+ if (sc->destroy) {
+ sc->destroy(s);
+ }
+}
+
+static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun,
+ uint8_t *buf, void *hba_private)
+{
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
+ if (sc->alloc_req) {
+ return sc->alloc_req(s, tag, lun, buf, hba_private);
+ }
+
+ return NULL;
+}
+
+static void scsi_device_unit_attention_reported(SCSIDevice *s)
+{
+ SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
+ if (sc->unit_attention_reported) {
+ sc->unit_attention_reported(s);
+ }
+}
+
/* Create a scsi bus, and attach devices to it. */
void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
{
@@ -79,10 +115,9 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
}
}
-static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int scsi_qdev_init(DeviceState *qdev)
{
- SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
- SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base);
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
SCSIDevice *d;
int rc = -1;
@@ -126,9 +161,8 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
}
- dev->info = info;
QTAILQ_INIT(&dev->requests);
- rc = dev->info->init(dev);
+ rc = scsi_device_init(dev);
if (rc == 0) {
dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb,
dev);
@@ -140,26 +174,15 @@ err:
static int scsi_qdev_exit(DeviceState *qdev)
{
- SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->vmsentry) {
qemu_del_vm_change_state_handler(dev->vmsentry);
}
- if (dev->info->destroy) {
- dev->info->destroy(dev);
- }
+ scsi_device_destroy(dev);
return 0;
}
-void scsi_qdev_register(SCSIDeviceInfo *info)
-{
- info->qdev.bus_info = &scsi_bus_info;
- info->qdev.init = scsi_qdev_init;
- info->qdev.unplug = qdev_simple_unplug_cb;
- info->qdev.exit = scsi_qdev_exit;
- qdev_register(&info->qdev);
-}
-
/* handle legacy '-drive if=scsi,...' cmd line args */
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
int unit, bool removable, int bootindex)
@@ -182,7 +205,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
}
if (qdev_init(dev) < 0)
return NULL;
- return DO_UPCAST(SCSIDevice, qdev, dev);
+ return SCSI_DEVICE(dev);
}
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
@@ -278,7 +301,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
found_lun0 = false;
n = 0;
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
- SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
if (dev->lun == 0) {
@@ -300,7 +323,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
stl_be_p(&r->buf, n);
i = found_lun0 ? 8 : 16;
QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
- SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
store_lun(&r->buf[i], dev->lun);
@@ -398,9 +421,7 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
MIN(req->cmd.xfer, sizeof r->buf),
(req->cmd.buf[1] & 1) == 0);
if (r->req.dev->sense_is_ua) {
- if (r->req.dev->info->unit_attention_reported) {
- r->req.dev->info->unit_attention_reported(req->dev);
- }
+ scsi_device_unit_attention_reported(req->dev);
r->req.dev->sense_len = 0;
r->req.dev->sense_is_ua = false;
}
@@ -507,7 +528,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
hba_private);
} else {
- req = d->info->alloc_req(d, tag, lun, buf, hba_private);
+ req = scsi_device_alloc_req(d, tag, lun, buf, hba_private);
}
}
@@ -597,9 +618,7 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
* Here we handle unit attention clearing for UA_INTLCK_CTRL == 00b.
*/
if (req->dev->sense_is_ua) {
- if (req->dev->info->unit_attention_reported) {
- req->dev->info->unit_attention_reported(req->dev);
- }
+ scsi_device_unit_attention_reported(req->dev);
req->dev->sense_len = 0;
req->dev->sense_is_ua = false;
}
@@ -1367,7 +1386,7 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense)
static char *scsibus_get_fw_dev_path(DeviceState *dev)
{
- SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
+ SCSIDevice *d = SCSI_DEVICE(dev);
char path[100];
snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel,
@@ -1382,7 +1401,7 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
SCSIDevice *target_dev = NULL;
QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
- SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev);
+ SCSIDevice *dev = SCSI_DEVICE(qdev);
if (dev->channel == channel && dev->id == id) {
if (dev->lun == lun) {
@@ -1393,3 +1412,28 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
}
return target_dev;
}
+
+static void scsi_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->bus_info = &scsi_bus_info;
+ k->init = scsi_qdev_init;
+ k->unplug = qdev_simple_unplug_cb;
+ k->exit = scsi_qdev_exit;
+}
+
+static TypeInfo scsi_device_type_info = {
+ .name = TYPE_SCSI_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(SCSIDevice),
+ .abstract = true,
+ .class_size = sizeof(SCSIDeviceClass),
+ .class_init = scsi_device_class_init,
+};
+
+static void scsi_register_devices(void)
+{
+ type_register_static(&scsi_device_type_info);
+}
+
+device_init(scsi_register_devices);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 5d8bf53586..399e51e494 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -391,9 +391,6 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
l = strlen(s->serial);
- if (l > req->cmd.xfer) {
- l = req->cmd.xfer;
- }
if (l > 20) {
l = 20;
}
@@ -1002,9 +999,6 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
outbuf[0] = ((buflen - 2) >> 8) & 0xff;
outbuf[1] = (buflen - 2) & 0xff;
}
- if (buflen > r->req.cmd.xfer) {
- buflen = r->req.cmd.xfer;
- }
return buflen;
}
@@ -1038,9 +1032,6 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
default:
return -1;
}
- if (toclen > req->cmd.xfer) {
- toclen = req->cmd.xfer;
- }
return toclen;
}
@@ -1251,6 +1242,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
return -1;
}
+ buflen = MIN(buflen, req->cmd.xfer);
return buflen;
not_ready:
@@ -1720,75 +1712,124 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
DEFINE_PROP_STRING("serial", SCSIDiskState, serial)
-static SCSIDeviceInfo scsi_disk_info[] = {
- {
- .qdev.name = "scsi-hd",
- .qdev.fw_name = "disk",
- .qdev.desc = "virtual SCSI disk",
- .qdev.size = sizeof(SCSIDiskState),
- .qdev.reset = scsi_disk_reset,
- .init = scsi_hd_initfn,
- .destroy = scsi_destroy,
- .alloc_req = scsi_new_request,
- .unit_attention_reported = scsi_disk_unit_attention_reported,
- .qdev.props = (Property[]) {
- DEFINE_SCSI_DISK_PROPERTIES(),
- DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
- DEFINE_PROP_END_OF_LIST(),
- }
- },{
- .qdev.name = "scsi-cd",
- .qdev.fw_name = "disk",
- .qdev.desc = "virtual SCSI CD-ROM",
- .qdev.size = sizeof(SCSIDiskState),
- .qdev.reset = scsi_disk_reset,
- .init = scsi_cd_initfn,
- .destroy = scsi_destroy,
- .alloc_req = scsi_new_request,
- .unit_attention_reported = scsi_disk_unit_attention_reported,
- .qdev.props = (Property[]) {
- DEFINE_SCSI_DISK_PROPERTIES(),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property scsi_hd_properties[] = {
+ DEFINE_SCSI_DISK_PROPERTIES(),
+ DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
+
+ sc->init = scsi_hd_initfn;
+ sc->destroy = scsi_destroy;
+ sc->alloc_req = scsi_new_request;
+ sc->unit_attention_reported = scsi_disk_unit_attention_reported;
+ dc->fw_name = "disk";
+ dc->desc = "virtual SCSI disk";
+ dc->reset = scsi_disk_reset;
+ dc->props = scsi_hd_properties;
+}
+
+static TypeInfo scsi_hd_info = {
+ .name = "scsi-hd",
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
+ .class_init = scsi_hd_class_initfn,
+};
+
+static Property scsi_cd_properties[] = {
+ DEFINE_SCSI_DISK_PROPERTIES(),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
+
+ sc->init = scsi_cd_initfn;
+ sc->destroy = scsi_destroy;
+ sc->alloc_req = scsi_new_request;
+ sc->unit_attention_reported = scsi_disk_unit_attention_reported;
+ dc->fw_name = "disk";
+ dc->desc = "virtual SCSI CD-ROM";
+ dc->reset = scsi_disk_reset;
+ dc->props = scsi_cd_properties;
+}
+
+static TypeInfo scsi_cd_info = {
+ .name = "scsi-cd",
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
+ .class_init = scsi_cd_class_initfn,
+};
+
#ifdef __linux__
- },{
- .qdev.name = "scsi-block",
- .qdev.fw_name = "disk",
- .qdev.desc = "SCSI block device passthrough",
- .qdev.size = sizeof(SCSIDiskState),
- .qdev.reset = scsi_disk_reset,
- .init = scsi_block_initfn,
- .destroy = scsi_destroy,
- .alloc_req = scsi_block_new_request,
- .qdev.props = (Property[]) {
- DEFINE_SCSI_DISK_PROPERTIES(),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property scsi_block_properties[] = {
+ DEFINE_SCSI_DISK_PROPERTIES(),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scsi_block_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
+
+ sc->init = scsi_block_initfn;
+ sc->destroy = scsi_destroy;
+ sc->alloc_req = scsi_block_new_request;
+ dc->fw_name = "disk";
+ dc->desc = "SCSI block device passthrough";
+ dc->reset = scsi_disk_reset;
+ dc->props = scsi_block_properties;
+}
+
+static TypeInfo scsi_block_info = {
+ .name = "scsi-block",
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
+ .class_init = scsi_block_class_initfn,
+};
#endif
- },{
- .qdev.name = "scsi-disk", /* legacy -device scsi-disk */
- .qdev.fw_name = "disk",
- .qdev.desc = "virtual SCSI disk or CD-ROM (legacy)",
- .qdev.size = sizeof(SCSIDiskState),
- .qdev.reset = scsi_disk_reset,
- .init = scsi_disk_initfn,
- .destroy = scsi_destroy,
- .alloc_req = scsi_new_request,
- .unit_attention_reported = scsi_disk_unit_attention_reported,
- .qdev.props = (Property[]) {
- DEFINE_SCSI_DISK_PROPERTIES(),
- DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
- DEFINE_PROP_END_OF_LIST(),
- }
- }
+
+static Property scsi_disk_properties[] = {
+ DEFINE_SCSI_DISK_PROPERTIES(),
+ DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
+ DEFINE_PROP_END_OF_LIST(),
};
-static void scsi_disk_register_devices(void)
+static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
{
- int i;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
+
+ sc->init = scsi_disk_initfn;
+ sc->destroy = scsi_destroy;
+ sc->alloc_req = scsi_new_request;
+ sc->unit_attention_reported = scsi_disk_unit_attention_reported;
+ dc->fw_name = "disk";
+ dc->desc = "virtual SCSI disk or CD-ROM (legacy)";
+ dc->reset = scsi_disk_reset;
+ dc->props = scsi_disk_properties;
+}
- for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) {
- scsi_qdev_register(&scsi_disk_info[i]);
- }
+static TypeInfo scsi_disk_info = {
+ .name = "scsi-disk",
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDiskState),
+ .class_init = scsi_disk_class_initfn,
+};
+
+static void scsi_disk_register_devices(void)
+{
+ type_register_static(&scsi_hd_info);
+ type_register_static(&scsi_cd_info);
+#ifdef __linux__
+ type_register_static(&scsi_block_info);
+#endif
+ type_register_static(&scsi_disk_info);
}
device_init(scsi_disk_register_devices)
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 0aebcddf6e..4859212734 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -357,7 +357,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
static void scsi_generic_reset(DeviceState *dev)
{
- SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
+ SCSIDevice *s = SCSI_DEVICE(dev);
scsi_device_purge_requests(s, SENSE_CODE(RESET));
}
@@ -457,24 +457,35 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
return req;
}
-static SCSIDeviceInfo scsi_generic_info = {
- .qdev.name = "scsi-generic",
- .qdev.fw_name = "disk",
- .qdev.desc = "pass through generic scsi device (/dev/sg*)",
- .qdev.size = sizeof(SCSIDevice),
- .qdev.reset = scsi_generic_reset,
- .init = scsi_generic_initfn,
- .destroy = scsi_destroy,
- .alloc_req = scsi_new_request,
- .qdev.props = (Property[]) {
- DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property scsi_generic_properties[] = {
+ DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
+
+ sc->init = scsi_generic_initfn;
+ sc->destroy = scsi_destroy;
+ sc->alloc_req = scsi_new_request;
+ dc->fw_name = "disk";
+ dc->desc = "pass through generic scsi device (/dev/sg*)";
+ dc->reset = scsi_generic_reset;
+ dc->props = scsi_generic_properties;
+}
+
+static TypeInfo scsi_generic_info = {
+ .name = "scsi-generic",
+ .parent = TYPE_SCSI_DEVICE,
+ .instance_size = sizeof(SCSIDevice),
+ .class_init = scsi_generic_class_initfn,
};
static void scsi_generic_register_devices(void)
{
- scsi_qdev_register(&scsi_generic_info);
+ type_register_static(&scsi_generic_info);
}
device_init(scsi_generic_register_devices)
diff --git a/hw/scsi.h b/hw/scsi.h
index ab6e952327..dc72b6fc1e 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -13,7 +13,6 @@ typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusInfo SCSIBusInfo;
typedef struct SCSICommand SCSICommand;
typedef struct SCSIDevice SCSIDevice;
-typedef struct SCSIDeviceInfo SCSIDeviceInfo;
typedef struct SCSIRequest SCSIRequest;
typedef struct SCSIReqOps SCSIReqOps;
@@ -58,6 +57,23 @@ struct SCSIRequest {
QTAILQ_ENTRY(SCSIRequest) next;
};
+#define TYPE_SCSI_DEVICE "scsi-device"
+#define SCSI_DEVICE(obj) \
+ OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE)
+#define SCSI_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE)
+#define SCSI_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE)
+
+typedef struct SCSIDeviceClass {
+ DeviceClass parent_class;
+ int (*init)(SCSIDevice *dev);
+ void (*destroy)(SCSIDevice *s);
+ SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
+ uint8_t *buf, void *hba_private);
+ void (*unit_attention_reported)(SCSIDevice *s);
+} SCSIDeviceClass;
+
struct SCSIDevice
{
DeviceState qdev;
@@ -65,7 +81,6 @@ struct SCSIDevice
QEMUBH *bh;
uint32_t id;
BlockConf conf;
- SCSIDeviceInfo *info;
SCSISense unit_attention;
bool sense_is_ua;
uint8_t sense[SCSI_SENSE_BUF_SIZE];
@@ -93,16 +108,6 @@ struct SCSIReqOps {
uint8_t *(*get_buf)(SCSIRequest *req);
};
-typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
-struct SCSIDeviceInfo {
- DeviceInfo qdev;
- scsi_qdev_initfn init;
- void (*destroy)(SCSIDevice *s);
- SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
- uint8_t *buf, void *hba_private);
- void (*unit_attention_reported)(SCSIDevice *s);
-};
-
struct SCSIBusInfo {
int tcq;
int max_channel, max_target, max_lun;
@@ -120,7 +125,6 @@ struct SCSIBus {
};
void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
-void scsi_qdev_register(SCSIDeviceInfo *info);
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
{
diff --git a/hw/serial.c b/hw/serial.c
index d35c7a9207..82917e24d7 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -879,23 +879,33 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
return s;
}
-static ISADeviceInfo serial_isa_info = {
- .qdev.name = "isa-serial",
- .qdev.size = sizeof(ISASerialState),
- .qdev.vmsd = &vmstate_isa_serial,
- .init = serial_isa_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("index", ISASerialState, index, -1),
- DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1),
- DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1),
- DEFINE_PROP_CHR("chardev", ISASerialState, state.chr),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property serial_isa_properties[] = {
+ DEFINE_PROP_UINT32("index", ISASerialState, index, -1),
+ DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1),
+ DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1),
+ DEFINE_PROP_CHR("chardev", ISASerialState, state.chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void serial_isa_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = serial_isa_initfn;
+ dc->vmsd = &vmstate_isa_serial;
+ dc->props = serial_isa_properties;
+}
+
+static TypeInfo serial_isa_info = {
+ .name = "isa-serial",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISASerialState),
+ .class_init = serial_isa_class_initfn,
};
static void serial_register_devices(void)
{
- isa_qdev_register(&serial_isa_info);
+ type_register_static(&serial_isa_info);
}
device_init(serial_register_devices)
diff --git a/hw/sga.c b/hw/sga.c
index 7ef750adf6..b08e3c5aea 100644
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -35,22 +35,29 @@ typedef struct ISAGAState {
ISADevice dev;
} ISASGAState;
-static int isa_cirrus_vga_initfn(ISADevice *dev)
+static int sga_initfn(ISADevice *dev)
{
rom_add_vga(SGABIOS_FILENAME);
return 0;
}
+static void sga_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = sga_initfn;
+ dc->desc = "Serial Graphics Adapter";
+}
-static ISADeviceInfo sga_info = {
- .qdev.name = "sga",
- .qdev.desc = "Serial Graphics Adapter",
- .qdev.size = sizeof(ISASGAState),
- .init = isa_cirrus_vga_initfn,
+static TypeInfo sga_info = {
+ .name = "sga",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISASGAState),
+ .class_init = sga_class_initfn,
};
static void sga_register(void)
{
- isa_qdev_register(&sga_info);
+ type_register_static(&sga_info);
}
device_init(sga_register);
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index d4d028d811..4234d935e7 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -110,7 +110,7 @@ static void sh_pci_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[irq_num], level);
}
-static int sh_pci_init_device(SysBusDevice *dev)
+static int sh_pci_device_init(SysBusDevice *dev)
{
SHPCIState *s;
int i;
@@ -147,19 +147,40 @@ static int sh_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo sh_pci_host_info = {
- .qdev.name = "sh_pci_host",
- .qdev.size = sizeof(PCIDevice),
- .init = sh_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_HITACHI,
- .device_id = PCI_DEVICE_ID_HITACHI_SH7751R,
+static void sh_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = sh_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_HITACHI;
+ k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
+}
+
+static TypeInfo sh_pci_host_info = {
+ .name = "sh_pci_host",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = sh_pci_host_class_init,
+};
+
+static void sh_pci_device_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = sh_pci_device_init;
+}
+
+static TypeInfo sh_pci_device_info = {
+ .name = "sh_pci",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SHPCIState),
+ .class_init = sh_pci_device_class_init,
};
static void sh_pci_register_devices(void)
{
- sysbus_register_dev("sh_pci", sizeof(SHPCIState),
- sh_pci_init_device);
- pci_qdev_register(&sh_pci_host_info);
+ type_register_static(&sh_pci_device_info);
+ type_register_static(&sh_pci_host_info);
}
device_init(sh_pci_register_devices)
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 9925e6460b..e3701c75d2 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -446,17 +446,26 @@ static int slavio_intctl_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo slavio_intctl_info = {
- .init = slavio_intctl_init1,
- .qdev.name = "slavio_intctl",
- .qdev.size = sizeof(SLAVIO_INTCTLState),
- .qdev.vmsd = &vmstate_intctl,
- .qdev.reset = slavio_intctl_reset,
+static void slavio_intctl_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = slavio_intctl_init1;
+ dc->reset = slavio_intctl_reset;
+ dc->vmsd = &vmstate_intctl;
+}
+
+static TypeInfo slavio_intctl_info = {
+ .name = "slavio_intctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SLAVIO_INTCTLState),
+ .class_init = slavio_intctl_class_init,
};
static void slavio_intctl_register_devices(void)
{
- sysbus_register_withprop(&slavio_intctl_info);
+ type_register_static(&slavio_intctl_info);
}
device_init(slavio_intctl_register_devices)
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 484301c48a..5a025186af 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -468,24 +468,41 @@ static int slavio_misc_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo slavio_misc_info = {
- .init = slavio_misc_init1,
- .qdev.name = "slavio_misc",
- .qdev.size = sizeof(MiscState),
- .qdev.vmsd = &vmstate_misc,
- .qdev.reset = slavio_misc_reset,
+static void slavio_misc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = slavio_misc_init1;
+ dc->reset = slavio_misc_reset;
+ dc->vmsd = &vmstate_misc;
+}
+
+static TypeInfo slavio_misc_info = {
+ .name = "slavio_misc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MiscState),
+ .class_init = slavio_misc_class_init,
};
-static SysBusDeviceInfo apc_info = {
- .init = apc_init1,
- .qdev.name = "apc",
- .qdev.size = sizeof(MiscState),
+static void apc_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = apc_init1;
+}
+
+static TypeInfo apc_info = {
+ .name = "apc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MiscState),
+ .class_init = apc_class_init,
};
static void slavio_misc_register_devices(void)
{
- sysbus_register_withprop(&slavio_misc_info);
- sysbus_register_withprop(&apc_info);
+ type_register_static(&slavio_misc_info);
+ type_register_static(&apc_info);
}
device_init(slavio_misc_register_devices)
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 44b500a5fa..3878f6fa5e 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -404,21 +404,32 @@ static int slavio_timer_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo slavio_timer_info = {
- .init = slavio_timer_init1,
- .qdev.name = "slavio_timer",
- .qdev.size = sizeof(SLAVIO_TIMERState),
- .qdev.vmsd = &vmstate_slavio_timer,
- .qdev.reset = slavio_timer_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property slavio_timer_properties[] = {
+ DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void slavio_timer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = slavio_timer_init1;
+ dc->reset = slavio_timer_reset;
+ dc->vmsd = &vmstate_slavio_timer;
+ dc->props = slavio_timer_properties;
+}
+
+static TypeInfo slavio_timer_info = {
+ .name = "slavio_timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SLAVIO_TIMERState),
+ .class_init = slavio_timer_class_init,
};
static void slavio_timer_register_devices(void)
{
- sysbus_register_withprop(&slavio_timer_info);
+ type_register_static(&slavio_timer_info);
}
device_init(slavio_timer_register_devices)
diff --git a/hw/sm501.c b/hw/sm501.c
index 09c5894cf9..94c0abf4cb 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1323,15 +1323,12 @@ static void sm501_draw_crt(SM501State * s)
for (y = 0; y < height; y++) {
int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
int update = full_update || update_hwc;
- ram_addr_t page0 = offset & TARGET_PAGE_MASK;
- ram_addr_t page1 = (offset + width * src_bpp - 1) & TARGET_PAGE_MASK;
- ram_addr_t page;
+ ram_addr_t page0 = offset;
+ ram_addr_t page1 = offset + width * src_bpp - 1;
/* check dirty flags for each line */
- for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
- if (memory_region_get_dirty(&s->local_mem_region, page,
- DIRTY_MEMORY_VGA))
- update = 1;
+ update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
+ DIRTY_MEMORY_VGA);
/* draw line and change status */
if (update) {
diff --git a/hw/smbus.c b/hw/smbus.c
index ff027c814f..77626f3645 100644
--- a/hw/smbus.c
+++ b/hw/smbus.c
@@ -37,37 +37,38 @@ enum {
static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
{
- SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
DPRINTF("Quick Command %d\n", recv);
- if (t->quick_cmd)
- t->quick_cmd(dev, recv);
+ if (sc->quick_cmd) {
+ sc->quick_cmd(dev, recv);
+ }
}
static void smbus_do_write(SMBusDevice *dev)
{
- SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
if (dev->data_len == 0) {
smbus_do_quick_cmd(dev, 0);
} else if (dev->data_len == 1) {
DPRINTF("Send Byte\n");
- if (t->send_byte) {
- t->send_byte(dev, dev->data_buf[0]);
+ if (sc->send_byte) {
+ sc->send_byte(dev, dev->data_buf[0]);
}
} else {
dev->command = dev->data_buf[0];
DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
- if (t->write_data) {
- t->write_data(dev, dev->command, dev->data_buf + 1,
- dev->data_len - 1);
+ if (sc->write_data) {
+ sc->write_data(dev, dev->command, dev->data_buf + 1,
+ dev->data_len - 1);
}
}
}
-static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
+static void smbus_i2c_event(I2CSlave *s, enum i2c_event event)
{
- SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
+ SMBusDevice *dev = SMBUS_DEVICE(s);
switch (event) {
case I2C_START_SEND:
@@ -148,16 +149,16 @@ static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
}
}
-static int smbus_i2c_recv(i2c_slave *s)
+static int smbus_i2c_recv(I2CSlave *s)
{
- SMBusDeviceInfo *t = container_of(s->info, SMBusDeviceInfo, i2c);
- SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
+ SMBusDevice *dev = SMBUS_DEVICE(s);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
int ret;
switch (dev->mode) {
case SMBUS_RECV_BYTE:
- if (t->receive_byte) {
- ret = t->receive_byte(dev);
+ if (sc->receive_byte) {
+ ret = sc->receive_byte(dev);
} else {
ret = 0;
}
@@ -165,8 +166,8 @@ static int smbus_i2c_recv(i2c_slave *s)
dev->mode = SMBUS_DONE;
break;
case SMBUS_READ_DATA:
- if (t->read_data) {
- ret = t->read_data(dev, dev->command, dev->data_len);
+ if (sc->read_data) {
+ ret = sc->read_data(dev, dev->command, dev->data_len);
dev->data_len++;
} else {
ret = 0;
@@ -182,9 +183,9 @@ static int smbus_i2c_recv(i2c_slave *s)
return ret;
}
-static int smbus_i2c_send(i2c_slave *s, uint8_t data)
+static int smbus_i2c_send(I2CSlave *s, uint8_t data)
{
- SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
+ SMBusDevice *dev = SMBUS_DEVICE(s);
switch (dev->mode) {
case SMBUS_WRITE_DATA:
@@ -198,22 +199,12 @@ static int smbus_i2c_send(i2c_slave *s, uint8_t data)
return 0;
}
-static int smbus_device_init(i2c_slave *i2c)
+static int smbus_device_init(I2CSlave *i2c)
{
- SMBusDeviceInfo *t = container_of(i2c->info, SMBusDeviceInfo, i2c);
- SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, i2c);
-
- return t->init(dev);
-}
+ SMBusDevice *dev = SMBUS_DEVICE(i2c);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
-void smbus_register_device(SMBusDeviceInfo *info)
-{
- assert(info->i2c.qdev.size >= sizeof(SMBusDevice));
- info->i2c.init = smbus_device_init;
- info->i2c.event = smbus_i2c_event;
- info->i2c.recv = smbus_i2c_recv;
- info->i2c.send = smbus_i2c_send;
- i2c_register_slave(&info->i2c);
+ return sc->init(dev);
}
/* Master device commands. */
@@ -316,3 +307,29 @@ void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *dat
i2c_send(bus, data[i]);
i2c_end_transfer(bus);
}
+
+static void smbus_device_class_init(ObjectClass *klass, void *data)
+{
+ I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
+
+ sc->init = smbus_device_init;
+ sc->event = smbus_i2c_event;
+ sc->recv = smbus_i2c_recv;
+ sc->send = smbus_i2c_send;
+}
+
+static TypeInfo smbus_device_type_info = {
+ .name = TYPE_SMBUS_DEVICE,
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(SMBusDevice),
+ .abstract = true,
+ .class_size = sizeof(SMBusDeviceClass),
+ .class_init = smbus_device_class_init,
+};
+
+static void smbus_device_register_devices(void)
+{
+ type_register_static(&smbus_device_type_info);
+}
+
+device_init(smbus_device_register_devices);
diff --git a/hw/smbus.h b/hw/smbus.h
index a39871593b..6ed45bd03d 100644
--- a/hw/smbus.h
+++ b/hw/smbus.h
@@ -1,3 +1,6 @@
+#ifndef QEMU_SMBUS_H
+#define QEMU_SMBUS_H
+
/*
* QEMU SMBus API
*
@@ -24,19 +27,17 @@
#include "i2c.h"
-struct SMBusDevice {
- /* The SMBus protocol is implemented on top of I2C. */
- i2c_slave i2c;
-
- /* Remaining fields for internal use only. */
- int mode;
- int data_len;
- uint8_t data_buf[34]; /* command + len + 32 bytes of data. */
- uint8_t command;
-};
+#define TYPE_SMBUS_DEVICE "smbus-device"
+#define SMBUS_DEVICE(obj) \
+ OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE)
+#define SMBUS_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE)
+#define SMBUS_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE)
-typedef struct {
- I2CSlaveInfo i2c;
+typedef struct SMBusDeviceClass
+{
+ I2CSlaveClass parent_class;
int (*init)(SMBusDevice *dev);
void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
void (*send_byte)(SMBusDevice *dev, uint8_t val);
@@ -51,9 +52,18 @@ typedef struct {
byte at a time. The device is responsible for adding the length
byte on block reads. */
uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n);
-} SMBusDeviceInfo;
+} SMBusDeviceClass;
-void smbus_register_device(SMBusDeviceInfo *info);
+struct SMBusDevice {
+ /* The SMBus protocol is implemented on top of I2C. */
+ I2CSlave i2c;
+
+ /* Remaining fields for internal use only. */
+ int mode;
+ int data_len;
+ uint8_t data_buf[34]; /* command + len + 32 bytes of data. */
+ uint8_t command;
+};
/* Master device commands. */
void smbus_quick_command(i2c_bus *bus, uint8_t addr, int read);
@@ -69,3 +79,5 @@ void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *dat
void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int size);
+
+#endif
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 5d080abed7..9d96cbe41a 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -104,24 +104,35 @@ static int smbus_eeprom_initfn(SMBusDevice *dev)
return 0;
}
-static SMBusDeviceInfo smbus_eeprom_info = {
- .i2c.qdev.name = "smbus-eeprom",
- .i2c.qdev.size = sizeof(SMBusEEPROMDevice),
- .i2c.qdev.props = (Property[]) {
- DEFINE_PROP_PTR("data", SMBusEEPROMDevice, data),
- DEFINE_PROP_END_OF_LIST(),
- },
- .init = smbus_eeprom_initfn,
- .quick_cmd = eeprom_quick_cmd,
- .send_byte = eeprom_send_byte,
- .receive_byte = eeprom_receive_byte,
- .write_data = eeprom_write_data,
- .read_data = eeprom_read_data
+static Property smbus_eeprom_properties[] = {
+ DEFINE_PROP_PTR("data", SMBusEEPROMDevice, data),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass);
+
+ sc->init = smbus_eeprom_initfn;
+ sc->quick_cmd = eeprom_quick_cmd;
+ sc->send_byte = eeprom_send_byte;
+ sc->receive_byte = eeprom_receive_byte;
+ sc->write_data = eeprom_write_data;
+ sc->read_data = eeprom_read_data;
+ dc->props = smbus_eeprom_properties;
+}
+
+static TypeInfo smbus_eeprom_info = {
+ .name = "smbus-eeprom",
+ .parent = TYPE_SMBUS_DEVICE,
+ .instance_size = sizeof(SMBusEEPROMDevice),
+ .class_init = smbus_eeprom_class_initfn,
};
static void smbus_eeprom_register_devices(void)
{
- smbus_register_device(&smbus_eeprom_info);
+ type_register_static(&smbus_eeprom_info);
}
device_init(smbus_eeprom_register_devices)
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 82b8811459..1bf2901d1a 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -752,27 +752,38 @@ static int smc91c111_init1(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
/* ??? Save/restore. */
return 0;
}
-static SysBusDeviceInfo smc91c111_info = {
- .init = smc91c111_init1,
- .qdev.name = "smc91c111",
- .qdev.size = sizeof(smc91c111_state),
- .qdev.vmsd = &vmstate_smc91c111,
- .qdev.reset = smc91c111_reset,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property smc91c111_properties[] = {
+ DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void smc91c111_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = smc91c111_init1;
+ dc->reset = smc91c111_reset;
+ dc->vmsd = &vmstate_smc91c111;
+ dc->props = smc91c111_properties;
+}
+
+static TypeInfo smc91c111_info = {
+ .name = "smc91c111",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(smc91c111_state),
+ .class_init = smc91c111_class_init,
};
static void smc91c111_register_devices(void)
{
- sysbus_register_withprop(&smc91c111_info);
+ type_register_static(&smc91c111_info);
}
/* Legacy helper function. Should go away when machine config files are
diff --git a/hw/spapr.c b/hw/spapr.c
index 0e1f80dfdc..dffb6a2a50 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -50,19 +50,29 @@
#include <libfdt.h>
-#define KERNEL_LOAD_ADDR 0x00000000
-#define INITRD_LOAD_ADDR 0x02800000
+/* SLOF memory layout:
+ *
+ * SLOF raw image loaded at 0, copies its romfs right below the flat
+ * device-tree, then position SLOF itself 31M below that
+ *
+ * So we set FW_OVERHEAD to 40MB which should account for all of that
+ * and more
+ *
+ * We load our kernel at 4M, leaving space for SLOF initial image
+ */
#define FDT_MAX_SIZE 0x10000
#define RTAS_MAX_SIZE 0x10000
#define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin"
+#define FW_OVERHEAD 0x2800000
+#define KERNEL_LOAD_ADDR FW_MAX_SIZE
-#define MIN_RMA_SLOF 128UL
+#define MIN_RMA_SLOF 128UL
#define TIMEBASE_FREQ 512000000ULL
#define MAX_CPUS 256
-#define XICS_IRQS 1024
+#define XICS_IRQS 1024
#define SPAPR_PCI_BUID 0x800000020000001ULL
#define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000)
@@ -139,6 +149,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
target_phys_addr_t rma_size,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
+ target_phys_addr_t kernel_size,
const char *boot_device,
const char *kernel_cmdline,
long hash_shift)
@@ -176,6 +187,12 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
fdt = g_malloc0(FDT_MAX_SIZE);
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+ if (kernel_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
+ }
+ if (initrd_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));
+ }
_FDT((fdt_finish_reservemap(fdt)));
/* Root node */
@@ -197,15 +214,13 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
&start_prop, sizeof(start_prop))));
_FDT((fdt_property(fdt, "linux,initrd-end",
&end_prop, sizeof(end_prop))));
- _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
+ if (kernel_size) {
+ uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
+ cpu_to_be64(kernel_size) };
- /*
- * Because we don't always invoke any firmware, we can't rely on
- * that to do BAR allocation. Long term, we should probably do
- * that ourselves, but for now, this setting (plus advertising the
- * current BARs as 0) causes sufficiently recent kernels to to the
- * BAR assignment themselves */
- _FDT((fdt_property_cell(fdt, "linux,pci-probe-only", 0)));
+ _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
+ }
+ _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
_FDT((fdt_end_node(fdt)));
@@ -445,6 +460,12 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
_FDT((fdt_pack(fdt)));
+ if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
+ hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
+ fdt_totalsize(fdt), FDT_MAX_SIZE);
+ exit(1);
+ }
+
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
g_free(fdt);
@@ -494,8 +515,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
target_phys_addr_t rma_alloc_size, rma_size;
- uint32_t initrd_base;
- long kernel_size, initrd_size, fw_size;
+ uint32_t initrd_base = 0;
+ long kernel_size = 0, initrd_size = 0;
+ long load_limit, rtas_limit, fw_size;
long pteg_shift = 17;
char *filename;
@@ -517,11 +539,13 @@ static void ppc_spapr_init(ram_addr_t ram_size,
rma_size = ram_size;
}
- /* We place the device tree just below either the top of the RMA,
+ /* We place the device tree and RTAS just below either the top of the RMA,
* or just below 2GB, whichever is lowere, so that it can be
* processed with 32-bit real mode code if necessary */
- spapr->fdt_addr = MIN(rma_size, 0x80000000) - FDT_MAX_SIZE;
- spapr->rtas_addr = spapr->fdt_addr - RTAS_MAX_SIZE;
+ rtas_limit = MIN(rma_size, 0x80000000);
+ spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
+ spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
+ load_limit = spapr->fdt_addr - FW_OVERHEAD;
/* init CPUs */
if (cpu_model == NULL) {
@@ -577,13 +601,19 @@ static void ppc_spapr_init(ram_addr_t ram_size,
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
- ram_size - spapr->rtas_addr);
+ rtas_limit - spapr->rtas_addr);
if (spapr->rtas_size < 0) {
hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
exit(1);
}
+ if (spapr->rtas_size > RTAS_MAX_SIZE) {
+ hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
+ spapr->rtas_size, RTAS_MAX_SIZE);
+ exit(1);
+ }
g_free(filename);
+
/* Set up Interrupt Controller */
spapr->icp = xics_system_init(XICS_IRQS);
spapr->next_irq = 16;
@@ -622,6 +652,20 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr_vscsi_create(spapr->vio_bus, 0x2000 + i);
}
+ if (rma_size < (MIN_RMA_SLOF << 20)) {
+ fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
+ "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
+ exit(1);
+ }
+
+ fprintf(stderr, "sPAPR memory map:\n");
+ fprintf(stderr, "RTAS : 0x%08lx..%08lx\n",
+ (unsigned long)spapr->rtas_addr,
+ (unsigned long)(spapr->rtas_addr + spapr->rtas_size - 1));
+ fprintf(stderr, "FDT : 0x%08lx..%08lx\n",
+ (unsigned long)spapr->fdt_addr,
+ (unsigned long)(spapr->fdt_addr + FDT_MAX_SIZE - 1));
+
if (kernel_filename) {
uint64_t lowaddr = 0;
@@ -630,57 +674,60 @@ static void ppc_spapr_init(ram_addr_t ram_size,
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename,
KERNEL_LOAD_ADDR,
- ram_size - KERNEL_LOAD_ADDR);
+ load_limit - KERNEL_LOAD_ADDR);
}
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
+ fprintf(stderr, "Kernel : 0x%08x..%08lx\n",
+ KERNEL_LOAD_ADDR, KERNEL_LOAD_ADDR + kernel_size - 1);
/* load initrd */
if (initrd_filename) {
- initrd_base = INITRD_LOAD_ADDR;
+ /* Try to locate the initrd in the gap between the kernel
+ * and the firmware. Add a bit of space just in case
+ */
+ initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
initrd_size = load_image_targphys(initrd_filename, initrd_base,
- ram_size - initrd_base);
+ load_limit - initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
+ fprintf(stderr, "Ramdisk : 0x%08lx..%08lx\n",
+ (long)initrd_base, (long)(initrd_base + initrd_size - 1));
} else {
initrd_base = 0;
initrd_size = 0;
}
+ }
- spapr->entry_point = KERNEL_LOAD_ADDR;
- } else {
- if (rma_size < (MIN_RMA_SLOF << 20)) {
- fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
- "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
- exit(1);
- }
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
- fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
- if (fw_size < 0) {
- hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
- exit(1);
- }
- g_free(filename);
- spapr->entry_point = 0x100;
- initrd_base = 0;
- initrd_size = 0;
-
- /* SLOF will startup the secondary CPUs using RTAS,
- rather than expecting a kexec() style entry */
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- env->halted = 1;
- }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
+ fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
+ if (fw_size < 0) {
+ hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+ exit(1);
+ }
+ g_free(filename);
+ fprintf(stderr, "Firmware load : 0x%08x..%08lx\n",
+ 0, fw_size);
+ fprintf(stderr, "Firmware runtime : 0x%08lx..%08lx\n",
+ load_limit, (unsigned long)spapr->fdt_addr);
+
+ spapr->entry_point = 0x100;
+
+ /* SLOF will startup the secondary CPUs using RTAS */
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ env->halted = 1;
}
/* Prepare the device tree */
spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size,
initrd_base, initrd_size,
+ kernel_size,
boot_device, kernel_cmdline,
pteg_shift + 7);
assert(spapr->fdt_skel != NULL);
@@ -693,7 +740,6 @@ static QEMUMachine spapr_machine = {
.desc = "pSeries Logical Partition (PAPR compliant)",
.init = ppc_spapr_init,
.max_cpus = MAX_CPUS,
- .no_vga = 1,
.no_parallel = 1,
.use_scsi = 1,
};
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 45674c4cb9..79b394132b 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -189,7 +189,7 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
- sdev->qdev.info->name, sdev->qdev.id, dev);
+ object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
qemu_format_nic_info_str(&dev->nic->nc, dev->nicconf.macaddr.a);
return 0;
@@ -474,30 +474,41 @@ static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
-static VIOsPAPRDeviceInfo spapr_vlan = {
- .init = spapr_vlan_init,
- .devnode = spapr_vlan_devnode,
- .dt_name = "l-lan",
- .dt_type = "network",
- .dt_compatible = "IBM,l-lan",
- .signal_mask = 0x1,
- .qdev.name = "spapr-vlan",
- .qdev.size = sizeof(VIOsPAPRVLANDevice),
- .qdev.props = (Property[]) {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000),
- DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property spapr_vlan_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000),
+ DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_vlan_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+ k->init = spapr_vlan_init;
+ k->devnode = spapr_vlan_devnode;
+ k->dt_name = "l-lan";
+ k->dt_type = "network";
+ k->dt_compatible = "IBM,l-lan";
+ k->signal_mask = 0x1;
+ dc->props = spapr_vlan_properties;
+}
+
+static TypeInfo spapr_vlan_info = {
+ .name = "spapr-vlan",
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(VIOsPAPRVLANDevice),
+ .class_init = spapr_vlan_class_init,
};
static void spapr_vlan_register(void)
{
- spapr_vio_bus_register_withprop(&spapr_vlan);
spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
h_add_logical_lan_buffer);
spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
+ type_register_static(&spapr_vlan_info);
}
device_init(spapr_vlan_register);
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 9b6a032cce..ed2e4b33e7 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -62,6 +62,30 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr,
return NULL;
}
+static uint32_t rtas_pci_cfgaddr(uint32_t arg)
+{
+ return ((arg >> 20) & 0xf00) | (arg & 0xff);
+}
+
+static uint32_t rtas_read_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
+ uint32_t limit, uint32_t len)
+{
+ if ((addr + len) <= limit) {
+ return pci_host_config_read_common(pci_dev, addr, limit, len);
+ } else {
+ return ~0x0;
+ }
+}
+
+static void rtas_write_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
+ uint32_t limit, uint32_t val,
+ uint32_t len)
+{
+ if ((addr + len) <= limit) {
+ pci_host_config_write_common(pci_dev, addr, limit, val, len);
+ }
+}
+
static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
@@ -76,8 +100,8 @@ static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
return;
}
size = rtas_ld(args, 3);
- addr = rtas_ld(args, 0) & 0xFF;
- val = pci_default_read_config(dev, addr, size);
+ addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
+ val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
rtas_st(rets, 0, 0);
rtas_st(rets, 1, val);
}
@@ -95,8 +119,8 @@ static void rtas_read_pci_config(sPAPREnvironment *spapr,
return;
}
size = rtas_ld(args, 1);
- addr = rtas_ld(args, 0) & 0xFF;
- val = pci_default_read_config(dev, addr, size);
+ addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
+ val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
rtas_st(rets, 0, 0);
rtas_st(rets, 1, val);
}
@@ -116,8 +140,8 @@ static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
}
val = rtas_ld(args, 4);
size = rtas_ld(args, 3);
- addr = rtas_ld(args, 0) & 0xFF;
- pci_default_write_config(dev, addr, val, size);
+ addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
+ rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
rtas_st(rets, 0, 0);
}
@@ -135,8 +159,8 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr,
}
val = rtas_ld(args, 2);
size = rtas_ld(args, 1);
- addr = rtas_ld(args, 0) & 0xFF;
- pci_default_write_config(dev, addr, val, size);
+ addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
+ rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
rtas_st(rets, 0, 0);
}
@@ -190,17 +214,38 @@ static int spapr_main_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo spapr_main_pci_host_info = {
- .qdev.name = "spapr-pci-host-bridge",
- .qdev.size = sizeof(PCIDevice),
- .init = spapr_main_pci_host_init,
+static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = spapr_main_pci_host_init;
+}
+
+static TypeInfo spapr_main_pci_host_info = {
+ .name = "spapr-pci-host-bridge-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = spapr_main_pci_host_class_init,
+};
+
+static void spapr_phb_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = spapr_phb_init;
+}
+
+static TypeInfo spapr_phb_info = {
+ .name = "spapr-pci-host-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(sPAPRPHBState),
+ .class_init = spapr_phb_class_init,
};
static void spapr_register_devices(void)
{
- sysbus_register_dev("spapr-pci-host-bridge", sizeof(sPAPRPHBState),
- spapr_phb_init);
- pci_qdev_register(&spapr_main_pci_host_info);
+ type_register_static(&spapr_phb_info);
+ type_register_static(&spapr_main_pci_host_info);
}
device_init(spapr_register_devices)
@@ -319,31 +364,13 @@ void spapr_create_phb(sPAPREnvironment *spapr,
#define b_fff(x) b_x((x), 8, 3) /* function number */
#define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */
-static uint32_t regtype_to_ss(uint8_t type)
-{
- if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- return 3;
- }
- if (type == PCI_BASE_ADDRESS_SPACE_IO) {
- return 1;
- }
- return 2;
-}
-
int spapr_populate_pci_devices(sPAPRPHBState *phb,
uint32_t xics_phandle,
void *fdt)
{
PCIBus *bus = phb->host_state.bus;
- int bus_off, node_off = 0, devid, fn, i, n, devices;
- DeviceState *qdev;
+ int bus_off, i;
char nodename[256];
- struct {
- uint32_t hi;
- uint64_t addr;
- uint64_t size;
- } __attribute__((packed)) reg[PCI_NUM_REGIONS + 1],
- assigned_addresses[PCI_NUM_REGIONS];
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
struct {
uint32_t hi;
@@ -364,7 +391,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
};
uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
uint32_t interrupt_map_mask[] = {
- cpu_to_be32(b_ddddd(-1)|b_fff(-1)), 0x0, 0x0, 0x0};
+ cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, 0x0};
uint32_t interrupt_map[bus->nirq][7];
/* Start populating the FDT */
@@ -392,117 +419,26 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
+ _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
+
+ /* Build the interrupt-map, this must matches what is done
+ * in pci_spapr_map_irq
+ */
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
&interrupt_map_mask, sizeof(interrupt_map_mask)));
-
- /* Populate PCI devices and allocate IRQs */
- devices = 0;
- QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
- PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
- int irq_index = pci_spapr_map_irq(dev, 0);
- uint32_t *irqmap = interrupt_map[devices];
- uint8_t *config = dev->config;
-
- devid = dev->devfn >> 3;
- fn = dev->devfn & 7;
-
- sprintf(nodename, "pci@%u,%u", devid, fn);
-
- /* Allocate interrupt from the map */
- if (devid > bus->nirq) {
- printf("Unexpected behaviour in spapr_populate_pci_devices,"
- "wrong devid %u\n", devid);
- exit(-1);
- }
- irqmap[0] = cpu_to_be32(b_ddddd(devid)|b_fff(fn));
+ for (i = 0; i < 7; i++) {
+ uint32_t *irqmap = interrupt_map[i];
+ irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
irqmap[1] = 0;
irqmap[2] = 0;
irqmap[3] = 0;
irqmap[4] = cpu_to_be32(xics_phandle);
- irqmap[5] = cpu_to_be32(phb->lsi_table[irq_index].dt_irq);
+ irqmap[5] = cpu_to_be32(phb->lsi_table[i % SPAPR_PCI_NUM_LSI].dt_irq);
irqmap[6] = cpu_to_be32(0x8);
-
- /* Add node to FDT */
- node_off = fdt_add_subnode(fdt, bus_off, nodename);
- if (node_off < 0) {
- return node_off;
- }
-
- _FDT(fdt_setprop_cell(fdt, node_off, "vendor-id",
- pci_get_word(&config[PCI_VENDOR_ID])));
- _FDT(fdt_setprop_cell(fdt, node_off, "device-id",
- pci_get_word(&config[PCI_DEVICE_ID])));
- _FDT(fdt_setprop_cell(fdt, node_off, "revision-id",
- pci_get_byte(&config[PCI_REVISION_ID])));
- _FDT(fdt_setprop_cell(fdt, node_off, "class-code",
- pci_get_long(&config[PCI_CLASS_REVISION]) >> 8));
- _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-id",
- pci_get_word(&config[PCI_SUBSYSTEM_ID])));
- _FDT(fdt_setprop_cell(fdt, node_off, "subsystem-vendor-id",
- pci_get_word(&config[PCI_SUBSYSTEM_VENDOR_ID])));
-
- /* Config space region comes first */
- reg[0].hi = cpu_to_be32(
- b_n(0) |
- b_p(0) |
- b_t(0) |
- b_ss(0/*config*/) |
- b_bbbbbbbb(0) |
- b_ddddd(devid) |
- b_fff(fn));
- reg[0].addr = 0;
- reg[0].size = 0;
-
- n = 0;
- for (i = 0; i < ARRAY_SIZE(bars); ++i) {
- if (0 == dev->io_regions[i].size) {
- continue;
- }
-
- reg[n+1].hi = cpu_to_be32(
- b_n(0) |
- b_p(0) |
- b_t(0) |
- b_ss(regtype_to_ss(dev->io_regions[i].type)) |
- b_bbbbbbbb(0) |
- b_ddddd(devid) |
- b_fff(fn) |
- b_rrrrrrrr(bars[i]));
- reg[n+1].addr = 0;
- reg[n+1].size = cpu_to_be64(dev->io_regions[i].size);
-
- assigned_addresses[n].hi = cpu_to_be32(
- b_n(1) |
- b_p(0) |
- b_t(0) |
- b_ss(regtype_to_ss(dev->io_regions[i].type)) |
- b_bbbbbbbb(0) |
- b_ddddd(devid) |
- b_fff(fn) |
- b_rrrrrrrr(bars[i]));
-
- /*
- * Writing zeroes to assigned_addresses causes the guest kernel to
- * reassign BARs
- */
- assigned_addresses[n].addr = cpu_to_be64(dev->io_regions[i].addr);
- assigned_addresses[n].size = reg[n+1].size;
-
- ++n;
- }
- _FDT(fdt_setprop(fdt, node_off, "reg", reg, sizeof(reg[0])*(n+1)));
- _FDT(fdt_setprop(fdt, node_off, "assigned-addresses",
- assigned_addresses,
- sizeof(assigned_addresses[0])*(n)));
- _FDT(fdt_setprop_cell(fdt, node_off, "interrupts",
- pci_get_byte(&config[PCI_INTERRUPT_PIN])));
-
- ++devices;
}
-
/* Write interrupt map */
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
- devices * sizeof(interrupt_map[0])));
+ 7 * sizeof(interrupt_map[0])));
return 0;
}
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 7a86dc8d2c..64f0009814 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -75,11 +75,11 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
static char *vio_format_dev_name(VIOsPAPRDevice *dev)
{
- VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
char *name;
/* Device tree style name device@reg */
- if (asprintf(&name, "%s@%x", info->dt_name, dev->reg) < 0) {
+ if (asprintf(&name, "%s@%x", pc->dt_name, dev->reg) < 0) {
return NULL;
}
@@ -90,7 +90,7 @@ static char *vio_format_dev_name(VIOsPAPRDevice *dev)
static int vio_make_devnode(VIOsPAPRDevice *dev,
void *fdt)
{
- VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
int vdevice_off, node_off, ret;
char *dt_name;
@@ -115,17 +115,17 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
return ret;
}
- if (info->dt_type) {
+ if (pc->dt_type) {
ret = fdt_setprop_string(fdt, node_off, "device_type",
- info->dt_type);
+ pc->dt_type);
if (ret < 0) {
return ret;
}
}
- if (info->dt_compatible) {
+ if (pc->dt_compatible) {
ret = fdt_setprop_string(fdt, node_off, "compatible",
- info->dt_compatible);
+ pc->dt_compatible);
if (ret < 0) {
return ret;
}
@@ -163,8 +163,8 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
}
}
- if (info->devnode) {
- ret = (info->devnode)(dev, fdt, node_off);
+ if (pc->devnode) {
+ ret = (pc->devnode)(dev, fdt, node_off);
if (ret < 0) {
return ret;
}
@@ -621,7 +621,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
rtas_st(rets, 0, 0);
}
-static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
+static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
{
VIOsPAPRDevice *other_sdev;
DeviceState *qdev;
@@ -639,7 +639,9 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
- info->qdev.name, other_sdev->qdev.info->name, sdev->reg);
+ object_get_typename(OBJECT(sdev)),
+ object_get_typename(OBJECT(qdev)),
+ sdev->reg);
return -EEXIST;
}
}
@@ -647,14 +649,14 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
return 0;
}
-static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
+static int spapr_vio_busdev_init(DeviceState *qdev)
{
- VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
char *id;
int ret;
- ret = spapr_vio_check_reg(dev, info);
+ ret = spapr_vio_check_reg(dev);
if (ret) {
return ret;
}
@@ -675,16 +677,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
rtce_init(dev);
- return info->init(dev);
-}
-
-void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info)
-{
- info->qdev.init = spapr_vio_busdev_init;
- info->qdev.bus_info = &spapr_vio_bus_info;
-
- assert(info->qdev.size >= sizeof(VIOsPAPRDevice));
- qdev_register(&info->qdev);
+ return pc->init(dev);
}
static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr,
@@ -694,15 +687,15 @@ static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr,
target_ulong reg = args[0];
target_ulong mode = args[1];
VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- VIOsPAPRDeviceInfo *info;
+ VIOsPAPRDeviceClass *pc;
if (!dev) {
return H_PARAMETER;
}
- info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+ pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- if (mode & ~info->signal_mask) {
+ if (mode & ~pc->signal_mask) {
return H_PARAMETER;
}
@@ -753,16 +746,42 @@ static int spapr_vio_bridge_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo spapr_vio_bridge_info = {
- .init = spapr_vio_bridge_init,
- .qdev.name = "spapr-vio-bridge",
- .qdev.size = sizeof(SysBusDevice),
- .qdev.no_user = 1,
+static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = spapr_vio_bridge_init;
+ dc->no_user = 1;
+}
+
+static TypeInfo spapr_vio_bridge_info = {
+ .name = "spapr-vio-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = spapr_vio_bridge_class_init,
+};
+
+static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = spapr_vio_busdev_init;
+ k->bus_info = &spapr_vio_bus_info;
+}
+
+static TypeInfo spapr_vio_type_info = {
+ .name = TYPE_VIO_SPAPR_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VIOsPAPRDevice),
+ .abstract = true,
+ .class_size = sizeof(VIOsPAPRDeviceClass),
+ .class_init = vio_spapr_device_class_init,
};
static void spapr_vio_register_devices(void)
{
- sysbus_register_withprop(&spapr_vio_bridge_info);
+ type_register_static(&spapr_vio_bridge_info);
+ type_register_static(&spapr_vio_type_info);
}
device_init(spapr_vio_register_devices)
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 0984d559db..d8527bed90 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -34,6 +34,14 @@ enum VIOsPAPR_TCEAccess {
#define SPAPR_VTY_BASE_ADDRESS 0x30000000
+#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
+#define VIO_SPAPR_DEVICE(obj) \
+ OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
+#define VIO_SPAPR_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VIOsPAPRDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE)
+#define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
+
struct VIOsPAPRDevice;
typedef struct VIOsPAPR_RTCE {
@@ -47,7 +55,20 @@ typedef struct VIOsPAPR_CRQ {
int(*SendFunc)(struct VIOsPAPRDevice *vdev, uint8_t *crq);
} VIOsPAPR_CRQ;
-typedef struct VIOsPAPRDevice {
+typedef struct VIOsPAPRDevice VIOsPAPRDevice;
+typedef struct VIOsPAPRBus VIOsPAPRBus;
+
+typedef struct VIOsPAPRDeviceClass {
+ DeviceClass parent_class;
+
+ const char *dt_name, *dt_type, *dt_compatible;
+ target_ulong signal_mask;
+ int (*init)(VIOsPAPRDevice *dev);
+ void (*hcalls)(VIOsPAPRBus *bus);
+ int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
+} VIOsPAPRDeviceClass;
+
+struct VIOsPAPRDevice {
DeviceState qdev;
uint32_t reg;
uint32_t flags;
@@ -59,28 +80,23 @@ typedef struct VIOsPAPRDevice {
VIOsPAPR_RTCE *rtce_table;
int kvmtce_fd;
VIOsPAPR_CRQ crq;
-} VIOsPAPRDevice;
+};
#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \
DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \
DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \
default_dma_window)
-typedef struct VIOsPAPRBus {
+struct VIOsPAPRBus {
BusState bus;
-} VIOsPAPRBus;
-
-typedef struct {
- DeviceInfo qdev;
const char *dt_name, *dt_type, *dt_compatible;
target_ulong signal_mask;
int (*init)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
-} VIOsPAPRDeviceInfo;
+};
extern VIOsPAPRBus *spapr_vio_bus_init(void);
extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
-extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 00e2d2d5d3..9cfce19a73 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -947,23 +947,34 @@ static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
return 0;
}
-static VIOsPAPRDeviceInfo spapr_vscsi = {
- .init = spapr_vscsi_init,
- .devnode = spapr_vscsi_devnode,
- .dt_name = "v-scsi",
- .dt_type = "vscsi",
- .dt_compatible = "IBM,v-scsi",
- .signal_mask = 0x00000001,
- .qdev.name = "spapr-vscsi",
- .qdev.size = sizeof(VSCSIState),
- .qdev.props = (Property[]) {
- DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property spapr_vscsi_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+ k->init = spapr_vscsi_init;
+ k->devnode = spapr_vscsi_devnode;
+ k->dt_name = "v-scsi";
+ k->dt_type = "vscsi";
+ k->dt_compatible = "IBM,v-scsi";
+ k->signal_mask = 0x00000001;
+ dc->props = spapr_vscsi_properties;
+}
+
+static TypeInfo spapr_vscsi_info = {
+ .name = "spapr-vscsi",
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(VSCSIState),
+ .class_init = spapr_vscsi_class_init,
};
static void spapr_vscsi_register(void)
{
- spapr_vio_bus_register_withprop(&spapr_vscsi);
+ type_register_static(&spapr_vscsi_info);
}
device_init(spapr_vscsi_register);
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index c5fb0968ed..a954e7d29b 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -135,18 +135,29 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
qdev_init_nofail(dev);
}
-static VIOsPAPRDeviceInfo spapr_vty = {
- .init = spapr_vty_init,
- .dt_name = "vty",
- .dt_type = "serial",
- .dt_compatible = "hvterm1",
- .qdev.name = "spapr-vty",
- .qdev.size = sizeof(VIOsPAPRVTYDevice),
- .qdev.props = (Property[]) {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
- DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property spapr_vty_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
+ DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_vty_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+ k->init = spapr_vty_init;
+ k->dt_name = "vty";
+ k->dt_type = "serial";
+ k->dt_compatible = "hvterm1";
+ dc->props = spapr_vty_properties;
+}
+
+static TypeInfo spapr_vty_info = {
+ .name = "spapr-vty",
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(VIOsPAPRVTYDevice),
+ .class_init = spapr_vty_class_init,
};
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
@@ -163,7 +174,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
selected = NULL;
QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
/* Only look at VTY devices */
- if (iter->info != &spapr_vty.qdev) {
+ if (!object_dynamic_cast(OBJECT(iter), "spapr-vty")) {
continue;
}
@@ -203,8 +214,8 @@ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
static void spapr_vty_register(void)
{
- spapr_vio_bus_register_withprop(&spapr_vty);
spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
+ type_register_static(&spapr_vty_info);
}
device_init(spapr_vty_register);
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 035d2e205b..f07cc6fdf0 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -283,22 +283,33 @@ static int sparc32_dma_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo sparc32_dma_info = {
- .init = sparc32_dma_init1,
- .qdev.name = "sparc32_dma",
- .qdev.size = sizeof(DMAState),
- .qdev.vmsd = &vmstate_dma,
- .qdev.reset = dma_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
- DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property sparc32_dma_properties[] = {
+ DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
+ DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sparc32_dma_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sparc32_dma_init1;
+ dc->reset = dma_reset;
+ dc->vmsd = &vmstate_dma;
+ dc->props = sparc32_dma_properties;
+}
+
+static TypeInfo sparc32_dma_info = {
+ .name = "sparc32_dma",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(DMAState),
+ .class_init = sparc32_dma_class_init,
};
static void sparc32_dma_register_devices(void)
{
- sysbus_register_withprop(&sparc32_dma_info);
+ type_register_static(&sparc32_dma_info);
}
device_init(sparc32_dma_register_devices)
diff --git a/hw/spitz.c b/hw/spitz.c
index 9d129c22b9..4e6540d976 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -717,7 +717,7 @@ static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
static void spitz_wm8750_addr(void *opaque, int line, int level)
{
- i2c_slave *wm = (i2c_slave *) opaque;
+ I2CSlave *wm = (I2CSlave *) opaque;
if (level)
i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
else
@@ -1023,16 +1023,27 @@ static VMStateDescription vmstate_sl_nand_info = {
},
};
-static SysBusDeviceInfo sl_nand_info = {
- .init = sl_nand_init,
- .qdev.name = "sl-nand",
- .qdev.size = sizeof(SLNANDState),
- .qdev.vmsd = &vmstate_sl_nand_info,
- .qdev.props = (Property []) {
- DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
- DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property sl_nand_properties[] = {
+ DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
+ DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sl_nand_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sl_nand_init;
+ dc->vmsd = &vmstate_sl_nand_info;
+ dc->props = sl_nand_properties;
+}
+
+static TypeInfo sl_nand_info = {
+ .name = "sl-nand",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SLNANDState),
+ .class_init = sl_nand_class_init,
};
static VMStateDescription vmstate_spitz_kbd = {
@@ -1049,14 +1060,25 @@ static VMStateDescription vmstate_spitz_kbd = {
},
};
-static SysBusDeviceInfo spitz_keyboard_info = {
- .init = spitz_keyboard_init,
- .qdev.name = "spitz-keyboard",
- .qdev.size = sizeof(SpitzKeyboardState),
- .qdev.vmsd = &vmstate_spitz_kbd,
- .qdev.props = (Property []) {
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property spitz_keyboard_properties[] = {
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = spitz_keyboard_init;
+ dc->vmsd = &vmstate_spitz_kbd;
+ dc->props = spitz_keyboard_properties;
+}
+
+static TypeInfo spitz_keyboard_info = {
+ .name = "spitz-keyboard",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SpitzKeyboardState),
+ .class_init = spitz_keyboard_class_init,
};
static const VMStateDescription vmstate_corgi_ssp_regs = {
@@ -1070,12 +1092,21 @@ static const VMStateDescription vmstate_corgi_ssp_regs = {
}
};
-static SSISlaveInfo corgi_ssp_info = {
- .qdev.name = "corgi-ssp",
- .qdev.size = sizeof(CorgiSSPState),
- .qdev.vmsd = &vmstate_corgi_ssp_regs,
- .init = corgi_ssp_init,
- .transfer = corgi_ssp_transfer
+static void corgi_ssp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = corgi_ssp_init;
+ k->transfer = corgi_ssp_transfer;
+ dc->vmsd = &vmstate_corgi_ssp_regs;
+}
+
+static TypeInfo corgi_ssp_info = {
+ .name = "corgi-ssp",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(CorgiSSPState),
+ .class_init = corgi_ssp_class_init,
};
static const VMStateDescription vmstate_spitz_lcdtg_regs = {
@@ -1090,20 +1121,29 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = {
}
};
-static SSISlaveInfo spitz_lcdtg_info = {
- .qdev.name = "spitz-lcdtg",
- .qdev.size = sizeof(SpitzLCDTG),
- .qdev.vmsd = &vmstate_spitz_lcdtg_regs,
- .init = spitz_lcdtg_init,
- .transfer = spitz_lcdtg_transfer
+static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = spitz_lcdtg_init;
+ k->transfer = spitz_lcdtg_transfer;
+ dc->vmsd = &vmstate_spitz_lcdtg_regs;
+}
+
+static TypeInfo spitz_lcdtg_info = {
+ .name = "spitz-lcdtg",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(SpitzLCDTG),
+ .class_init = spitz_lcdtg_class_init,
};
static void spitz_register_devices(void)
{
- ssi_register_slave(&corgi_ssp_info);
- ssi_register_slave(&spitz_lcdtg_info);
- sysbus_register_withprop(&spitz_keyboard_info);
- sysbus_register_withprop(&sl_nand_info);
+ type_register_static(&corgi_ssp_info);
+ type_register_static(&spitz_lcdtg_info);
+ type_register_static(&spitz_keyboard_info);
+ type_register_static(&sl_nand_info);
}
device_init(spitz_register_devices)
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index bcad7bf922..685602a584 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -42,7 +42,7 @@ enum ssd0303_cmd {
};
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
DisplayState *ds;
int row;
int col;
@@ -57,13 +57,13 @@ typedef struct {
uint8_t framebuffer[132*8];
} ssd0303_state;
-static int ssd0303_recv(i2c_slave *i2c)
+static int ssd0303_recv(I2CSlave *i2c)
{
BADF("Reads not implemented\n");
return -1;
}
-static int ssd0303_send(i2c_slave *i2c, uint8_t data)
+static int ssd0303_send(I2CSlave *i2c, uint8_t data)
{
ssd0303_state *s = (ssd0303_state *)i2c;
enum ssd0303_cmd old_cmd_state;
@@ -173,7 +173,7 @@ static int ssd0303_send(i2c_slave *i2c, uint8_t data)
return 0;
}
-static void ssd0303_event(i2c_slave *i2c, enum i2c_event event)
+static void ssd0303_event(I2CSlave *i2c, enum i2c_event event)
{
ssd0303_state *s = (ssd0303_state *)i2c;
switch (event) {
@@ -283,7 +283,7 @@ static const VMStateDescription vmstate_ssd0303 = {
}
};
-static int ssd0303_init(i2c_slave *i2c)
+static int ssd0303_init(I2CSlave *i2c)
{
ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
@@ -294,19 +294,28 @@ static int ssd0303_init(i2c_slave *i2c)
return 0;
}
-static I2CSlaveInfo ssd0303_info = {
- .qdev.name = "ssd0303",
- .qdev.size = sizeof(ssd0303_state),
- .qdev.vmsd = &vmstate_ssd0303,
- .init = ssd0303_init,
- .event = ssd0303_event,
- .recv = ssd0303_recv,
- .send = ssd0303_send
+static void ssd0303_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = ssd0303_init;
+ k->event = ssd0303_event;
+ k->recv = ssd0303_recv;
+ k->send = ssd0303_send;
+ dc->vmsd = &vmstate_ssd0303;
+}
+
+static TypeInfo ssd0303_info = {
+ .name = "ssd0303",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(ssd0303_state),
+ .class_init = ssd0303_class_init,
};
static void ssd0303_register_devices(void)
{
- i2c_register_slave(&ssd0303_info);
+ type_register_static(&ssd0303_info);
}
device_init(ssd0303_register_devices)
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 1eb3823fed..3c43738ae1 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -340,16 +340,24 @@ static int ssd0323_init(SSISlave *dev)
return 0;
}
-static SSISlaveInfo ssd0323_info = {
- .qdev.name = "ssd0323",
- .qdev.size = sizeof(ssd0323_state),
- .init = ssd0323_init,
- .transfer = ssd0323_transfer
+static void ssd0323_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = ssd0323_init;
+ k->transfer = ssd0323_transfer;
+}
+
+static TypeInfo ssd0323_info = {
+ .name = "ssd0323",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(ssd0323_state),
+ .class_init = ssd0323_class_init,
};
static void ssd03232_register_devices(void)
{
- ssi_register_slave(&ssd0323_info);
+ type_register_static(&ssd0323_info);
}
device_init(ssd03232_register_devices)
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 2d89cfe522..f2e6cecb71 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -244,16 +244,24 @@ static int ssi_sd_init(SSISlave *dev)
return 0;
}
-static SSISlaveInfo ssi_sd_info = {
- .qdev.name = "ssi-sd",
- .qdev.size = sizeof(ssi_sd_state),
- .init = ssi_sd_init,
- .transfer = ssi_sd_transfer
+static void ssi_sd_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = ssi_sd_init;
+ k->transfer = ssi_sd_transfer;
+}
+
+static TypeInfo ssi_sd_info = {
+ .name = "ssi-sd",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(ssi_sd_state),
+ .class_init = ssi_sd_class_init,
};
static void ssi_sd_register_devices(void)
{
- ssi_register_slave(&ssi_sd_info);
+ type_register_static(&ssi_sd_info);
}
device_init(ssi_sd_register_devices)
diff --git a/hw/ssi.c b/hw/ssi.c
index b47953a989..ead446c49a 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -21,10 +21,10 @@ static struct BusInfo ssi_bus_info = {
.size = sizeof(SSIBus),
};
-static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
+static int ssi_slave_init(DeviceState *dev)
{
- SSISlaveInfo *info = container_of(base_info, SSISlaveInfo, qdev);
- SSISlave *s = SSI_SLAVE_FROM_QDEV(dev);
+ SSISlave *s = SSI_SLAVE(dev);
+ SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
SSIBus *bus;
bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
@@ -33,18 +33,24 @@ static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
hw_error("Too many devices on SSI bus");
}
- s->info = info;
- return info->init(s);
+ return ssc->init(s);
}
-void ssi_register_slave(SSISlaveInfo *info)
+static void ssi_slave_class_init(ObjectClass *klass, void *data)
{
- assert(info->qdev.size >= sizeof(SSISlave));
- info->qdev.init = ssi_slave_init;
- info->qdev.bus_info = &ssi_bus_info;
- qdev_register(&info->qdev);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->init = ssi_slave_init;
+ dc->bus_info = &ssi_bus_info;
}
+static TypeInfo ssi_slave_info = {
+ .name = TYPE_SSI_SLAVE,
+ .parent = TYPE_DEVICE,
+ .class_init = ssi_slave_class_init,
+ .class_size = sizeof(SSISlaveClass),
+ .abstract = true,
+};
+
DeviceState *ssi_create_slave(SSIBus *bus, const char *name)
{
DeviceState *dev;
@@ -64,10 +70,19 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
{
DeviceState *dev;
SSISlave *slave;
+ SSISlaveClass *ssc;
dev = QTAILQ_FIRST(&bus->qbus.children);
if (!dev) {
return 0;
}
- slave = SSI_SLAVE_FROM_QDEV(dev);
- return slave->info->transfer(slave, val);
+ slave = SSI_SLAVE(dev);
+ ssc = SSI_SLAVE_GET_CLASS(slave);
+ return ssc->transfer(slave, val);
+}
+
+static void register_ssi_slave(void)
+{
+ type_register_static(&ssi_slave_info);
}
+
+device_init(register_ssi_slave);
diff --git a/hw/ssi.h b/hw/ssi.h
index 24610a80cb..06657d7c16 100644
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -15,23 +15,29 @@
typedef struct SSISlave SSISlave;
+#define TYPE_SSI_SLAVE "ssi-slave"
+#define SSI_SLAVE(obj) \
+ OBJECT_CHECK(SSISlave, (obj), TYPE_SSI_SLAVE)
+#define SSI_SLAVE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SSISlaveClass, (klass), TYPE_SSI_SLAVE)
+#define SSI_SLAVE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SSISlaveClass, (obj), TYPE_SSI_SLAVE)
+
/* Slave devices. */
-typedef struct {
- DeviceInfo qdev;
+typedef struct SSISlaveClass {
+ DeviceClass parent_class;
+
int (*init)(SSISlave *dev);
uint32_t (*transfer)(SSISlave *dev, uint32_t val);
-} SSISlaveInfo;
+} SSISlaveClass;
struct SSISlave {
DeviceState qdev;
- SSISlaveInfo *info;
};
#define SSI_SLAVE_FROM_QDEV(dev) DO_UPCAST(SSISlave, qdev, dev)
#define FROM_SSI_SLAVE(type, dev) DO_UPCAST(type, ssidev, dev)
-void ssi_register_slave(SSISlaveInfo *info);
-
DeviceState *ssi_create_slave(SSIBus *bus, const char *name);
/* Master interface. */
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 7a73074982..31a65cfb77 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1394,22 +1394,69 @@ static void stellaris_machine_init(void)
machine_init(stellaris_machine_init);
-static SSISlaveInfo stellaris_ssi_bus_info = {
- .qdev.name = "evb6965-ssi",
- .qdev.size = sizeof(stellaris_ssi_bus_state),
- .init = stellaris_ssi_bus_init,
- .transfer = stellaris_ssi_bus_transfer
+static void stellaris_ssi_bus_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = stellaris_ssi_bus_init;
+ k->transfer = stellaris_ssi_bus_transfer;
+}
+
+static TypeInfo stellaris_ssi_bus_info = {
+ .name = "evb6965-ssi",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(stellaris_ssi_bus_state),
+ .class_init = stellaris_ssi_bus_class_init,
+};
+
+static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_i2c_init;
+}
+
+static TypeInfo stellaris_i2c_info = {
+ .name = "stellaris-i2c",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(stellaris_i2c_state),
+ .class_init = stellaris_i2c_class_init,
+};
+
+static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_gptm_init;
+}
+
+static TypeInfo stellaris_gptm_info = {
+ .name = "stellaris-gptm",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(gptm_state),
+ .class_init = stellaris_gptm_class_init,
+};
+
+static void stellaris_adc_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = stellaris_adc_init;
+}
+
+static TypeInfo stellaris_adc_info = {
+ .name = "stellaris-adc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(stellaris_adc_state),
+ .class_init = stellaris_adc_class_init,
};
static void stellaris_register_devices(void)
{
- sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state),
- stellaris_i2c_init);
- sysbus_register_dev("stellaris-gptm", sizeof(gptm_state),
- stellaris_gptm_init);
- sysbus_register_dev("stellaris-adc", sizeof(stellaris_adc_state),
- stellaris_adc_init);
- ssi_register_slave(&stellaris_ssi_bus_info);
+ type_register_static(&stellaris_i2c_info);
+ type_register_static(&stellaris_gptm_info);
+ type_register_static(&stellaris_adc_info);
+ type_register_static(&stellaris_ssi_bus_info);
}
device_init(stellaris_register_devices)
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 866c9a2381..9b1be8dadc 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -411,7 +411,7 @@ static int stellaris_enet_init(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
stellaris_enet_reset(s);
@@ -420,19 +420,30 @@ static int stellaris_enet_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo stellaris_enet_info = {
- .init = stellaris_enet_init,
- .qdev.name = "stellaris_enet",
- .qdev.size = sizeof(stellaris_enet_state),
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(stellaris_enet_state, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property stellaris_enet_properties[] = {
+ DEFINE_NIC_PROPERTIES(stellaris_enet_state, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void stellaris_enet_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = stellaris_enet_init;
+ dc->props = stellaris_enet_properties;
+}
+
+static TypeInfo stellaris_enet_info = {
+ .name = "stellaris_enet",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(stellaris_enet_state),
+ .class_init = stellaris_enet_class_init,
};
static void stellaris_enet_register_devices(void)
{
- sysbus_register_withprop(&stellaris_enet_info);
+ type_register_static(&stellaris_enet_info);
}
device_init(stellaris_enet_register_devices)
diff --git a/hw/strongarm.c b/hw/strongarm.c
index fe63fd7ab7..8d2e7eb6fe 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -201,12 +201,21 @@ static VMStateDescription vmstate_strongarm_pic_regs = {
},
};
-static SysBusDeviceInfo strongarm_pic_info = {
- .init = strongarm_pic_initfn,
- .qdev.name = "strongarm_pic",
- .qdev.desc = "StrongARM PIC",
- .qdev.size = sizeof(StrongARMPICState),
- .qdev.vmsd = &vmstate_strongarm_pic_regs,
+static void strongarm_pic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_pic_initfn;
+ dc->desc = "StrongARM PIC";
+ dc->vmsd = &vmstate_strongarm_pic_regs;
+}
+
+static TypeInfo strongarm_pic_info = {
+ .name = "strongarm_pic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMPICState),
+ .class_init = strongarm_pic_class_init,
};
/* Real-Time Clock */
@@ -413,12 +422,21 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = {
},
};
-static SysBusDeviceInfo strongarm_rtc_sysbus_info = {
- .init = strongarm_rtc_init,
- .qdev.name = "strongarm-rtc",
- .qdev.desc = "StrongARM RTC Controller",
- .qdev.size = sizeof(StrongARMRTCState),
- .qdev.vmsd = &vmstate_strongarm_rtc_regs,
+static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_rtc_init;
+ dc->desc = "StrongARM RTC Controller";
+ dc->vmsd = &vmstate_strongarm_rtc_regs;
+}
+
+static TypeInfo strongarm_rtc_sysbus_info = {
+ .name = "strongarm-rtc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMRTCState),
+ .class_init = strongarm_rtc_sysbus_class_init,
};
/* GPIO */
@@ -646,11 +664,20 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = {
},
};
-static SysBusDeviceInfo strongarm_gpio_info = {
- .init = strongarm_gpio_initfn,
- .qdev.name = "strongarm-gpio",
- .qdev.desc = "StrongARM GPIO controller",
- .qdev.size = sizeof(StrongARMGPIOInfo),
+static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_gpio_initfn;
+ dc->desc = "StrongARM GPIO controller";
+}
+
+static TypeInfo strongarm_gpio_info = {
+ .name = "strongarm-gpio",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMGPIOInfo),
+ .class_init = strongarm_gpio_class_init,
};
/* Peripheral Pin Controller */
@@ -803,11 +830,20 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = {
},
};
-static SysBusDeviceInfo strongarm_ppc_info = {
- .init = strongarm_ppc_init,
- .qdev.name = "strongarm-ppc",
- .qdev.desc = "StrongARM PPC controller",
- .qdev.size = sizeof(StrongARMPPCInfo),
+static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_ppc_init;
+ dc->desc = "StrongARM PPC controller";
+}
+
+static TypeInfo strongarm_ppc_info = {
+ .name = "strongarm-ppc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMPPCInfo),
+ .class_init = strongarm_ppc_class_init,
};
/* UART Ports */
@@ -1245,17 +1281,28 @@ static const VMStateDescription vmstate_strongarm_uart_regs = {
},
};
-static SysBusDeviceInfo strongarm_uart_info = {
- .init = strongarm_uart_init,
- .qdev.name = "strongarm-uart",
- .qdev.desc = "StrongARM UART controller",
- .qdev.size = sizeof(StrongARMUARTState),
- .qdev.reset = strongarm_uart_reset,
- .qdev.vmsd = &vmstate_strongarm_uart_regs,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property strongarm_uart_properties[] = {
+ DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void strongarm_uart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_uart_init;
+ dc->desc = "StrongARM UART controller";
+ dc->reset = strongarm_uart_reset;
+ dc->vmsd = &vmstate_strongarm_uart_regs;
+ dc->props = strongarm_uart_properties;
+}
+
+static TypeInfo strongarm_uart_info = {
+ .name = "strongarm-uart",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMUARTState),
+ .class_init = strongarm_uart_class_init,
};
/* Synchronous Serial Ports */
@@ -1479,13 +1526,22 @@ static const VMStateDescription vmstate_strongarm_ssp_regs = {
},
};
-static SysBusDeviceInfo strongarm_ssp_info = {
- .init = strongarm_ssp_init,
- .qdev.name = "strongarm-ssp",
- .qdev.desc = "StrongARM SSP controller",
- .qdev.size = sizeof(StrongARMSSPState),
- .qdev.reset = strongarm_ssp_reset,
- .qdev.vmsd = &vmstate_strongarm_ssp_regs,
+static void strongarm_ssp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = strongarm_ssp_init;
+ dc->desc = "StrongARM SSP controller";
+ dc->reset = strongarm_ssp_reset;
+ dc->vmsd = &vmstate_strongarm_ssp_regs;
+}
+
+static TypeInfo strongarm_ssp_info = {
+ .name = "strongarm-ssp",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(StrongARMSSPState),
+ .class_init = strongarm_ssp_class_init,
};
/* Main CPU functions */
@@ -1555,11 +1611,11 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
static void strongarm_register_devices(void)
{
- sysbus_register_withprop(&strongarm_pic_info);
- sysbus_register_withprop(&strongarm_rtc_sysbus_info);
- sysbus_register_withprop(&strongarm_gpio_info);
- sysbus_register_withprop(&strongarm_ppc_info);
- sysbus_register_withprop(&strongarm_uart_info);
- sysbus_register_withprop(&strongarm_ssp_info);
+ type_register_static(&strongarm_pic_info);
+ type_register_static(&strongarm_rtc_sysbus_info);
+ type_register_static(&strongarm_gpio_info);
+ type_register_static(&strongarm_ppc_info);
+ type_register_static(&strongarm_uart_info);
+ type_register_static(&strongarm_ssp_info);
}
device_init(strongarm_register_devices)
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index e15b1674ce..081d6cc8bd 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -206,17 +206,26 @@ static int sun4c_intctl_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo sun4c_intctl_info = {
- .init = sun4c_intctl_init1,
- .qdev.name = "sun4c_intctl",
- .qdev.size = sizeof(Sun4c_INTCTLState),
- .qdev.vmsd = &vmstate_sun4c_intctl,
- .qdev.reset = sun4c_intctl_reset,
+static void sun4c_intctl_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = sun4c_intctl_init1;
+ dc->reset = sun4c_intctl_reset;
+ dc->vmsd = &vmstate_sun4c_intctl;
+}
+
+static TypeInfo sun4c_intctl_info = {
+ .name = "sun4c_intctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(Sun4c_INTCTLState),
+ .class_init = sun4c_intctl_class_init,
};
static void sun4c_intctl_register_devices(void)
{
- sysbus_register_withprop(&sun4c_intctl_info);
+ type_register_static(&sun4c_intctl_info);
}
device_init(sun4c_intctl_register_devices)
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 941cc98b9b..b79d14c35a 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -609,15 +609,23 @@ static int idreg_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo idreg_info = {
- .init = idreg_init1,
- .qdev.name = "macio_idreg",
- .qdev.size = sizeof(IDRegState),
+static void idreg_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = idreg_init1;
+}
+
+static TypeInfo idreg_info = {
+ .name = "macio_idreg",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IDRegState),
+ .class_init = idreg_class_init,
};
static void idreg_register_devices(void)
{
- sysbus_register_withprop(&idreg_info);
+ type_register_static(&idreg_info);
}
device_init(idreg_register_devices);
@@ -650,15 +658,23 @@ static int afx_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo afx_info = {
- .init = afx_init1,
- .qdev.name = "tcx_afx",
- .qdev.size = sizeof(AFXState),
+static void afx_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = afx_init1;
+}
+
+static TypeInfo afx_info = {
+ .name = "tcx_afx",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AFXState),
+ .class_init = afx_class_init,
};
static void afx_register_devices(void)
{
- sysbus_register_withprop(&afx_info);
+ type_register_static(&afx_info);
}
device_init(afx_register_devices);
@@ -720,18 +736,29 @@ static int prom_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo prom_info = {
- .init = prom_init1,
- .qdev.name = "openprom",
- .qdev.size = sizeof(PROMState),
- .qdev.props = (Property[]) {
- {/* end of property list */}
- }
+static Property prom_properties[] = {
+ {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = prom_init1;
+ dc->props = prom_properties;
+}
+
+static TypeInfo prom_info = {
+ .name = "openprom",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PROMState),
+ .class_init = prom_class_init,
};
static void prom_register_devices(void)
{
- sysbus_register_withprop(&prom_info);
+ type_register_static(&prom_info);
}
device_init(prom_register_devices);
@@ -779,19 +806,30 @@ static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size,
sysbus_mmio_map(s, 0, addr);
}
-static SysBusDeviceInfo ram_info = {
- .init = ram_init1,
- .qdev.name = "memory",
- .qdev.size = sizeof(RamDevice),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT64("size", RamDevice, size, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ram_properties[] = {
+ DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = ram_init1;
+ dc->props = ram_properties;
+}
+
+static TypeInfo ram_info = {
+ .name = "memory",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RamDevice),
+ .class_init = ram_class_init,
};
static void ram_register_devices(void)
{
- sysbus_register_withprop(&ram_info);
+ type_register_static(&ram_info);
}
device_init(ram_register_devices);
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index ef7627c467..727532cb09 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -357,21 +357,32 @@ static int iommu_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo iommu_info = {
- .init = iommu_init1,
- .qdev.name = "iommu",
- .qdev.size = sizeof(IOMMUState),
- .qdev.vmsd = &vmstate_iommu,
- .qdev.reset = iommu_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("version", IOMMUState, version, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property iommu_properties[] = {
+ DEFINE_PROP_HEX32("version", IOMMUState, version, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void iommu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = iommu_init1;
+ dc->reset = iommu_reset;
+ dc->vmsd = &vmstate_iommu;
+ dc->props = iommu_properties;
+}
+
+static TypeInfo iommu_info = {
+ .name = "iommu",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IOMMUState),
+ .class_init = iommu_class_init,
};
static void iommu_register_devices(void)
{
- sysbus_register_withprop(&iommu_info);
+ type_register_static(&iommu_info);
}
device_init(iommu_register_devices)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 2dc3d0439f..79bbd495eb 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -562,19 +562,27 @@ pci_ebus_init1(PCIDevice *pci_dev)
return 0;
}
-static PCIDeviceInfo ebus_info = {
- .qdev.name = "ebus",
- .qdev.size = sizeof(EbusState),
- .init = pci_ebus_init1,
- .vendor_id = PCI_VENDOR_ID_SUN,
- .device_id = PCI_DEVICE_ID_SUN_EBUS,
- .revision = 0x01,
- .class_id = PCI_CLASS_BRIDGE_OTHER,
+static void ebus_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_ebus_init1;
+ k->vendor_id = PCI_VENDOR_ID_SUN;
+ k->device_id = PCI_DEVICE_ID_SUN_EBUS;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static TypeInfo ebus_info = {
+ .name = "ebus",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(EbusState),
+ .class_init = ebus_class_init,
};
static void pci_ebus_register(void)
{
- pci_qdev_register(&ebus_info);
+ type_register_static(&ebus_info);
}
device_init(pci_ebus_register);
@@ -636,18 +644,29 @@ static int prom_init1(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo prom_info = {
- .init = prom_init1,
- .qdev.name = "openprom",
- .qdev.size = sizeof(PROMState),
- .qdev.props = (Property[]) {
- {/* end of property list */}
- }
+static Property prom_properties[] = {
+ {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = prom_init1;
+ dc->props = prom_properties;
+}
+
+static TypeInfo prom_info = {
+ .name = "openprom",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PROMState),
+ .class_init = prom_class_init,
};
static void prom_register_devices(void)
{
- sysbus_register_withprop(&prom_info);
+ type_register_static(&prom_info);
}
device_init(prom_register_devices);
@@ -688,19 +707,30 @@ static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size)
sysbus_mmio_map(s, 0, addr);
}
-static SysBusDeviceInfo ram_info = {
- .init = ram_init1,
- .qdev.name = "memory",
- .qdev.size = sizeof(RamDevice),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT64("size", RamDevice, size, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ram_properties[] = {
+ DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = ram_init1;
+ dc->props = ram_properties;
+}
+
+static TypeInfo ram_info = {
+ .name = "memory",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RamDevice),
+ .class_init = ram_class_init,
};
static void ram_register_devices(void)
{
- sysbus_register_withprop(&ram_info);
+ type_register_static(&ram_info);
}
device_init(ram_register_devices);
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 2e06fe823c..282060abb6 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -105,31 +105,12 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
}
}
-static int sysbus_device_init(DeviceState *dev, DeviceInfo *base)
+static int sysbus_device_init(DeviceState *dev)
{
- SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev);
+ SysBusDevice *sd = SYS_BUS_DEVICE(dev);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
- return info->init(sysbus_from_qdev(dev));
-}
-
-void sysbus_register_withprop(SysBusDeviceInfo *info)
-{
- info->qdev.init = sysbus_device_init;
- info->qdev.bus_info = &system_bus_info;
-
- assert(info->qdev.size >= sizeof(SysBusDevice));
- qdev_register(&info->qdev);
-}
-
-void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
-{
- SysBusDeviceInfo *info;
-
- info = g_malloc0(sizeof(*info));
- info->qdev.name = g_strdup(name);
- info->qdev.size = size;
- info->init = init;
- sysbus_register_withprop(info);
+ return sbc->init(sd);
}
DeviceState *sysbus_create_varargs(const char *name,
@@ -258,3 +239,26 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev)
{
return get_system_memory();
}
+
+static void sysbus_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = sysbus_device_init;
+ k->bus_info = &system_bus_info;
+}
+
+static TypeInfo sysbus_device_type_info = {
+ .name = TYPE_SYS_BUS_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .abstract = true,
+ .class_size = sizeof(SysBusDeviceClass),
+ .class_init = sysbus_device_class_init,
+};
+
+static void sysbus_register(void)
+{
+ type_register_static(&sysbus_device_type_info);
+}
+
+device_init(sysbus_register);
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 7b8ca236bf..22555cd443 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -12,6 +12,20 @@
typedef struct SysBusDevice SysBusDevice;
+#define TYPE_SYS_BUS_DEVICE "sys-bus-device"
+#define SYS_BUS_DEVICE(obj) \
+ OBJECT_CHECK(SysBusDevice, (obj), TYPE_SYS_BUS_DEVICE)
+#define SYS_BUS_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SysBusDeviceClass, (klass), TYPE_SYS_BUS_DEVICE)
+#define SYS_BUS_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SysBusDeviceClass, (obj), TYPE_SYS_BUS_DEVICE)
+
+typedef struct SysBusDeviceClass {
+ DeviceClass parent_class;
+
+ int (*init)(SysBusDevice *dev);
+} SysBusDeviceClass;
+
struct SysBusDevice {
DeviceState qdev;
int num_irq;
@@ -26,19 +40,10 @@ struct SysBusDevice {
pio_addr_t pio[QDEV_MAX_PIO];
};
-typedef int (*sysbus_initfn)(SysBusDevice *dev);
-
/* Macros to compensate for lack of type inheritance in C. */
#define sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev)
-typedef struct {
- DeviceInfo qdev;
- sysbus_initfn init;
-} SysBusDeviceInfo;
-
-void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
-void sysbus_register_withprop(SysBusDeviceInfo *info);
void *sysbus_new(void);
void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
diff --git a/hw/tcx.c b/hw/tcx.c
index 75a28f2ee5..ceb94c74a7 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -61,21 +61,13 @@ static void tcx24_screen_dump(void *opaque, const char *filename);
static void tcx_set_dirty(TCXState *s)
{
- unsigned int i;
-
- for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
- memory_region_set_dirty(&s->vram_mem, i);
- }
+ memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
}
static void tcx24_set_dirty(TCXState *s)
{
- unsigned int i;
-
- for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
- memory_region_set_dirty(&s->vram_mem, s->vram24_offset + i);
- memory_region_set_dirty(&s->vram_mem, s->cplane_offset + i);
- }
+ memory_region_set_dirty(&s->vram_mem, s->vram24_offset, MAXX * MAXY * 4);
+ memory_region_set_dirty(&s->vram_mem, s->cplane_offset, MAXX * MAXY * 4);
}
static void update_palette_entries(TCXState *s, int start, int end)
@@ -186,15 +178,13 @@ static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
ram_addr_t cpage)
{
int ret;
- unsigned int off;
-
- ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
- for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
- ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
- DIRTY_MEMORY_VGA);
- ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
- DIRTY_MEMORY_VGA);
- }
+
+ ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
+ DIRTY_MEMORY_VGA);
+ ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
+ DIRTY_MEMORY_VGA);
+ ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
+ DIRTY_MEMORY_VGA);
return ret;
}
@@ -253,7 +243,8 @@ static void tcx_update_display(void *opaque)
}
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
- if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
+ if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
+ DIRTY_MEMORY_VGA)) {
if (y_start < 0)
y_start = y;
if (page < page_min)
@@ -646,25 +637,36 @@ 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.reset = tcx_reset,
- .qdev.vmsd = &vmstate_tcx,
- .qdev.props = (Property[]) {
- DEFINE_PROP_TADDR("addr", TCXState, addr, -1),
- DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
- DEFINE_PROP_UINT16("width", TCXState, width, -1),
- DEFINE_PROP_UINT16("height", TCXState, height, -1),
- DEFINE_PROP_UINT16("depth", TCXState, depth, -1),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property tcx_properties[] = {
+ DEFINE_PROP_TADDR("addr", TCXState, addr, -1),
+ DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
+ DEFINE_PROP_UINT16("width", TCXState, width, -1),
+ DEFINE_PROP_UINT16("height", TCXState, height, -1),
+ DEFINE_PROP_UINT16("depth", TCXState, depth, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tcx_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = tcx_init1;
+ dc->reset = tcx_reset;
+ dc->vmsd = &vmstate_tcx;
+ dc->props = tcx_properties;
+}
+
+static TypeInfo tcx_info = {
+ .name = "SUNW,tcx",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TCXState),
+ .class_init = tcx_class_init,
};
static void tcx_register_devices(void)
{
- sysbus_register_withprop(&tcx_info);
+ type_register_static(&tcx_info);
}
device_init(tcx_register_devices)
diff --git a/hw/tmp105.c b/hw/tmp105.c
index f7e6f2b909..a3bdd91d40 100644
--- a/hw/tmp105.c
+++ b/hw/tmp105.c
@@ -22,7 +22,7 @@
#include "i2c.h"
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
uint8_t len;
uint8_t buf[2];
qemu_irq pin;
@@ -65,7 +65,7 @@ static void tmp105_alarm_update(TMP105State *s)
}
/* Units are 0.001 centigrades relative to 0 C. */
-void tmp105_set(i2c_slave *i2c, int temp)
+void tmp105_set(I2CSlave *i2c, int temp)
{
TMP105State *s = (TMP105State *) i2c;
@@ -138,7 +138,7 @@ static void tmp105_write(TMP105State *s)
}
}
-static int tmp105_rx(i2c_slave *i2c)
+static int tmp105_rx(I2CSlave *i2c)
{
TMP105State *s = (TMP105State *) i2c;
@@ -148,7 +148,7 @@ static int tmp105_rx(i2c_slave *i2c)
return 0xff;
}
-static int tmp105_tx(i2c_slave *i2c, uint8_t data)
+static int tmp105_tx(I2CSlave *i2c, uint8_t data)
{
TMP105State *s = (TMP105State *) i2c;
@@ -163,7 +163,7 @@ static int tmp105_tx(i2c_slave *i2c, uint8_t data)
return 0;
}
-static void tmp105_event(i2c_slave *i2c, enum i2c_event event)
+static void tmp105_event(I2CSlave *i2c, enum i2c_event event)
{
TMP105State *s = (TMP105State *) i2c;
@@ -202,7 +202,7 @@ static const VMStateDescription vmstate_tmp105 = {
}
};
-static void tmp105_reset(i2c_slave *i2c)
+static void tmp105_reset(I2CSlave *i2c)
{
TMP105State *s = (TMP105State *) i2c;
@@ -215,7 +215,7 @@ static void tmp105_reset(i2c_slave *i2c)
tmp105_interrupt_update(s);
}
-static int tmp105_init(i2c_slave *i2c)
+static int tmp105_init(I2CSlave *i2c)
{
TMP105State *s = FROM_I2C_SLAVE(TMP105State, i2c);
@@ -226,19 +226,28 @@ static int tmp105_init(i2c_slave *i2c)
return 0;
}
-static I2CSlaveInfo tmp105_info = {
- .qdev.name = "tmp105",
- .qdev.size = sizeof(TMP105State),
- .qdev.vmsd = &vmstate_tmp105,
- .init = tmp105_init,
- .event = tmp105_event,
- .recv = tmp105_rx,
- .send = tmp105_tx
+static void tmp105_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = tmp105_init;
+ k->event = tmp105_event;
+ k->recv = tmp105_rx;
+ k->send = tmp105_tx;
+ dc->vmsd = &vmstate_tmp105;
+}
+
+static TypeInfo tmp105_info = {
+ .name = "tmp105",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(TMP105State),
+ .class_init = tmp105_class_init,
};
static void tmp105_register_devices(void)
{
- i2c_register_slave(&tmp105_info);
+ type_register_static(&tmp105_info);
}
device_init(tmp105_register_devices)
diff --git a/hw/tosa.c b/hw/tosa.c
index 0caba79c98..c0d401759e 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -133,12 +133,12 @@ static int tosa_ssp_init(SSISlave *dev)
}
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
int len;
char buf[3];
} TosaDACState;
-static int tosa_dac_send(i2c_slave *i2c, uint8_t data)
+static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
{
TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
s->buf[s->len] = data;
@@ -157,7 +157,7 @@ static int tosa_dac_send(i2c_slave *i2c, uint8_t data)
return 0;
}
-static void tosa_dac_event(i2c_slave *i2c, enum i2c_event event)
+static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event)
{
TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
s->len = 0;
@@ -180,13 +180,13 @@ static void tosa_dac_event(i2c_slave *i2c, enum i2c_event event)
}
}
-static int tosa_dac_recv(i2c_slave *s)
+static int tosa_dac_recv(I2CSlave *s)
{
printf("%s: recv not supported!!!\n", __FUNCTION__);
return -1;
}
-static int tosa_dac_init(i2c_slave *i2c)
+static int tosa_dac_init(I2CSlave *i2c)
{
/* Nothing to do. */
return 0;
@@ -259,26 +259,42 @@ static void tosapda_machine_init(void)
machine_init(tosapda_machine_init);
-static I2CSlaveInfo tosa_dac_info = {
- .qdev.name = "tosa_dac",
- .qdev.size = sizeof(TosaDACState),
- .init = tosa_dac_init,
- .event = tosa_dac_event,
- .recv = tosa_dac_recv,
- .send = tosa_dac_send
+static void tosa_dac_class_init(ObjectClass *klass, void *data)
+{
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = tosa_dac_init;
+ k->event = tosa_dac_event;
+ k->recv = tosa_dac_recv;
+ k->send = tosa_dac_send;
+}
+
+static TypeInfo tosa_dac_info = {
+ .name = "tosa_dac",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(TosaDACState),
+ .class_init = tosa_dac_class_init,
};
-static SSISlaveInfo tosa_ssp_info = {
- .qdev.name = "tosa-ssp",
- .qdev.size = sizeof(SSISlave),
- .init = tosa_ssp_init,
- .transfer = tosa_ssp_tansfer
+static void tosa_ssp_class_init(ObjectClass *klass, void *data)
+{
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = tosa_ssp_init;
+ k->transfer = tosa_ssp_tansfer;
+}
+
+static TypeInfo tosa_ssp_info = {
+ .name = "tosa-ssp",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(SSISlave),
+ .class_init = tosa_ssp_class_init,
};
static void tosa_register_devices(void)
{
- i2c_register_slave(&tosa_dac_info);
- ssi_register_slave(&tosa_ssp_info);
+ type_register_static(&tosa_dac_info);
+ type_register_static(&tosa_ssp_info);
}
device_init(tosa_register_devices)
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 276300a302..0ade670906 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -789,16 +789,25 @@ static int tusb6010_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo tusb6010_info = {
- .init = tusb6010_init,
- .qdev.name = "tusb6010",
- .qdev.size = sizeof(TUSBState),
- .qdev.reset = tusb6010_reset,
+static void tusb6010_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = tusb6010_init;
+ dc->reset = tusb6010_reset;
+}
+
+static TypeInfo tusb6010_info = {
+ .name = "tusb6010",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TUSBState),
+ .class_init = tusb6010_class_init,
};
static void tusb6010_register_device(void)
{
- sysbus_register_withprop(&tusb6010_info);
+ type_register_static(&tusb6010_info);
}
device_init(tusb6010_register_device)
diff --git a/hw/twl92230.c b/hw/twl92230.c
index a75448f06a..03fdccc8ce 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -27,7 +27,7 @@
#define VERBOSE 1
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
int firstbyte;
uint8_t reg;
@@ -126,7 +126,7 @@ static void menelaus_rtc_hz(void *opaque)
menelaus_update(s);
}
-static void menelaus_reset(i2c_slave *i2c)
+static void menelaus_reset(I2CSlave *i2c)
{
MenelausState *s = (MenelausState *) i2c;
s->reg = 0x00;
@@ -709,7 +709,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
}
}
-static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
+static void menelaus_event(I2CSlave *i2c, enum i2c_event event)
{
MenelausState *s = (MenelausState *) i2c;
@@ -717,7 +717,7 @@ static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
s->firstbyte = 1;
}
-static int menelaus_tx(i2c_slave *i2c, uint8_t data)
+static int menelaus_tx(I2CSlave *i2c, uint8_t data)
{
MenelausState *s = (MenelausState *) i2c;
/* Interpret register address byte */
@@ -730,7 +730,7 @@ static int menelaus_tx(i2c_slave *i2c, uint8_t data)
return 0;
}
-static int menelaus_rx(i2c_slave *i2c)
+static int menelaus_rx(I2CSlave *i2c)
{
MenelausState *s = (MenelausState *) i2c;
@@ -842,7 +842,7 @@ static const VMStateDescription vmstate_menelaus = {
}
};
-static int twl92230_init(i2c_slave *i2c)
+static int twl92230_init(I2CSlave *i2c)
{
MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
@@ -857,19 +857,28 @@ static int twl92230_init(i2c_slave *i2c)
return 0;
}
-static I2CSlaveInfo twl92230_info = {
- .qdev.name ="twl92230",
- .qdev.size = sizeof(MenelausState),
- .qdev.vmsd = &vmstate_menelaus,
- .init = twl92230_init,
- .event = menelaus_event,
- .recv = menelaus_rx,
- .send = menelaus_tx
+static void twl92230_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
+
+ sc->init = twl92230_init;
+ sc->event = menelaus_event;
+ sc->recv = menelaus_rx;
+ sc->send = menelaus_tx;
+ dc->vmsd = &vmstate_menelaus;
+}
+
+static TypeInfo twl92230_info = {
+ .name = "twl92230",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(MenelausState),
+ .class_init = twl92230_class_init,
};
static void twl92230_register_devices(void)
{
- i2c_register_slave(&twl92230_info);
+ type_register_static(&twl92230_info);
}
device_init(twl92230_register_devices)
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 14d99147f3..17d86aac68 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -39,7 +39,6 @@
static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
typedef struct UNINState {
- SysBusDevice busdev;
PCIHostState host_state;
MemoryRegion pci_mmio;
MemoryRegion pci_hole;
@@ -64,10 +63,6 @@ static void pci_unin_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[unin_irq_line[irq_num]], level);
}
-static void pci_unin_reset(void *opaque)
-{
-}
-
static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
{
uint32_t retval;
@@ -134,11 +129,13 @@ static const MemoryRegionOps unin_data_ops = {
static int pci_unin_main_init_device(SysBusDevice *dev)
{
+ PCIHostState *h;
UNINState *s;
/* Use values found on a real PowerMac */
/* Uninorth main bus */
- s = FROM_SYSBUS(UNINState, dev);
+ h = FROM_SYSBUS(PCIHostState, dev);
+ s = DO_UPCAST(UNINState, host_state, h);
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
&s->host_state, "pci-conf-idx", 0x1000);
@@ -147,17 +144,18 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->host_state.conf_mem);
sysbus_init_mmio(dev, &s->host_state.data_mem);
- qemu_register_reset(pci_unin_reset, &s->host_state);
return 0;
}
static int pci_u3_agp_init_device(SysBusDevice *dev)
{
+ PCIHostState *h;
UNINState *s;
/* Uninorth U3 AGP bus */
- s = FROM_SYSBUS(UNINState, dev);
+ h = FROM_SYSBUS(PCIHostState, dev);
+ s = DO_UPCAST(UNINState, host_state, h);
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
&s->host_state, "pci-conf-idx", 0x1000);
@@ -166,17 +164,17 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->host_state.conf_mem);
sysbus_init_mmio(dev, &s->host_state.data_mem);
- qemu_register_reset(pci_unin_reset, &s->host_state);
-
return 0;
}
static int pci_unin_agp_init_device(SysBusDevice *dev)
{
+ PCIHostState *h;
UNINState *s;
/* Uninorth AGP bus */
- s = FROM_SYSBUS(UNINState, dev);
+ h = FROM_SYSBUS(PCIHostState, dev);
+ s = DO_UPCAST(UNINState, host_state, h);
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
&s->host_state, "pci-conf-idx", 0x1000);
@@ -189,10 +187,12 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
static int pci_unin_internal_init_device(SysBusDevice *dev)
{
+ PCIHostState *h;
UNINState *s;
/* Uninorth internal bus */
- s = FROM_SYSBUS(UNINState, dev);
+ h = FROM_SYSBUS(PCIHostState, dev);
+ s = DO_UPCAST(UNINState, host_state, h);
memory_region_init_io(&s->host_state.conf_mem, &pci_host_conf_le_ops,
&s->host_state, "pci-conf-idx", 0x1000);
@@ -209,21 +209,23 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
{
DeviceState *dev;
SysBusDevice *s;
+ PCIHostState *h;
UNINState *d;
/* Use values found on a real PowerMac */
/* Uninorth main bus */
- dev = qdev_create(NULL, "uni-north");
+ dev = qdev_create(NULL, "uni-north-pci-pcihost");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
- d = FROM_SYSBUS(UNINState, s);
+ h = FROM_SYSBUS(PCIHostState, s);
+ d = DO_UPCAST(UNINState, host_state, h);
memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
0x80000000ULL, 0x70000000ULL);
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
- d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
+ d->host_state.bus = pci_register_bus(dev, "pci",
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
@@ -245,7 +247,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
/* Uninorth AGP bus */
pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north-agp");
- dev = qdev_create(NULL, "uni-north-agp");
+ dev = qdev_create(NULL, "uni-north-agp-pcihost");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf0800000);
@@ -254,8 +256,9 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
/* Uninorth internal bus */
#if 0
/* XXX: not needed for now */
- pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0), "uni-north-pci");
- dev = qdev_create(NULL, "uni-north-pci");
+ pci_create_simple(d->host_state.bus, PCI_DEVFN(14, 0),
+ "uni-north-internal-pci");
+ dev = qdev_create(NULL, "uni-north-internal-pci-pcihost");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf4800000);
@@ -271,14 +274,16 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
{
DeviceState *dev;
SysBusDevice *s;
+ PCIHostState *h;
UNINState *d;
/* Uninorth AGP bus */
- dev = qdev_create(NULL, "u3-agp");
+ dev = qdev_create(NULL, "u3-agp-pcihost");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
- d = FROM_SYSBUS(UNINState, s);
+ h = FROM_SYSBUS(PCIHostState, s);
+ d = DO_UPCAST(UNINState, host_state, h);
memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
@@ -286,7 +291,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
- d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
+ d->host_state.bus = pci_register_bus(dev, "pci",
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
@@ -334,60 +339,145 @@ static int unin_internal_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo unin_main_pci_host_info = {
- .qdev.name = "uni-north",
- .qdev.size = sizeof(PCIDevice),
- .init = unin_main_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_APPLE,
- .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
- .revision = 0x00,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = unin_main_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static TypeInfo unin_main_pci_host_info = {
+ .name = "uni-north-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = unin_main_pci_host_class_init,
+};
+
+static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = u3_agp_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static TypeInfo u3_agp_pci_host_info = {
+ .name = "u3-agp",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = u3_agp_pci_host_class_init,
+};
+
+static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = unin_agp_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static TypeInfo unin_agp_pci_host_info = {
+ .name = "uni-north-agp",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = unin_agp_pci_host_class_init,
+};
+
+static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = unin_internal_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static TypeInfo unin_internal_pci_host_info = {
+ .name = "uni-north-internal-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = unin_internal_pci_host_class_init,
};
-static PCIDeviceInfo u3_agp_pci_host_info = {
- .qdev.name = "u3-agp",
- .qdev.size = sizeof(PCIDevice),
- .init = u3_agp_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_APPLE,
- .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
- .revision = 0x00,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void pci_unin_main_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = pci_unin_main_init_device;
+}
+
+static TypeInfo pci_unin_main_info = {
+ .name = "uni-north-pci-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(UNINState),
+ .class_init = pci_unin_main_class_init,
+};
+
+static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = pci_u3_agp_init_device;
+}
+
+static TypeInfo pci_u3_agp_info = {
+ .name = "u3-agp-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(UNINState),
+ .class_init = pci_u3_agp_class_init,
};
-static PCIDeviceInfo unin_agp_pci_host_info = {
- .qdev.name = "uni-north-agp",
- .qdev.size = sizeof(PCIDevice),
- .init = unin_agp_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_APPLE,
- .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
- .revision = 0x00,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = pci_unin_agp_init_device;
+}
+
+static TypeInfo pci_unin_agp_info = {
+ .name = "uni-north-agp-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(UNINState),
+ .class_init = pci_unin_agp_class_init,
};
-static PCIDeviceInfo unin_internal_pci_host_info = {
- .qdev.name = "uni-north-pci",
- .qdev.size = sizeof(PCIDevice),
- .init = unin_internal_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_APPLE,
- .device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI,
- .revision = 0x00,
- .class_id = PCI_CLASS_BRIDGE_HOST,
+static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = pci_unin_internal_init_device;
+}
+
+static TypeInfo pci_unin_internal_info = {
+ .name = "uni-north-internal-pci-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(UNINState),
+ .class_init = pci_unin_internal_class_init,
};
static void unin_register_devices(void)
{
- sysbus_register_dev("uni-north", sizeof(UNINState),
- pci_unin_main_init_device);
- pci_qdev_register(&unin_main_pci_host_info);
- sysbus_register_dev("u3-agp", sizeof(UNINState),
- pci_u3_agp_init_device);
- pci_qdev_register(&u3_agp_pci_host_info);
- sysbus_register_dev("uni-north-agp", sizeof(UNINState),
- pci_unin_agp_init_device);
- pci_qdev_register(&unin_agp_pci_host_info);
- sysbus_register_dev("uni-north-pci", sizeof(UNINState),
- pci_unin_internal_init_device);
- pci_qdev_register(&unin_internal_pci_host_info);
+ type_register_static(&unin_main_pci_host_info);
+ type_register_static(&u3_agp_pci_host_info);
+ type_register_static(&unin_agp_pci_host_info);
+ type_register_static(&unin_internal_pci_host_info);
+
+ type_register_static(&pci_unin_main_info);
+ type_register_static(&pci_u3_agp_info);
+ type_register_static(&pci_unin_agp_info);
+ type_register_static(&pci_unin_internal_info);
}
device_init(unin_register_devices)
diff --git a/hw/usb-audio.c b/hw/usb-audio.c
new file mode 100644
index 0000000000..cd589b718a
--- /dev/null
+++ b/hw/usb-audio.c
@@ -0,0 +1,715 @@
+/*
+ * QEMU USB audio device
+ *
+ * written by:
+ * H. Peter Anvin <hpa@linux.intel.com>
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * lousely based on usb net device code which is:
+ *
+ * Copyright (c) 2006 Thomas Sailer
+ * Copyright (c) 2008 Andrzej Zaborowski
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "usb.h"
+#include "usb-desc.h"
+#include "hw.h"
+#include "audiodev.h"
+#include "audio/audio.h"
+
+#define USBAUDIO_VENDOR_NUM 0x46f4 /* CRC16() of "QEMU" */
+#define USBAUDIO_PRODUCT_NUM 0x0002
+
+#define DEV_CONFIG_VALUE 1 /* The one and only */
+
+/* Descriptor subtypes for AC interfaces */
+#define DST_AC_HEADER 1
+#define DST_AC_INPUT_TERMINAL 2
+#define DST_AC_OUTPUT_TERMINAL 3
+#define DST_AC_FEATURE_UNIT 6
+/* Descriptor subtypes for AS interfaces */
+#define DST_AS_GENERAL 1
+#define DST_AS_FORMAT_TYPE 2
+/* Descriptor subtypes for endpoints */
+#define DST_EP_GENERAL 1
+
+enum usb_audio_strings {
+ STRING_NULL,
+ STRING_MANUFACTURER,
+ STRING_PRODUCT,
+ STRING_SERIALNUMBER,
+ STRING_CONFIG,
+ STRING_USBAUDIO_CONTROL,
+ STRING_INPUT_TERMINAL,
+ STRING_FEATURE_UNIT,
+ STRING_OUTPUT_TERMINAL,
+ STRING_NULL_STREAM,
+ STRING_REAL_STREAM,
+};
+
+static const USBDescStrings usb_audio_stringtable = {
+ [STRING_MANUFACTURER] = "QEMU",
+ [STRING_PRODUCT] = "QEMU USB Audio",
+ [STRING_SERIALNUMBER] = "1",
+ [STRING_CONFIG] = "Audio Configuration",
+ [STRING_USBAUDIO_CONTROL] = "Audio Device",
+ [STRING_INPUT_TERMINAL] = "Audio Output Pipe",
+ [STRING_FEATURE_UNIT] = "Audio Output Volume Control",
+ [STRING_OUTPUT_TERMINAL] = "Audio Output Terminal",
+ [STRING_NULL_STREAM] = "Audio Output - Disabled",
+ [STRING_REAL_STREAM] = "Audio Output - 48 kHz Stereo",
+};
+
+#define U16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
+#define U24(x) U16(x), (((x) >> 16) & 0xff)
+#define U32(x) U24(x), (((x) >> 24) & 0xff)
+
+/*
+ * A Basic Audio Device uses these specific values
+ */
+#define USBAUDIO_PACKET_SIZE 192
+#define USBAUDIO_SAMPLE_RATE 48000
+#define USBAUDIO_PACKET_INTERVAL 1
+
+static const USBDescIface desc_iface[] = {
+ {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL,
+ .bInterfaceProtocol = 0x04,
+ .iInterface = STRING_USBAUDIO_CONTROL,
+ .ndesc = 4,
+ .descs = (USBDescOther[]) {
+ {
+ /* Headphone Class-Specific AC Interface Header Descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AC_HEADER, /* u8 bDescriptorSubtype */
+ U16(0x0100), /* u16 bcdADC */
+ U16(0x2b), /* u16 wTotalLength */
+ 0x01, /* u8 bInCollection */
+ 0x01, /* u8 baInterfaceNr */
+ }
+ },{
+ /* Generic Stereo Input Terminal ID1 Descriptor */
+ .data = (uint8_t[]) {
+ 0x0c, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AC_INPUT_TERMINAL, /* u8 bDescriptorSubtype */
+ 0x01, /* u8 bTerminalID */
+ U16(0x0101), /* u16 wTerminalType */
+ 0x00, /* u8 bAssocTerminal */
+ 0x02, /* u16 bNrChannels */
+ U16(0x0003), /* u16 wChannelConfig */
+ 0x00, /* u8 iChannelNames */
+ STRING_INPUT_TERMINAL, /* u8 iTerminal */
+ }
+ },{
+ /* Generic Stereo Feature Unit ID2 Descriptor */
+ .data = (uint8_t[]) {
+ 0x0d, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AC_FEATURE_UNIT, /* u8 bDescriptorSubtype */
+ 0x02, /* u8 bUnitID */
+ 0x01, /* u8 bSourceID */
+ 0x02, /* u8 bControlSize */
+ U16(0x0001), /* u16 bmaControls(0) */
+ U16(0x0002), /* u16 bmaControls(1) */
+ U16(0x0002), /* u16 bmaControls(2) */
+ STRING_FEATURE_UNIT, /* u8 iFeature */
+ }
+ },{
+ /* Headphone Ouptut Terminal ID3 Descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AC_OUTPUT_TERMINAL, /* u8 bDescriptorSubtype */
+ 0x03, /* u8 bUnitID */
+ U16(0x0301), /* u16 wTerminalType (SPK) */
+ 0x00, /* u8 bAssocTerminal */
+ 0x02, /* u8 bSourceID */
+ STRING_OUTPUT_TERMINAL, /* u8 iTerminal */
+ }
+ }
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_STREAMING,
+ .iInterface = STRING_NULL_STREAM,
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_STREAMING,
+ .iInterface = STRING_REAL_STREAM,
+ .ndesc = 2,
+ .descs = (USBDescOther[]) {
+ {
+ /* Headphone Class-specific AS General Interface Descriptor */
+ .data = (uint8_t[]) {
+ 0x07, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AS_GENERAL, /* u8 bDescriptorSubtype */
+ 0x01, /* u8 bTerminalLink */
+ 0x00, /* u8 bDelay */
+ 0x01, 0x00, /* u16 wFormatTag */
+ }
+ },{
+ /* Headphone Type I Format Type Descriptor */
+ .data = (uint8_t[]) {
+ 0x0b, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ DST_AS_FORMAT_TYPE, /* u8 bDescriptorSubtype */
+ 0x01, /* u8 bFormatType */
+ 0x02, /* u8 bNrChannels */
+ 0x02, /* u8 bSubFrameSize */
+ 0x10, /* u8 bBitResolution */
+ 0x01, /* u8 bSamFreqType */
+ U24(USBAUDIO_SAMPLE_RATE), /* u24 tSamFreq */
+ }
+ }
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | 0x01,
+ .bmAttributes = 0x0d,
+ .wMaxPacketSize = USBAUDIO_PACKET_SIZE,
+ .bInterval = 1,
+ .is_audio = 1,
+ /* Stereo Headphone Class-specific
+ AS Audio Data Endpoint Descriptor */
+ .extra = (uint8_t[]) {
+ 0x07, /* u8 bLength */
+ USB_DT_CS_ENDPOINT, /* u8 bDescriptorType */
+ DST_EP_GENERAL, /* u8 bDescriptorSubtype */
+ 0x00, /* u8 bmAttributes */
+ 0x00, /* u8 bLockDelayUnits */
+ U16(0x0000), /* u16 wLockDelay */
+ },
+ },
+ }
+ }
+};
+
+static const USBDescDevice desc_device = {
+ .bcdUSB = 0x0200,
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 2,
+ .bConfigurationValue = DEV_CONFIG_VALUE,
+ .iConfiguration = STRING_CONFIG,
+ .bmAttributes = 0xc0,
+ .bMaxPower = 0x32,
+ .nif = ARRAY_SIZE(desc_iface),
+ .ifs = desc_iface,
+ },
+ },
+};
+
+static const USBDesc desc_audio = {
+ .id = {
+ .idVendor = USBAUDIO_VENDOR_NUM,
+ .idProduct = USBAUDIO_PRODUCT_NUM,
+ .bcdDevice = 0,
+ .iManufacturer = STRING_MANUFACTURER,
+ .iProduct = STRING_PRODUCT,
+ .iSerialNumber = STRING_SERIALNUMBER,
+ },
+ .full = &desc_device,
+ .str = usb_audio_stringtable,
+};
+
+/*
+ * A USB audio device supports an arbitrary number of alternate
+ * interface settings for each interface. Each corresponds to a block
+ * diagram of parameterized blocks. This can thus refer to things like
+ * number of channels, data rates, or in fact completely different
+ * block diagrams. Alternative setting 0 is always the null block diagram,
+ * which is used by a disabled device.
+ */
+enum usb_audio_altset {
+ ALTSET_OFF = 0x00, /* No endpoint */
+ ALTSET_ON = 0x01, /* Single endpoint */
+};
+
+/*
+ * Class-specific control requests
+ */
+#define CR_SET_CUR 0x01
+#define CR_GET_CUR 0x81
+#define CR_SET_MIN 0x02
+#define CR_GET_MIN 0x82
+#define CR_SET_MAX 0x03
+#define CR_GET_MAX 0x83
+#define CR_SET_RES 0x04
+#define CR_GET_RES 0x84
+#define CR_SET_MEM 0x05
+#define CR_GET_MEM 0x85
+#define CR_GET_STAT 0xff
+
+/*
+ * Feature Unit Control Selectors
+ */
+#define MUTE_CONTROL 0x01
+#define VOLUME_CONTROL 0x02
+#define BASS_CONTROL 0x03
+#define MID_CONTROL 0x04
+#define TREBLE_CONTROL 0x05
+#define GRAPHIC_EQUALIZER_CONTROL 0x06
+#define AUTOMATIC_GAIN_CONTROL 0x07
+#define DELAY_CONTROL 0x08
+#define BASS_BOOST_CONTROL 0x09
+#define LOUDNESS_CONTROL 0x0a
+
+/*
+ * buffering
+ */
+
+struct streambuf {
+ uint8_t *data;
+ uint32_t size;
+ uint32_t prod;
+ uint32_t cons;
+};
+
+static void streambuf_init(struct streambuf *buf, uint32_t size)
+{
+ g_free(buf->data);
+ buf->size = size - (size % USBAUDIO_PACKET_SIZE);
+ buf->data = g_malloc(buf->size);
+ buf->prod = 0;
+ buf->cons = 0;
+}
+
+static void streambuf_fini(struct streambuf *buf)
+{
+ g_free(buf->data);
+ buf->data = NULL;
+}
+
+static int streambuf_put(struct streambuf *buf, USBPacket *p)
+{
+ uint32_t free = buf->size - (buf->prod - buf->cons);
+
+ if (!free) {
+ return 0;
+ }
+ assert(free >= USBAUDIO_PACKET_SIZE);
+ usb_packet_copy(p, buf->data + (buf->prod % buf->size),
+ USBAUDIO_PACKET_SIZE);
+ buf->prod += USBAUDIO_PACKET_SIZE;
+ return USBAUDIO_PACKET_SIZE;
+}
+
+static uint8_t *streambuf_get(struct streambuf *buf)
+{
+ uint32_t used = buf->prod - buf->cons;
+ uint8_t *data;
+
+ if (!used) {
+ return NULL;
+ }
+ assert(used >= USBAUDIO_PACKET_SIZE);
+ data = buf->data + (buf->cons % buf->size);
+ buf->cons += USBAUDIO_PACKET_SIZE;
+ return data;
+}
+
+typedef struct USBAudioState {
+ /* qemu interfaces */
+ USBDevice dev;
+ QEMUSoundCard card;
+
+ /* state */
+ struct {
+ enum usb_audio_altset altset;
+ struct audsettings as;
+ SWVoiceOut *voice;
+ bool mute;
+ uint8_t vol[2];
+ struct streambuf buf;
+ } out;
+
+ /* properties */
+ uint32_t debug;
+ uint32_t buffer;
+} USBAudioState;
+
+static void output_callback(void *opaque, int avail)
+{
+ USBAudioState *s = opaque;
+ uint8_t *data;
+
+ for (;;) {
+ if (avail < USBAUDIO_PACKET_SIZE) {
+ return;
+ }
+ data = streambuf_get(&s->out.buf);
+ if (NULL == data) {
+ return;
+ }
+ AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE);
+ avail -= USBAUDIO_PACKET_SIZE;
+ }
+}
+
+static int usb_audio_set_output_altset(USBAudioState *s, int altset)
+{
+ switch (altset) {
+ case ALTSET_OFF:
+ streambuf_init(&s->out.buf, s->buffer);
+ AUD_set_active_out(s->out.voice, false);
+ break;
+ case ALTSET_ON:
+ AUD_set_active_out(s->out.voice, true);
+ break;
+ default:
+ return -1;
+ }
+
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: set interface %d\n", altset);
+ }
+ s->out.altset = altset;
+ return 0;
+}
+
+/*
+ * Note: we arbitrarily map the volume control range onto -inf..+8 dB
+ */
+#define ATTRIB_ID(cs, attrib, idif) \
+ (((cs) << 24) | ((attrib) << 16) | (idif))
+
+static int usb_audio_get_control(USBAudioState *s, uint8_t attrib,
+ uint16_t cscn, uint16_t idif,
+ int length, uint8_t *data)
+{
+ uint8_t cs = cscn >> 8;
+ uint8_t cn = cscn - 1; /* -1 for the non-present master control */
+ uint32_t aid = ATTRIB_ID(cs, attrib, idif);
+ int ret = USB_RET_STALL;
+
+ switch (aid) {
+ case ATTRIB_ID(MUTE_CONTROL, CR_GET_CUR, 0x0200):
+ data[0] = s->out.mute;
+ ret = 1;
+ break;
+ case ATTRIB_ID(VOLUME_CONTROL, CR_GET_CUR, 0x0200):
+ if (cn < 2) {
+ uint16_t vol = (s->out.vol[cn] * 0x8800 + 127) / 255 + 0x8000;
+ data[0] = vol;
+ data[1] = vol >> 8;
+ ret = 2;
+ }
+ break;
+ case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MIN, 0x0200):
+ if (cn < 2) {
+ data[0] = 0x01;
+ data[1] = 0x80;
+ ret = 2;
+ }
+ break;
+ case ATTRIB_ID(VOLUME_CONTROL, CR_GET_MAX, 0x0200):
+ if (cn < 2) {
+ data[0] = 0x00;
+ data[1] = 0x08;
+ ret = 2;
+ }
+ break;
+ case ATTRIB_ID(VOLUME_CONTROL, CR_GET_RES, 0x0200):
+ if (cn < 2) {
+ data[0] = 0x88;
+ data[1] = 0x00;
+ ret = 2;
+ }
+ break;
+ }
+
+ return ret;
+}
+static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
+ uint16_t cscn, uint16_t idif,
+ int length, uint8_t *data)
+{
+ uint8_t cs = cscn >> 8;
+ uint8_t cn = cscn - 1; /* -1 for the non-present master control */
+ uint32_t aid = ATTRIB_ID(cs, attrib, idif);
+ int ret = USB_RET_STALL;
+ bool set_vol = false;
+
+ switch (aid) {
+ case ATTRIB_ID(MUTE_CONTROL, CR_SET_CUR, 0x0200):
+ s->out.mute = data[0] & 1;
+ set_vol = true;
+ ret = 0;
+ break;
+ case ATTRIB_ID(VOLUME_CONTROL, CR_SET_CUR, 0x0200):
+ if (cn < 2) {
+ uint16_t vol = data[0] + (data[1] << 8);
+
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: vol %04x\n", (uint16_t)vol);
+ }
+
+ vol -= 0x8000;
+ vol = (vol * 255 + 0x4400) / 0x8800;
+ if (vol > 255) {
+ vol = 255;
+ }
+
+ s->out.vol[cn] = vol;
+ set_vol = true;
+ ret = 0;
+ }
+ break;
+ }
+
+ if (set_vol) {
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: mute %d, lvol %3d, rvol %3d\n",
+ s->out.mute, s->out.vol[0], s->out.vol[1]);
+ }
+ AUD_set_volume_out(s->out.voice, s->out.mute,
+ s->out.vol[0], s->out.vol[1]);
+ }
+
+ return ret;
+}
+
+static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
+ int request, int value, int index,
+ int length, uint8_t *data)
+{
+ USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+ int ret = 0;
+
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: control transaction: "
+ "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
+ request, value, index, length);
+ }
+
+ ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ switch (request) {
+ case ClassInterfaceRequest | CR_GET_CUR:
+ case ClassInterfaceRequest | CR_GET_MIN:
+ case ClassInterfaceRequest | CR_GET_MAX:
+ case ClassInterfaceRequest | CR_GET_RES:
+ ret = usb_audio_get_control(s, request & 0xff, value, index,
+ length, data);
+ if (ret < 0) {
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: fail: get control\n");
+ }
+ goto fail;
+ }
+ break;
+
+ case ClassInterfaceOutRequest | CR_SET_CUR:
+ case ClassInterfaceOutRequest | CR_SET_MIN:
+ case ClassInterfaceOutRequest | CR_SET_MAX:
+ case ClassInterfaceOutRequest | CR_SET_RES:
+ ret = usb_audio_set_control(s, request & 0xff, value, index,
+ length, data);
+ if (ret < 0) {
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: fail: set control\n");
+ }
+ goto fail;
+ }
+ break;
+
+ default:
+fail:
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: failed control transaction: "
+ "request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
+ request, value, index, length);
+ }
+ ret = USB_RET_STALL;
+ break;
+ }
+ return ret;
+}
+
+static void usb_audio_set_interface(USBDevice *dev, int iface,
+ int old, int value)
+{
+ USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+ if (iface == 1) {
+ usb_audio_set_output_altset(s, value);
+ }
+}
+
+static void usb_audio_handle_reset(USBDevice *dev)
+{
+ USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: reset\n");
+ }
+ usb_audio_set_output_altset(s, ALTSET_OFF);
+}
+
+static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
+{
+ int rc;
+
+ if (s->out.altset == ALTSET_OFF) {
+ return USB_RET_STALL;
+ }
+
+ rc = streambuf_put(&s->out.buf, p);
+ if (rc < p->iov.size && s->debug > 1) {
+ fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
+ p->iov.size - rc);
+ }
+
+ return 0;
+}
+
+static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
+{
+ USBAudioState *s = (USBAudioState *) dev;
+ int ret = 0;
+
+ switch (p->pid) {
+ case USB_TOKEN_OUT:
+ switch (p->devep) {
+ case 1:
+ ret = usb_audio_handle_dataout(s, p);
+ break;
+ default:
+ goto fail;
+ }
+ break;
+
+ default:
+fail:
+ ret = USB_RET_STALL;
+ break;
+ }
+ if (ret == USB_RET_STALL && s->debug) {
+ fprintf(stderr, "usb-audio: failed data transaction: "
+ "pid 0x%x ep 0x%x len 0x%zx\n",
+ p->pid, p->devep, p->iov.size);
+ }
+ return ret;
+}
+
+static void usb_audio_handle_destroy(USBDevice *dev)
+{
+ USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+ if (s->debug) {
+ fprintf(stderr, "usb-audio: destroy\n");
+ }
+
+ usb_audio_set_output_altset(s, ALTSET_OFF);
+ AUD_close_out(&s->card, s->out.voice);
+ AUD_remove_card(&s->card);
+
+ streambuf_fini(&s->out.buf);
+}
+
+static int usb_audio_initfn(USBDevice *dev)
+{
+ USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+
+ usb_desc_init(dev);
+ s->dev.opaque = s;
+ AUD_register_card("usb-audio", &s->card);
+
+ s->out.altset = ALTSET_OFF;
+ s->out.mute = false;
+ s->out.vol[0] = 240; /* 0 dB */
+ s->out.vol[1] = 240; /* 0 dB */
+ s->out.as.freq = USBAUDIO_SAMPLE_RATE;
+ s->out.as.nchannels = 2;
+ s->out.as.fmt = AUD_FMT_S16;
+ s->out.as.endianness = 0;
+ streambuf_init(&s->out.buf, s->buffer);
+
+ s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio",
+ s, output_callback, &s->out.as);
+ AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]);
+ AUD_set_active_out(s->out.voice, 0);
+ return 0;
+}
+
+static const VMStateDescription vmstate_usb_audio = {
+ .name = "usb-audio",
+ .unmigratable = 1,
+};
+
+static Property usb_audio_properties[] = {
+ DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0),
+ DEFINE_PROP_UINT32("buffer", USBAudioState, buffer,
+ 8 * USBAUDIO_PACKET_SIZE),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_audio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *k = USB_DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_usb_audio;
+ dc->props = usb_audio_properties;
+ k->product_desc = "QEMU USB Audio Interface";
+ k->usb_desc = &desc_audio;
+ k->init = usb_audio_initfn;
+ k->handle_packet = usb_generic_handle_packet;
+ k->handle_reset = usb_audio_handle_reset;
+ k->handle_control = usb_audio_handle_control;
+ k->handle_data = usb_audio_handle_data;
+ k->handle_destroy = usb_audio_handle_destroy;
+ k->set_interface = usb_audio_set_interface;
+}
+
+static TypeInfo usb_audio_info = {
+ .name = "usb-audio",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBAudioState),
+ .class_init = usb_audio_class_init,
+};
+
+static void usb_audio_register_devices(void)
+{
+ type_register_static(&usb_audio_info);
+ usb_legacy_register("usb-audio", "audio", NULL);
+}
+
+device_init(usb_audio_register_devices)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index f30eec1ea2..90c3b0e0eb 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -28,7 +28,6 @@ struct USBBtState {
USBDevice dev;
struct HCIInfo *hci;
- int altsetting;
int config;
#define CFIFO_LEN_MASK 255
@@ -362,7 +361,6 @@ static void usb_bt_handle_reset(USBDevice *dev)
s->outcmd.len = 0;
s->outacl.len = 0;
s->outsco.len = 0;
- s->altsetting = 0;
}
static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
@@ -402,26 +400,6 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
case EndpointOutRequest | USB_REQ_SET_FEATURE:
goto fail;
break;
- case InterfaceRequest | USB_REQ_GET_INTERFACE:
- if (value != 0 || (index & ~1) || length != 1)
- goto fail;
- if (index == 1)
- data[0] = s->altsetting;
- else
- data[0] = 0;
- ret = 1;
- break;
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- if ((index & ~1) || length != 0 ||
- (index == 1 && (value < 0 || value > 4)) ||
- (index == 0 && value != 0)) {
- printf("%s: Wrong SET_INTERFACE request (%i, %i)\n",
- __FUNCTION__, index, value);
- goto fail;
- }
- s->altsetting = value;
- ret = 0;
- break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
if (s->config)
usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
@@ -549,22 +527,31 @@ static const VMStateDescription vmstate_usb_bt = {
.unmigratable = 1,
};
-static struct USBDeviceInfo bt_info = {
- .product_desc = "QEMU BT dongle",
- .qdev.name = "usb-bt-dongle",
- .qdev.size = sizeof(struct USBBtState),
- .qdev.vmsd = &vmstate_usb_bt,
- .usb_desc = &desc_bluetooth,
- .init = usb_bt_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_bt_handle_reset,
- .handle_control = usb_bt_handle_control,
- .handle_data = usb_bt_handle_data,
- .handle_destroy = usb_bt_handle_destroy,
+static void usb_bt_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_bt_initfn;
+ uc->product_desc = "QEMU BT dongle";
+ uc->usb_desc = &desc_bluetooth;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_bt_handle_reset;
+ uc->handle_control = usb_bt_handle_control;
+ uc->handle_data = usb_bt_handle_data;
+ uc->handle_destroy = usb_bt_handle_destroy;
+ dc->vmsd = &vmstate_usb_bt;
+}
+
+static TypeInfo bt_info = {
+ .name = "usb-bt-dongle",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(struct USBBtState),
+ .class_init = usb_bt_class_initfn,
};
static void usb_bt_register_devices(void)
{
- usb_qdev_register(&bt_info);
+ type_register_static(&bt_info);
}
device_init(usb_bt_register_devices)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index bd4afa7e2b..b753834584 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -65,21 +65,112 @@ USBBus *usb_bus_find(int busnr)
return NULL;
}
-static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int usb_device_init(USBDevice *dev)
{
- USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
- USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->init) {
+ return klass->init(dev);
+ }
+ return 0;
+}
+
+static void usb_device_handle_destroy(USBDevice *dev)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_destroy) {
+ klass->handle_destroy(dev);
+ }
+}
+
+int usb_device_handle_packet(USBDevice *dev, USBPacket *p)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_packet) {
+ return klass->handle_packet(dev, p);
+ }
+ return -ENOSYS;
+}
+
+void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->cancel_packet) {
+ klass->cancel_packet(dev, p);
+ }
+}
+
+void usb_device_handle_attach(USBDevice *dev)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_attach) {
+ klass->handle_attach(dev);
+ }
+}
+
+void usb_device_handle_reset(USBDevice *dev)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_reset) {
+ klass->handle_reset(dev);
+ }
+}
+
+int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+ int value, int index, int length, uint8_t *data)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_control) {
+ return klass->handle_control(dev, p, request, value, index, length,
+ data);
+ }
+ return -ENOSYS;
+}
+
+int usb_device_handle_data(USBDevice *dev, USBPacket *p)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->handle_data) {
+ return klass->handle_data(dev, p);
+ }
+ return -ENOSYS;
+}
+
+const char *usb_device_get_product_desc(USBDevice *dev)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ return klass->product_desc;
+}
+
+const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ return klass->usb_desc;
+}
+
+void usb_device_set_interface(USBDevice *dev, int interface,
+ int alt_old, int alt_new)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->set_interface) {
+ klass->set_interface(dev, interface, alt_old, alt_new);
+ }
+}
+
+static int usb_qdev_init(DeviceState *qdev)
+{
+ USBDevice *dev = USB_DEVICE(qdev);
int rc;
- pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc);
- dev->info = info;
+ pstrcpy(dev->product_desc, sizeof(dev->product_desc),
+ usb_device_get_product_desc(dev));
dev->auto_attach = 1;
QLIST_INIT(&dev->strings);
+ usb_ep_init(dev);
rc = usb_claim_port(dev);
if (rc != 0) {
return rc;
}
- rc = dev->info->init(dev);
+ rc = usb_device_init(dev);
if (rc != 0) {
usb_release_port(dev);
return rc;
@@ -96,34 +187,36 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
static int usb_qdev_exit(DeviceState *qdev)
{
- USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBDevice *dev = USB_DEVICE(qdev);
if (dev->attached) {
usb_device_detach(dev);
}
- if (dev->info->handle_destroy) {
- dev->info->handle_destroy(dev);
- }
+ usb_device_handle_destroy(dev);
if (dev->port) {
usb_release_port(dev);
}
return 0;
}
-void usb_qdev_register(USBDeviceInfo *info)
+typedef struct LegacyUSBFactory
{
- info->qdev.bus_info = &usb_bus_info;
- info->qdev.init = usb_qdev_init;
- info->qdev.unplug = qdev_simple_unplug_cb;
- info->qdev.exit = usb_qdev_exit;
- qdev_register(&info->qdev);
-}
+ const char *name;
+ const char *usbdevice_name;
+ USBDevice *(*usbdevice_init)(const char *params);
+} LegacyUSBFactory;
-void usb_qdev_register_many(USBDeviceInfo *info)
+static GSList *legacy_usb_factory;
+
+void usb_legacy_register(const char *typename, const char *usbdevice_name,
+ USBDevice *(*usbdevice_init)(const char *params))
{
- while (info->qdev.name) {
- usb_qdev_register(info);
- info++;
+ if (usbdevice_name) {
+ LegacyUSBFactory *f = g_malloc0(sizeof(*f));
+ f->name = typename;
+ f->usbdevice_name = usbdevice_name;
+ f->usbdevice_init = usbdevice_init;
+ legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
}
}
@@ -143,7 +236,7 @@ USBDevice *usb_create(USBBus *bus, const char *name)
#endif
dev = qdev_create(&bus->qbus, name);
- return DO_UPCAST(USBDevice, qdev, dev);
+ return USB_DEVICE(dev);
}
USBDevice *usb_create_simple(USBBus *bus, const char *name)
@@ -249,7 +342,7 @@ int usb_claim_port(USBDevice *dev)
return -1;
}
} else {
- if (bus->nfree == 1 && strcmp(dev->qdev.info->name, "usb-hub") != 0) {
+ if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
/* Create a new hub and chain it on */
usb_create_simple(bus, "usb-hub");
}
@@ -364,7 +457,7 @@ static const char *usb_speed(unsigned int speed)
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
- USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBDevice *dev = USB_DEVICE(qdev);
USBBus *bus = usb_bus_from_device(dev);
monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
@@ -376,13 +469,13 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
static char *usb_get_dev_path(DeviceState *qdev)
{
- USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBDevice *dev = USB_DEVICE(qdev);
return g_strdup(dev->port->path);
}
static char *usb_get_fw_dev_path(DeviceState *qdev)
{
- USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ USBDevice *dev = USB_DEVICE(qdev);
char *fw_path, *in;
ssize_t pos = 0, fw_len;
long nr;
@@ -433,8 +526,8 @@ void usb_info(Monitor *mon)
USBDevice *usbdevice_create(const char *cmdline)
{
USBBus *bus = usb_bus_find(-1 /* any */);
- DeviceInfo *info;
- USBDeviceInfo *usb;
+ LegacyUSBFactory *f = NULL;
+ GSList *i;
char driver[32];
const char *params;
int len;
@@ -451,17 +544,13 @@ USBDevice *usbdevice_create(const char *cmdline)
pstrcpy(driver, sizeof(driver), cmdline);
}
- for (info = device_info_list; info != NULL; info = info->next) {
- if (info->bus_info != &usb_bus_info)
- continue;
- usb = DO_UPCAST(USBDeviceInfo, qdev, info);
- if (usb->usbdevice_name == NULL)
- continue;
- if (strcmp(usb->usbdevice_name, driver) != 0)
- continue;
- break;
+ for (i = legacy_usb_factory; i; i = i->next) {
+ f = i->data;
+ if (strcmp(f->usbdevice_name, driver) == 0) {
+ break;
+ }
}
- if (info == NULL) {
+ if (i == NULL) {
#if 0
/* no error because some drivers are not converted (yet) */
error_report("usbdevice %s not found", driver);
@@ -469,12 +558,37 @@ USBDevice *usbdevice_create(const char *cmdline)
return NULL;
}
- if (!usb->usbdevice_init) {
+ if (!f->usbdevice_init) {
if (*params) {
error_report("usbdevice %s accepts no params", driver);
return NULL;
}
- return usb_create_simple(bus, usb->qdev.name);
+ return usb_create_simple(bus, f->name);
}
- return usb->usbdevice_init(params);
+ return f->usbdevice_init(params);
+}
+
+static void usb_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->bus_info = &usb_bus_info;
+ k->init = usb_qdev_init;
+ k->unplug = qdev_simple_unplug_cb;
+ k->exit = usb_qdev_exit;
}
+
+static TypeInfo usb_device_type_info = {
+ .name = TYPE_USB_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(USBDevice),
+ .abstract = true,
+ .class_size = sizeof(USBDeviceClass),
+ .class_init = usb_device_class_init,
+};
+
+static void usb_register_devices(void)
+{
+ type_register_static(&usb_device_type_info);
+}
+
+device_init(usb_register_devices);
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index cd349f3f17..881da3002e 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -269,7 +269,6 @@ typedef struct USBCCIDState {
USBDevice dev;
CCIDBus bus;
CCIDCardState *card;
- CCIDCardInfo *cardinfo; /* caching the info pointer */
BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
uint32_t bulk_in_pending_start;
uint32_t bulk_in_pending_end; /* first free */
@@ -468,6 +467,43 @@ static const USBDesc desc_ccid = {
.str = desc_strings,
};
+static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
+{
+ CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+ if (cc->get_atr) {
+ return cc->get_atr(card, len);
+ }
+ return NULL;
+}
+
+static void ccid_card_apdu_from_guest(CCIDCardState *card,
+ const uint8_t *apdu,
+ uint32_t len)
+{
+ CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+ if (cc->apdu_from_guest) {
+ cc->apdu_from_guest(card, apdu, len);
+ }
+}
+
+static int ccid_card_exitfn(CCIDCardState *card)
+{
+ CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+ if (cc->exitfn) {
+ return cc->exitfn(card);
+ }
+ return 0;
+}
+
+static int ccid_card_initfn(CCIDCardState *card)
+{
+ CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+ if (cc->initfn) {
+ return cc->initfn(card);
+ }
+ return 0;
+}
+
static bool ccid_has_pending_answers(USBCCIDState *s)
{
return s->pending_answers_num > 0;
@@ -611,14 +647,6 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
}
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
-
/* Class specific requests. */
case InterfaceOutClass | CCID_CONTROL_ABORT:
DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
@@ -749,7 +777,7 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
uint32_t len = 0;
if (s->card) {
- atr = s->cardinfo->get_atr(s->card, &len);
+ atr = ccid_card_get_atr(s->card, &len);
}
ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
}
@@ -835,7 +863,7 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
recv->hdr.bSeq, len);
ccid_add_pending_answer(s, (CCID_Header *)recv);
if (s->card) {
- s->cardinfo->apdu_from_guest(s->card, recv->abData, len);
+ ccid_card_apdu_from_guest(s->card, recv->abData, len);
} else {
DPRINTF(s, D_WARN, "warning: discarded apdu\n");
}
@@ -1121,26 +1149,21 @@ void ccid_card_card_inserted(CCIDCardState *card)
static int ccid_card_exit(DeviceState *qdev)
{
int ret = 0;
- CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
- CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev->info);
+ CCIDCardState *card = CCID_CARD(qdev);
USBCCIDState *s =
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
if (ccid_card_inserted(s)) {
ccid_card_card_removed(card);
}
- if (info->exitfn) {
- ret = info->exitfn(card);
- }
+ ret = ccid_card_exitfn(card);
s->card = NULL;
- s->cardinfo = NULL;
return ret;
}
-static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
+static int ccid_card_init(DeviceState *qdev)
{
- CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
- CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, base);
+ CCIDCardState *card = CCID_CARD(qdev);
USBCCIDState *s =
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
int ret = 0;
@@ -1154,22 +1177,13 @@ static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
error_report("Warning: usb-ccid card already full, not adding");
return -1;
}
- ret = info->initfn ? info->initfn(card) : ret;
+ ret = ccid_card_initfn(card);
if (ret == 0) {
s->card = card;
- s->cardinfo = info;
}
return ret;
}
-void ccid_card_qdev_register(CCIDCardInfo *card)
-{
- card->qdev.bus_info = &ccid_bus_info;
- card->qdev.init = ccid_card_init;
- card->qdev.exit = ccid_card_exit;
- qdev_register(&card->qdev);
-}
-
static int ccid_initfn(USBDevice *dev)
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
@@ -1178,7 +1192,6 @@ static int ccid_initfn(USBDevice *dev)
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
s->bus.qbus.allow_hotplug = 1;
s->card = NULL;
- s->cardinfo = NULL;
s->migration_state = MIGRATION_NONE;
s->migration_target_ip = 0;
s->migration_target_port = 0;
@@ -1294,28 +1307,57 @@ static VMStateDescription ccid_vmstate = {
}
};
-static struct USBDeviceInfo ccid_info = {
- .product_desc = "QEMU USB CCID",
- .qdev.name = CCID_DEV_NAME,
- .qdev.desc = "CCID Rev 1.1 smartcard reader",
- .qdev.size = sizeof(USBCCIDState),
- .init = ccid_initfn,
- .usb_desc = &desc_ccid,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = ccid_handle_reset,
- .handle_control = ccid_handle_control,
- .handle_data = ccid_handle_data,
- .handle_destroy = ccid_handle_destroy,
- .usbdevice_name = "ccid",
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.vmsd = &ccid_vmstate,
+static Property ccid_properties[] = {
+ DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ccid_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = ccid_initfn;
+ uc->product_desc = "QEMU USB CCID";
+ uc->usb_desc = &desc_ccid;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = ccid_handle_reset;
+ uc->handle_control = ccid_handle_control;
+ uc->handle_data = ccid_handle_data;
+ uc->handle_destroy = ccid_handle_destroy;
+ dc->desc = "CCID Rev 1.1 smartcard reader";
+ dc->vmsd = &ccid_vmstate;
+ dc->props = ccid_properties;
+}
+
+static TypeInfo ccid_info = {
+ .name = CCID_DEV_NAME,
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBCCIDState),
+ .class_init = ccid_class_initfn,
+};
+
+static void ccid_card_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->bus_info = &ccid_bus_info;
+ k->init = ccid_card_init;
+ k->exit = ccid_card_exit;
+}
+
+static TypeInfo ccid_card_type_info = {
+ .name = TYPE_CCID_CARD,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(CCIDCardState),
+ .abstract = true,
+ .class_size = sizeof(CCIDCardClass),
+ .class_init = ccid_card_class_init,
};
static void ccid_register_devices(void)
{
- usb_qdev_register(&ccid_info);
+ type_register_static(&ccid_card_type_info);
+ type_register_static(&ccid_info);
+ usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
}
device_init(ccid_register_devices)
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index ae2d384bb3..3c3ed6a802 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -192,9 +192,10 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
{
- uint8_t bLength = 0x07;
+ uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
+ uint8_t extralen = ep->extra ? ep->extra[0] : 0;
- if (len < bLength) {
+ if (len < bLength + extralen) {
return -1;
}
@@ -205,8 +206,15 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
dest[0x04] = usb_lo(ep->wMaxPacketSize);
dest[0x05] = usb_hi(ep->wMaxPacketSize);
dest[0x06] = ep->bInterval;
+ if (ep->is_audio) {
+ dest[0x07] = ep->bRefresh;
+ dest[0x08] = ep->bSynchAddress;
+ }
+ if (ep->extra) {
+ memcpy(dest + bLength, ep->extra, extralen);
+ }
- return bLength;
+ return bLength + extralen;
}
int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
@@ -223,9 +231,114 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
/* ------------------------------------------------------------------ */
+static void usb_desc_ep_init(USBDevice *dev)
+{
+ const USBDescIface *iface;
+ int i, e, pid, ep;
+
+ usb_ep_init(dev);
+ for (i = 0; i < dev->ninterfaces; i++) {
+ iface = dev->ifaces[i];
+ if (iface == NULL) {
+ continue;
+ }
+ for (e = 0; e < iface->bNumEndpoints; e++) {
+ pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
+ USB_TOKEN_IN : USB_TOKEN_OUT;
+ ep = iface->eps[e].bEndpointAddress & 0x0f;
+ usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
+ usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
+ usb_ep_set_max_packet_size(dev, pid, ep,
+ iface->eps[e].wMaxPacketSize);
+ }
+ }
+}
+
+static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
+ int nif, int alt)
+{
+ const USBDescIface *iface;
+ int g, i;
+
+ if (!dev->config) {
+ return NULL;
+ }
+ for (g = 0; g < dev->config->nif_groups; g++) {
+ for (i = 0; i < dev->config->if_groups[g].nif; i++) {
+ iface = &dev->config->if_groups[g].ifs[i];
+ if (iface->bInterfaceNumber == nif &&
+ iface->bAlternateSetting == alt) {
+ return iface;
+ }
+ }
+ }
+ for (i = 0; i < dev->config->nif; i++) {
+ iface = &dev->config->ifs[i];
+ if (iface->bInterfaceNumber == nif &&
+ iface->bAlternateSetting == alt) {
+ return iface;
+ }
+ }
+ return NULL;
+}
+
+static int usb_desc_set_interface(USBDevice *dev, int index, int value)
+{
+ const USBDescIface *iface;
+ int old;
+
+ iface = usb_desc_find_interface(dev, index, value);
+ if (iface == NULL) {
+ return -1;
+ }
+
+ old = dev->altsetting[index];
+ dev->altsetting[index] = value;
+ dev->ifaces[index] = iface;
+ usb_desc_ep_init(dev);
+
+ if (old != value) {
+ usb_device_set_interface(dev, index, old, value);
+ }
+ return 0;
+}
+
+static int usb_desc_set_config(USBDevice *dev, int value)
+{
+ int i;
+
+ if (value == 0) {
+ dev->configuration = 0;
+ dev->ninterfaces = 0;
+ dev->config = NULL;
+ } else {
+ for (i = 0; i < dev->device->bNumConfigurations; i++) {
+ if (dev->device->confs[i].bConfigurationValue == value) {
+ dev->configuration = value;
+ dev->ninterfaces = dev->device->confs[i].bNumInterfaces;
+ dev->config = dev->device->confs + i;
+ assert(dev->ninterfaces <= USB_MAX_INTERFACES);
+ }
+ }
+ if (i < dev->device->bNumConfigurations) {
+ return -1;
+ }
+ }
+
+ for (i = 0; i < dev->ninterfaces; i++) {
+ usb_desc_set_interface(dev, i, 0);
+ }
+ for (; i < USB_MAX_INTERFACES; i++) {
+ dev->altsetting[i] = 0;
+ dev->ifaces[i] = NULL;
+ }
+
+ return 0;
+}
+
static void usb_desc_setdefaults(USBDevice *dev)
{
- const USBDesc *desc = dev->info->usb_desc;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
assert(desc != NULL);
switch (dev->speed) {
@@ -237,12 +350,12 @@ static void usb_desc_setdefaults(USBDevice *dev)
dev->device = desc->high;
break;
}
- dev->config = dev->device->confs;
+ usb_desc_set_config(dev, 0);
}
void usb_desc_init(USBDevice *dev)
{
- const USBDesc *desc = dev->info->usb_desc;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
assert(desc != NULL);
dev->speed = USB_SPEED_FULL;
@@ -258,7 +371,7 @@ void usb_desc_init(USBDevice *dev)
void usb_desc_attach(USBDevice *dev)
{
- const USBDesc *desc = dev->info->usb_desc;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
assert(desc != NULL);
if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
@@ -267,7 +380,7 @@ void usb_desc_attach(USBDevice *dev)
dev->speed = USB_SPEED_FULL;
} else {
fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
- dev->info->product_desc);
+ usb_device_get_product_desc(dev));
return;
}
usb_desc_setdefaults(dev);
@@ -323,7 +436,7 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
str = usb_desc_get_string(dev, index);
if (str == NULL) {
- str = dev->info->usb_desc->str[index];
+ str = usb_device_get_usb_desc(dev)->str[index];
if (str == NULL) {
return 0;
}
@@ -342,7 +455,7 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
{
- const USBDesc *desc = dev->info->usb_desc;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
const USBDescDevice *other_dev;
uint8_t buf[256];
uint8_t type = value >> 8;
@@ -350,9 +463,9 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
int ret = -1;
if (dev->speed == USB_SPEED_HIGH) {
- other_dev = dev->info->usb_desc->full;
+ other_dev = usb_device_get_usb_desc(dev)->full;
} else {
- other_dev = dev->info->usb_desc->high;
+ other_dev = usb_device_get_usb_desc(dev)->high;
}
switch(type) {
@@ -407,8 +520,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
- const USBDesc *desc = dev->info->usb_desc;
- int i, ret = -1;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
+ int ret = -1;
assert(desc != NULL);
switch(request) {
@@ -427,12 +540,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- for (i = 0; i < dev->device->bNumConfigurations; i++) {
- if (dev->device->confs[i].bConfigurationValue == value) {
- dev->config = dev->device->confs + i;
- ret = 0;
- }
- }
+ ret = usb_desc_set_config(dev, value);
trace_usb_set_config(dev->addr, value, ret);
break;
@@ -461,6 +569,19 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
}
trace_usb_set_device_feature(dev->addr, value, ret);
break;
+
+ case InterfaceRequest | USB_REQ_GET_INTERFACE:
+ if (index < 0 || index >= dev->ninterfaces) {
+ break;
+ }
+ data[0] = dev->altsetting[index];
+ ret = 1;
+ break;
+ case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+ ret = usb_desc_set_interface(dev, index, value);
+ trace_usb_set_interface(dev->addr, index, value, ret);
+ break;
+
}
return ret;
}
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 5c14e4abdc..d6e07ea5d2 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -71,6 +71,11 @@ struct USBDescEndpoint {
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
+ uint8_t bRefresh;
+ uint8_t bSynchAddress;
+
+ uint8_t is_audio; /* has bRefresh + bSynchAddress */
+ uint8_t *extra;
};
struct USBDescOther {
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 7c926c0d47..75ef71e69e 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -715,7 +715,8 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
EHCIQueue *q, *tmp;
QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
- if (q->packet.owner != dev) {
+ if (q->packet.owner == NULL ||
+ q->packet.owner->dev != dev) {
continue;
}
ehci_free_queue(q);
@@ -2262,30 +2263,46 @@ static Property ehci_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static PCIDeviceInfo ehci_info[] = {
- {
- .qdev.name = "usb-ehci",
- .qdev.size = sizeof(EHCIState),
- .qdev.vmsd = &vmstate_ehci,
- .init = usb_ehci_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
- .revision = 0x10,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = ehci_properties,
- },{
- .qdev.name = "ich9-usb-ehci1",
- .qdev.size = sizeof(EHCIState),
- .qdev.vmsd = &vmstate_ehci,
- .init = usb_ehci_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
- .revision = 0x03,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = ehci_properties,
- },{
- /* end of list */
- }
+static void ehci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_ehci_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */
+ k->revision = 0x10;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_ehci;
+ dc->props = ehci_properties;
+}
+
+static TypeInfo ehci_info = {
+ .name = "usb-ehci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(EHCIState),
+ .class_init = ehci_class_init,
+};
+
+static void ich9_ehci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_ehci_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_ehci;
+ dc->props = ehci_properties;
+}
+
+static TypeInfo ich9_ehci_info = {
+ .name = "ich9-usb-ehci1",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(EHCIState),
+ .class_init = ich9_ehci_class_init,
};
static int usb_ehci_initfn(PCIDevice *dev)
@@ -2361,7 +2378,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
static void ehci_register(void)
{
- pci_qdev_register_many(ehci_info);
+ type_register_static(&ehci_info);
+ type_register_static(&ich9_ehci_info);
}
device_init(ehci_register);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index a110c74dda..3c4e45da70 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -384,13 +384,6 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
/* hid specific requests */
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
switch (value >> 8) {
@@ -560,53 +553,81 @@ static const VMStateDescription vmstate_usb_kbd = {
}
};
-static struct USBDeviceInfo hid_info[] = {
- {
- .product_desc = "QEMU USB Tablet",
- .qdev.name = "usb-tablet",
- .usbdevice_name = "tablet",
- .qdev.size = sizeof(USBHIDState),
- .qdev.vmsd = &vmstate_usb_ptr,
- .usb_desc = &desc_tablet,
- .init = usb_tablet_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_hid_handle_reset,
- .handle_control = usb_hid_handle_control,
- .handle_data = usb_hid_handle_data,
- .handle_destroy = usb_hid_handle_destroy,
- },{
- .product_desc = "QEMU USB Mouse",
- .qdev.name = "usb-mouse",
- .usbdevice_name = "mouse",
- .qdev.size = sizeof(USBHIDState),
- .qdev.vmsd = &vmstate_usb_ptr,
- .usb_desc = &desc_mouse,
- .init = usb_mouse_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_hid_handle_reset,
- .handle_control = usb_hid_handle_control,
- .handle_data = usb_hid_handle_data,
- .handle_destroy = usb_hid_handle_destroy,
- },{
- .product_desc = "QEMU USB Keyboard",
- .qdev.name = "usb-kbd",
- .usbdevice_name = "keyboard",
- .qdev.size = sizeof(USBHIDState),
- .qdev.vmsd = &vmstate_usb_kbd,
- .usb_desc = &desc_keyboard,
- .init = usb_keyboard_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_hid_handle_reset,
- .handle_control = usb_hid_handle_control,
- .handle_data = usb_hid_handle_data,
- .handle_destroy = usb_hid_handle_destroy,
- },{
- /* end of list */
- }
+static void usb_hid_class_initfn(ObjectClass *klass, void *data)
+{
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_hid_handle_reset;
+ uc->handle_control = usb_hid_handle_control;
+ uc->handle_data = usb_hid_handle_data;
+ uc->handle_destroy = usb_hid_handle_destroy;
+}
+
+static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ usb_hid_class_initfn(klass, data);
+ uc->init = usb_tablet_initfn;
+ uc->product_desc = "QEMU USB Tablet";
+ uc->usb_desc = &desc_tablet;
+ dc->vmsd = &vmstate_usb_ptr;
+}
+
+static TypeInfo usb_tablet_info = {
+ .name = "usb-tablet",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBHIDState),
+ .class_init = usb_tablet_class_initfn,
+};
+
+static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ usb_hid_class_initfn(klass, data);
+ uc->init = usb_mouse_initfn;
+ uc->product_desc = "QEMU USB Mouse";
+ uc->usb_desc = &desc_mouse;
+ dc->vmsd = &vmstate_usb_ptr;
+}
+
+static TypeInfo usb_mouse_info = {
+ .name = "usb-mouse",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBHIDState),
+ .class_init = usb_mouse_class_initfn,
+};
+
+static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ usb_hid_class_initfn(klass, data);
+ uc->init = usb_keyboard_initfn;
+ uc->product_desc = "QEMU USB Keyboard";
+ uc->usb_desc = &desc_keyboard;
+ dc->vmsd = &vmstate_usb_kbd;
+}
+
+static TypeInfo usb_keyboard_info = {
+ .name = "usb-kbd",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBHIDState),
+ .class_init = usb_keyboard_class_initfn,
};
static void usb_hid_register_devices(void)
{
- usb_qdev_register_many(hid_info);
+ type_register_static(&usb_tablet_info);
+ usb_legacy_register("usb-tablet", "tablet", NULL);
+ type_register_static(&usb_mouse_info);
+ usb_legacy_register("usb-mouse", "mouse", NULL);
+ type_register_static(&usb_keyboard_info);
+ usb_legacy_register("usb-kbd", "keyboard", NULL);
}
device_init(usb_hid_register_devices)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index e1959372e7..956b020eed 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -258,13 +258,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
/* usb specific requests */
case GetHubStatus:
data[0] = 0;
@@ -540,23 +533,32 @@ static const VMStateDescription vmstate_usb_hub = {
}
};
-static struct USBDeviceInfo hub_info = {
- .product_desc = "QEMU USB Hub",
- .qdev.name = "usb-hub",
- .qdev.fw_name = "hub",
- .qdev.size = sizeof(USBHubState),
- .qdev.vmsd = &vmstate_usb_hub,
- .usb_desc = &desc_hub,
- .init = usb_hub_initfn,
- .handle_packet = usb_hub_handle_packet,
- .handle_reset = usb_hub_handle_reset,
- .handle_control = usb_hub_handle_control,
- .handle_data = usb_hub_handle_data,
- .handle_destroy = usb_hub_handle_destroy,
+static void usb_hub_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_hub_initfn;
+ uc->product_desc = "QEMU USB Hub";
+ uc->usb_desc = &desc_hub;
+ uc->handle_packet = usb_hub_handle_packet;
+ uc->handle_reset = usb_hub_handle_reset;
+ uc->handle_control = usb_hub_handle_control;
+ uc->handle_data = usb_hub_handle_data;
+ uc->handle_destroy = usb_hub_handle_destroy;
+ dc->fw_name = "hub";
+ dc->vmsd = &vmstate_usb_hub;
+}
+
+static TypeInfo hub_info = {
+ .name = "usb-hub",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBHubState),
+ .class_init = usb_hub_class_initfn,
};
static void usb_hub_register_devices(void)
{
- usb_qdev_register(&hub_info);
+ type_register_static(&hub_info);
}
device_init(usb_hub_register_devices)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index e42729699d..6153376f3f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -306,19 +306,9 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
ret = 0;
break;
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
/* Class specific requests. */
case ClassInterfaceOutRequest | MassStorageReset:
/* Reset state ready for the next CBW. */
@@ -646,32 +636,42 @@ static const VMStateDescription vmstate_usb_msd = {
}
};
-static struct USBDeviceInfo msd_info = {
- .product_desc = "QEMU USB MSD",
- .qdev.name = "usb-storage",
- .qdev.fw_name = "storage",
- .qdev.size = sizeof(MSDState),
- .qdev.vmsd = &vmstate_usb_msd,
- .usb_desc = &desc,
- .init = usb_msd_initfn,
- .handle_packet = usb_generic_handle_packet,
- .cancel_packet = usb_msd_cancel_io,
- .handle_attach = usb_desc_attach,
- .handle_reset = usb_msd_handle_reset,
- .handle_control = usb_msd_handle_control,
- .handle_data = usb_msd_handle_data,
- .usbdevice_name = "disk",
- .usbdevice_init = usb_msd_init,
- .qdev.props = (Property[]) {
- DEFINE_BLOCK_PROPERTIES(MSDState, conf),
- DEFINE_PROP_STRING("serial", MSDState, serial),
- DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property msd_properties[] = {
+ DEFINE_BLOCK_PROPERTIES(MSDState, conf),
+ DEFINE_PROP_STRING("serial", MSDState, serial),
+ DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_msd_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_msd_initfn;
+ uc->product_desc = "QEMU USB MSD";
+ uc->usb_desc = &desc;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->cancel_packet = usb_msd_cancel_io;
+ uc->handle_attach = usb_desc_attach;
+ uc->handle_reset = usb_msd_handle_reset;
+ uc->handle_control = usb_msd_handle_control;
+ uc->handle_data = usb_msd_handle_data;
+ dc->fw_name = "storage";
+ dc->vmsd = &vmstate_usb_msd;
+ dc->props = msd_properties;
+}
+
+static TypeInfo msd_info = {
+ .name = "usb-storage",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(MSDState),
+ .class_init = usb_msd_class_initfn,
};
static void usb_msd_register_devices(void)
{
- usb_qdev_register(&msd_info);
+ type_register_static(&msd_info);
+ usb_legacy_register("usb-storage", "disk", usb_msd_init);
}
device_init(usb_msd_register_devices)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 01e2e7c389..4f528d25e5 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -812,7 +812,8 @@ static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
for (ep = 0; ep < 16; ep++) {
for (dir = 0; dir < 2; dir++) {
- if (s->ep[ep].packey[dir].p.owner != dev) {
+ if (s->ep[ep].packey[dir].p.owner == NULL ||
+ s->ep[ep].packey[dir].p.owner->dev != dev) {
continue;
}
usb_cancel_packet(&s->ep[ep].packey[dir].p);
diff --git a/hw/usb-net.c b/hw/usb-net.c
index f91fa32334..e2111413b4 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -71,9 +71,6 @@ enum usbstring_idx {
#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
-#define USB_DT_CS_INTERFACE 0x24
-#define USB_DT_CS_ENDPOINT 0x25
-
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
#define USB_CDC_REQ_SET_LINE_CODING 0x20
@@ -1098,17 +1095,6 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
#endif
break;
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- case InterfaceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
-
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
-
default:
fail:
fprintf(stderr, "usbnet: failed control transaction: "
@@ -1351,7 +1337,7 @@ static int usb_net_initfn(USBDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
- s->dev.qdev.info->name, s->dev.qdev.id, s);
+ object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
"%02x%02x%02x%02x%02x%02x",
@@ -1399,29 +1385,39 @@ static const VMStateDescription vmstate_usb_net = {
.unmigratable = 1,
};
-static struct USBDeviceInfo net_info = {
- .product_desc = "QEMU USB Network Interface",
- .qdev.name = "usb-net",
- .qdev.fw_name = "network",
- .qdev.size = sizeof(USBNetState),
- .qdev.vmsd = &vmstate_usb_net,
- .usb_desc = &desc_net,
- .init = usb_net_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_net_handle_reset,
- .handle_control = usb_net_handle_control,
- .handle_data = usb_net_handle_data,
- .handle_destroy = usb_net_handle_destroy,
- .usbdevice_name = "net",
- .usbdevice_init = usb_net_init,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(USBNetState, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property net_properties[] = {
+ DEFINE_NIC_PROPERTIES(USBNetState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_net_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_net_initfn;
+ uc->product_desc = "QEMU USB Network Interface";
+ uc->usb_desc = &desc_net;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_net_handle_reset;
+ uc->handle_control = usb_net_handle_control;
+ uc->handle_data = usb_net_handle_data;
+ uc->handle_destroy = usb_net_handle_destroy;
+ dc->fw_name = "network";
+ dc->vmsd = &vmstate_usb_net;
+ dc->props = net_properties;
+}
+
+static TypeInfo net_info = {
+ .name = "usb-net",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBNetState),
+ .class_init = usb_net_class_initfn,
};
static void usb_net_register_devices(void)
{
- usb_qdev_register(&net_info);
+ type_register_static(&net_info);
+ usb_legacy_register("usb-net", "net", usb_net_init);
}
device_init(usb_net_register_devices)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 81488c48e2..425030f141 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1707,7 +1707,9 @@ static void ohci_mem_write(void *opaque,
static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
{
- if (ohci->async_td && ohci->usb_packet.owner == dev) {
+ if (ohci->async_td &&
+ ohci->usb_packet.owner != NULL &&
+ ohci->usb_packet.owner->dev == dev) {
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
}
@@ -1775,7 +1777,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
ohci->localmem_base = localmem_base;
- ohci->name = dev->info->name;
+ ohci->name = object_get_typename(OBJECT(dev));
usb_packet_init(&ohci->usb_packet);
ohci->async_td = 0;
@@ -1834,37 +1836,59 @@ static int ohci_init_pxa(SysBusDevice *dev)
return 0;
}
-static PCIDeviceInfo ohci_pci_info = {
- .qdev.name = "pci-ohci",
- .qdev.desc = "Apple USB Controller",
- .qdev.size = sizeof(OHCIPCIState),
- .init = usb_ohci_initfn_pci,
- .vendor_id = PCI_VENDOR_ID_APPLE,
- .device_id = PCI_DEVICE_ID_APPLE_IPID_USB,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = (Property[]) {
- DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
- DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
- DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property ohci_pci_properties[] = {
+ DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
+ DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
+ DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
+ DEFINE_PROP_END_OF_LIST(),
};
-static SysBusDeviceInfo ohci_sysbus_info = {
- .init = ohci_init_pxa,
- .qdev.name = "sysbus-ohci",
- .qdev.desc = "OHCI USB Controller",
- .qdev.size = sizeof(OHCISysBusState),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
- DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3),
- DEFINE_PROP_END_OF_LIST(),
- }
+static void ohci_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_ohci_initfn_pci;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->desc = "Apple USB Controller";
+ dc->props = ohci_pci_properties;
+}
+
+static TypeInfo ohci_pci_info = {
+ .name = "pci-ohci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(OHCIPCIState),
+ .class_init = ohci_pci_class_init,
+};
+
+static Property ohci_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+ DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sbc->init = ohci_init_pxa;
+ dc->desc = "OHCI USB Controller";
+ dc->props = ohci_sysbus_properties;
+}
+
+static TypeInfo ohci_sysbus_info = {
+ .name = "sysbus-ohci",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OHCISysBusState),
+ .class_init = ohci_sysbus_class_init,
};
static void ohci_register(void)
{
- pci_qdev_register(&ohci_pci_info);
- sysbus_register_withprop(&ohci_sysbus_info);
+ type_register_static(&ohci_pci_info);
+ type_register_static(&ohci_sysbus_info);
}
device_init(ohci_register);
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 7dbf6dfc6d..c2cb6d24e8 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -233,13 +233,6 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
ret = 0;
break;
@@ -577,49 +570,69 @@ static const VMStateDescription vmstate_usb_serial = {
.unmigratable = 1,
};
-static struct USBDeviceInfo serial_info = {
- .product_desc = "QEMU USB Serial",
- .qdev.name = "usb-serial",
- .qdev.size = sizeof(USBSerialState),
- .qdev.vmsd = &vmstate_usb_serial,
- .usb_desc = &desc_serial,
- .init = usb_serial_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_serial_handle_reset,
- .handle_control = usb_serial_handle_control,
- .handle_data = usb_serial_handle_data,
- .handle_destroy = usb_serial_handle_destroy,
- .usbdevice_name = "serial",
- .usbdevice_init = usb_serial_init,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", USBSerialState, cs),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property serial_properties[] = {
+ DEFINE_PROP_CHR("chardev", USBSerialState, cs),
+ DEFINE_PROP_END_OF_LIST(),
};
-static struct USBDeviceInfo braille_info = {
- .product_desc = "QEMU USB Braille",
- .qdev.name = "usb-braille",
- .qdev.size = sizeof(USBSerialState),
- .qdev.vmsd = &vmstate_usb_serial,
- .usb_desc = &desc_braille,
- .init = usb_serial_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_serial_handle_reset,
- .handle_control = usb_serial_handle_control,
- .handle_data = usb_serial_handle_data,
- .handle_destroy = usb_serial_handle_destroy,
- .usbdevice_name = "braille",
- .usbdevice_init = usb_braille_init,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", USBSerialState, cs),
- DEFINE_PROP_END_OF_LIST(),
- },
+static void usb_serial_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_serial_initfn;
+ uc->product_desc = "QEMU USB Serial";
+ uc->usb_desc = &desc_serial;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_serial_handle_reset;
+ uc->handle_control = usb_serial_handle_control;
+ uc->handle_data = usb_serial_handle_data;
+ uc->handle_destroy = usb_serial_handle_destroy;
+ dc->vmsd = &vmstate_usb_serial;
+ dc->props = serial_properties;
+}
+
+static TypeInfo serial_info = {
+ .name = "usb-serial",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBSerialState),
+ .class_init = usb_serial_class_initfn,
+};
+
+static Property braille_properties[] = {
+ DEFINE_PROP_CHR("chardev", USBSerialState, cs),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_braille_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->init = usb_serial_initfn;
+ uc->product_desc = "QEMU USB Braille";
+ uc->usb_desc = &desc_braille;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_serial_handle_reset;
+ uc->handle_control = usb_serial_handle_control;
+ uc->handle_data = usb_serial_handle_data;
+ uc->handle_destroy = usb_serial_handle_destroy;
+ dc->vmsd = &vmstate_usb_serial;
+ dc->props = braille_properties;
+}
+
+static TypeInfo braille_info = {
+ .name = "usb-braille",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBSerialState),
+ .class_init = usb_braille_class_initfn,
};
static void usb_serial_register_devices(void)
{
- usb_qdev_register(&serial_info);
- usb_qdev_register(&braille_info);
+ type_register_static(&serial_info);
+ usb_legacy_register("usb-serial", "serial", usb_serial_init);
+ type_register_static(&braille_info);
+ usb_legacy_register("usb-braille", "braille", usb_braille_init);
}
device_init(usb_serial_register_devices)
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index f8912e2b0b..cddcc8927a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -245,7 +245,8 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
UHCIAsync *curr, *n;
QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
- if (curr->packet.owner != dev) {
+ if (curr->packet.owner == NULL ||
+ curr->packet.owner->dev != dev) {
continue;
}
uhci_async_unlink(s, curr);
@@ -1191,78 +1192,143 @@ static Property uhci_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static PCIDeviceInfo uhci_info[] = {
- {
- .qdev.name = "piix3-usb-uhci",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_common_initfn,
- .exit = usb_uhci_exit,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371SB_2,
- .revision = 0x01,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- .qdev.name = "piix4-usb-uhci",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_common_initfn,
- .exit = usb_uhci_exit,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82371AB_2,
- .revision = 0x01,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- .qdev.name = "vt82c686b-usb-uhci",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_vt82c686b_initfn,
- .exit = usb_uhci_exit,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_UHCI,
- .revision = 0x01,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- .qdev.name = "ich9-usb-uhci1",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_common_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1,
- .revision = 0x03,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- .qdev.name = "ich9-usb-uhci2",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_common_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2,
- .revision = 0x03,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- .qdev.name = "ich9-usb-uhci3",
- .qdev.size = sizeof(UHCIState),
- .qdev.vmsd = &vmstate_uhci,
- .init = usb_uhci_common_initfn,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3,
- .revision = 0x03,
- .class_id = PCI_CLASS_SERIAL_USB,
- .qdev.props = uhci_properties,
- },{
- /* end of list */
- }
+static void piix3_uhci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_common_initfn;
+ k->exit = usb_uhci_exit;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo piix3_uhci_info = {
+ .name = "piix3-usb-uhci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = piix3_uhci_class_init,
+};
+
+static void piix4_uhci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_common_initfn;
+ k->exit = usb_uhci_exit;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo piix4_uhci_info = {
+ .name = "piix4-usb-uhci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = piix4_uhci_class_init,
+};
+
+static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_vt82c686b_initfn;
+ k->exit = usb_uhci_exit;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_UHCI;
+ k->revision = 0x01;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo vt82c686b_uhci_info = {
+ .name = "vt82c686b-usb-uhci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = vt82c686b_uhci_class_init,
+};
+
+static void ich9_uhci1_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_common_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci1_info = {
+ .name = "ich9-usb-uhci1",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = ich9_uhci1_class_init,
+};
+
+static void ich9_uhci2_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_common_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci2_info = {
+ .name = "ich9-usb-uhci2",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = ich9_uhci2_class_init,
+};
+
+static void ich9_uhci3_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_uhci_common_initfn;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->vmsd = &vmstate_uhci;
+ dc->props = uhci_properties;
+}
+
+static TypeInfo ich9_uhci3_info = {
+ .name = "ich9-usb-uhci3",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(UHCIState),
+ .class_init = ich9_uhci3_class_init,
};
static void uhci_register(void)
{
- pci_qdev_register_many(uhci_info);
+ type_register_static(&piix3_uhci_info);
+ type_register_static(&piix4_uhci_info);
+ type_register_static(&vt82c686b_uhci_info);
+ type_register_static(&ich9_uhci1_info);
+ type_register_static(&ich9_uhci2_info);
+ type_register_static(&ich9_uhci3_info);
}
device_init(uhci_register);
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 25580067f2..14de14d5f7 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -263,13 +263,6 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_INTERFACE:
- data[0] = 0;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_INTERFACE:
- ret = 0;
- break;
case WACOM_SET_REPORT:
if (s->mouse_grabbed) {
qemu_remove_mouse_event_handler(s->eh_entry);
@@ -356,24 +349,33 @@ static const VMStateDescription vmstate_usb_wacom = {
.unmigratable = 1,
};
-static struct USBDeviceInfo wacom_info = {
- .product_desc = "QEMU PenPartner Tablet",
- .qdev.name = "usb-wacom-tablet",
- .qdev.desc = "QEMU PenPartner Tablet",
- .usbdevice_name = "wacom-tablet",
- .usb_desc = &desc_wacom,
- .qdev.size = sizeof(USBWacomState),
- .qdev.vmsd = &vmstate_usb_wacom,
- .init = usb_wacom_initfn,
- .handle_packet = usb_generic_handle_packet,
- .handle_reset = usb_wacom_handle_reset,
- .handle_control = usb_wacom_handle_control,
- .handle_data = usb_wacom_handle_data,
- .handle_destroy = usb_wacom_handle_destroy,
+static void usb_wacom_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->product_desc = "QEMU PenPartner Tablet";
+ uc->usb_desc = &desc_wacom;
+ uc->init = usb_wacom_initfn;
+ uc->handle_packet = usb_generic_handle_packet;
+ uc->handle_reset = usb_wacom_handle_reset;
+ uc->handle_control = usb_wacom_handle_control;
+ uc->handle_data = usb_wacom_handle_data;
+ uc->handle_destroy = usb_wacom_handle_destroy;
+ dc->desc = "QEMU PenPartner Tablet";
+ dc->vmsd = &vmstate_usb_wacom;
+}
+
+static TypeInfo wacom_info = {
+ .name = "usb-wacom-tablet",
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(USBWacomState),
+ .class_init = usb_wacom_class_init,
};
static void usb_wacom_register_devices(void)
{
- usb_qdev_register(&wacom_info);
+ type_register_static(&wacom_info);
+ usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL);
}
device_init(usb_wacom_register_devices)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
new file mode 100644
index 0000000000..37e887c431
--- /dev/null
+++ b/hw/usb-xhci.c
@@ -0,0 +1,2759 @@
+/*
+ * USB xHCI controller emulation
+ *
+ * Copyright (c) 2011 Securiforest
+ * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com>
+ * Based on usb-ohci.c, emulates Renesas NEC USB 3.0
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "qemu-timer.h"
+#include "usb.h"
+#include "pci.h"
+#include "qdev-addr.h"
+#include "msi.h"
+
+//#define DEBUG_XHCI
+//#define DEBUG_DATA
+
+#ifdef DEBUG_XHCI
+#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define DPRINTF(...) do {} while (0)
+#endif
+#define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
+ __func__, __LINE__); abort(); } while (0)
+
+#define MAXSLOTS 8
+#define MAXINTRS 1
+
+#define USB2_PORTS 4
+#define USB3_PORTS 4
+
+#define MAXPORTS (USB2_PORTS+USB3_PORTS)
+
+#define TD_QUEUE 24
+#define BG_XFERS 8
+#define BG_PKTS 8
+
+/* Very pessimistic, let's hope it's enough for all cases */
+#define EV_QUEUE (((3*TD_QUEUE)+16)*MAXSLOTS)
+/* Do not deliver ER Full events. NEC's driver does some things not bound
+ * to the specs when it gets them */
+#define ER_FULL_HACK
+
+#define LEN_CAP 0x40
+#define OFF_OPER LEN_CAP
+#define LEN_OPER (0x400 + 0x10 * MAXPORTS)
+#define OFF_RUNTIME ((OFF_OPER + LEN_OPER + 0x20) & ~0x1f)
+#define LEN_RUNTIME (0x20 + MAXINTRS * 0x20)
+#define OFF_DOORBELL (OFF_RUNTIME + LEN_RUNTIME)
+#define LEN_DOORBELL ((MAXSLOTS + 1) * 0x20)
+
+/* must be power of 2 */
+#define LEN_REGS 0x2000
+
+#if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS
+# error Increase LEN_REGS
+#endif
+
+#if MAXINTRS > 1
+# error TODO: only one interrupter supported
+#endif
+
+/* bit definitions */
+#define USBCMD_RS (1<<0)
+#define USBCMD_HCRST (1<<1)
+#define USBCMD_INTE (1<<2)
+#define USBCMD_HSEE (1<<3)
+#define USBCMD_LHCRST (1<<7)
+#define USBCMD_CSS (1<<8)
+#define USBCMD_CRS (1<<9)
+#define USBCMD_EWE (1<<10)
+#define USBCMD_EU3S (1<<11)
+
+#define USBSTS_HCH (1<<0)
+#define USBSTS_HSE (1<<2)
+#define USBSTS_EINT (1<<3)
+#define USBSTS_PCD (1<<4)
+#define USBSTS_SSS (1<<8)
+#define USBSTS_RSS (1<<9)
+#define USBSTS_SRE (1<<10)
+#define USBSTS_CNR (1<<11)
+#define USBSTS_HCE (1<<12)
+
+
+#define PORTSC_CCS (1<<0)
+#define PORTSC_PED (1<<1)
+#define PORTSC_OCA (1<<3)
+#define PORTSC_PR (1<<4)
+#define PORTSC_PLS_SHIFT 5
+#define PORTSC_PLS_MASK 0xf
+#define PORTSC_PP (1<<9)
+#define PORTSC_SPEED_SHIFT 10
+#define PORTSC_SPEED_MASK 0xf
+#define PORTSC_SPEED_FULL (1<<10)
+#define PORTSC_SPEED_LOW (2<<10)
+#define PORTSC_SPEED_HIGH (3<<10)
+#define PORTSC_SPEED_SUPER (4<<10)
+#define PORTSC_PIC_SHIFT 14
+#define PORTSC_PIC_MASK 0x3
+#define PORTSC_LWS (1<<16)
+#define PORTSC_CSC (1<<17)
+#define PORTSC_PEC (1<<18)
+#define PORTSC_WRC (1<<19)
+#define PORTSC_OCC (1<<20)
+#define PORTSC_PRC (1<<21)
+#define PORTSC_PLC (1<<22)
+#define PORTSC_CEC (1<<23)
+#define PORTSC_CAS (1<<24)
+#define PORTSC_WCE (1<<25)
+#define PORTSC_WDE (1<<26)
+#define PORTSC_WOE (1<<27)
+#define PORTSC_DR (1<<30)
+#define PORTSC_WPR (1<<31)
+
+#define CRCR_RCS (1<<0)
+#define CRCR_CS (1<<1)
+#define CRCR_CA (1<<2)
+#define CRCR_CRR (1<<3)
+
+#define IMAN_IP (1<<0)
+#define IMAN_IE (1<<1)
+
+#define ERDP_EHB (1<<3)
+
+#define TRB_SIZE 16
+typedef struct XHCITRB {
+ uint64_t parameter;
+ uint32_t status;
+ uint32_t control;
+ target_phys_addr_t addr;
+ bool ccs;
+} XHCITRB;
+
+
+typedef enum TRBType {
+ TRB_RESERVED = 0,
+ TR_NORMAL,
+ TR_SETUP,
+ TR_DATA,
+ TR_STATUS,
+ TR_ISOCH,
+ TR_LINK,
+ TR_EVDATA,
+ TR_NOOP,
+ CR_ENABLE_SLOT,
+ CR_DISABLE_SLOT,
+ CR_ADDRESS_DEVICE,
+ CR_CONFIGURE_ENDPOINT,
+ CR_EVALUATE_CONTEXT,
+ CR_RESET_ENDPOINT,
+ CR_STOP_ENDPOINT,
+ CR_SET_TR_DEQUEUE,
+ CR_RESET_DEVICE,
+ CR_FORCE_EVENT,
+ CR_NEGOTIATE_BW,
+ CR_SET_LATENCY_TOLERANCE,
+ CR_GET_PORT_BANDWIDTH,
+ CR_FORCE_HEADER,
+ CR_NOOP,
+ ER_TRANSFER = 32,
+ ER_COMMAND_COMPLETE,
+ ER_PORT_STATUS_CHANGE,
+ ER_BANDWIDTH_REQUEST,
+ ER_DOORBELL,
+ ER_HOST_CONTROLLER,
+ ER_DEVICE_NOTIFICATION,
+ ER_MFINDEX_WRAP,
+ /* vendor specific bits */
+ CR_VENDOR_VIA_CHALLENGE_RESPONSE = 48,
+ CR_VENDOR_NEC_FIRMWARE_REVISION = 49,
+ CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50,
+} TRBType;
+
+#define CR_LINK TR_LINK
+
+typedef enum TRBCCode {
+ CC_INVALID = 0,
+ CC_SUCCESS,
+ CC_DATA_BUFFER_ERROR,
+ CC_BABBLE_DETECTED,
+ CC_USB_TRANSACTION_ERROR,
+ CC_TRB_ERROR,
+ CC_STALL_ERROR,
+ CC_RESOURCE_ERROR,
+ CC_BANDWIDTH_ERROR,
+ CC_NO_SLOTS_ERROR,
+ CC_INVALID_STREAM_TYPE_ERROR,
+ CC_SLOT_NOT_ENABLED_ERROR,
+ CC_EP_NOT_ENABLED_ERROR,
+ CC_SHORT_PACKET,
+ CC_RING_UNDERRUN,
+ CC_RING_OVERRUN,
+ CC_VF_ER_FULL,
+ CC_PARAMETER_ERROR,
+ CC_BANDWIDTH_OVERRUN,
+ CC_CONTEXT_STATE_ERROR,
+ CC_NO_PING_RESPONSE_ERROR,
+ CC_EVENT_RING_FULL_ERROR,
+ CC_INCOMPATIBLE_DEVICE_ERROR,
+ CC_MISSED_SERVICE_ERROR,
+ CC_COMMAND_RING_STOPPED,
+ CC_COMMAND_ABORTED,
+ CC_STOPPED,
+ CC_STOPPED_LENGTH_INVALID,
+ CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
+ CC_ISOCH_BUFFER_OVERRUN = 31,
+ CC_EVENT_LOST_ERROR,
+ CC_UNDEFINED_ERROR,
+ CC_INVALID_STREAM_ID_ERROR,
+ CC_SECONDARY_BANDWIDTH_ERROR,
+ CC_SPLIT_TRANSACTION_ERROR
+} TRBCCode;
+
+#define TRB_C (1<<0)
+#define TRB_TYPE_SHIFT 10
+#define TRB_TYPE_MASK 0x3f
+#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
+
+#define TRB_EV_ED (1<<2)
+
+#define TRB_TR_ENT (1<<1)
+#define TRB_TR_ISP (1<<2)
+#define TRB_TR_NS (1<<3)
+#define TRB_TR_CH (1<<4)
+#define TRB_TR_IOC (1<<5)
+#define TRB_TR_IDT (1<<6)
+#define TRB_TR_TBC_SHIFT 7
+#define TRB_TR_TBC_MASK 0x3
+#define TRB_TR_BEI (1<<9)
+#define TRB_TR_TLBPC_SHIFT 16
+#define TRB_TR_TLBPC_MASK 0xf
+#define TRB_TR_FRAMEID_SHIFT 20
+#define TRB_TR_FRAMEID_MASK 0x7ff
+#define TRB_TR_SIA (1<<31)
+
+#define TRB_TR_DIR (1<<16)
+
+#define TRB_CR_SLOTID_SHIFT 24
+#define TRB_CR_SLOTID_MASK 0xff
+#define TRB_CR_EPID_SHIFT 16
+#define TRB_CR_EPID_MASK 0x1f
+
+#define TRB_CR_BSR (1<<9)
+#define TRB_CR_DC (1<<9)
+
+#define TRB_LK_TC (1<<1)
+
+#define EP_TYPE_MASK 0x7
+#define EP_TYPE_SHIFT 3
+
+#define EP_STATE_MASK 0x7
+#define EP_DISABLED (0<<0)
+#define EP_RUNNING (1<<0)
+#define EP_HALTED (2<<0)
+#define EP_STOPPED (3<<0)
+#define EP_ERROR (4<<0)
+
+#define SLOT_STATE_MASK 0x1f
+#define SLOT_STATE_SHIFT 27
+#define SLOT_STATE(s) (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK)
+#define SLOT_ENABLED 0
+#define SLOT_DEFAULT 1
+#define SLOT_ADDRESSED 2
+#define SLOT_CONFIGURED 3
+
+#define SLOT_CONTEXT_ENTRIES_MASK 0x1f
+#define SLOT_CONTEXT_ENTRIES_SHIFT 27
+
+typedef enum EPType {
+ ET_INVALID = 0,
+ ET_ISO_OUT,
+ ET_BULK_OUT,
+ ET_INTR_OUT,
+ ET_CONTROL,
+ ET_ISO_IN,
+ ET_BULK_IN,
+ ET_INTR_IN,
+} EPType;
+
+typedef struct XHCIRing {
+ target_phys_addr_t base;
+ target_phys_addr_t dequeue;
+ bool ccs;
+} XHCIRing;
+
+typedef struct XHCIPort {
+ USBPort port;
+ uint32_t portsc;
+} XHCIPort;
+
+struct XHCIState;
+typedef struct XHCIState XHCIState;
+
+typedef struct XHCITransfer {
+ XHCIState *xhci;
+ USBPacket packet;
+ bool running;
+ bool cancelled;
+ bool complete;
+ bool backgrounded;
+ unsigned int iso_pkts;
+ unsigned int slotid;
+ unsigned int epid;
+ bool in_xfer;
+ bool iso_xfer;
+ bool bg_xfer;
+
+ unsigned int trb_count;
+ unsigned int trb_alloced;
+ XHCITRB *trbs;
+
+ unsigned int data_length;
+ unsigned int data_alloced;
+ uint8_t *data;
+
+ TRBCCode status;
+
+ unsigned int pkts;
+ unsigned int pktsize;
+ unsigned int cur_pkt;
+} XHCITransfer;
+
+typedef struct XHCIEPContext {
+ XHCIRing ring;
+ unsigned int next_xfer;
+ unsigned int comp_xfer;
+ XHCITransfer transfers[TD_QUEUE];
+ bool bg_running;
+ bool bg_updating;
+ unsigned int next_bg;
+ XHCITransfer bg_transfers[BG_XFERS];
+ EPType type;
+ target_phys_addr_t pctx;
+ unsigned int max_psize;
+ bool has_bg;
+ uint32_t state;
+} XHCIEPContext;
+
+typedef struct XHCISlot {
+ bool enabled;
+ target_phys_addr_t ctx;
+ unsigned int port;
+ unsigned int devaddr;
+ XHCIEPContext * eps[31];
+} XHCISlot;
+
+typedef struct XHCIEvent {
+ TRBType type;
+ TRBCCode ccode;
+ uint64_t ptr;
+ uint32_t length;
+ uint32_t flags;
+ uint8_t slotid;
+ uint8_t epid;
+} XHCIEvent;
+
+struct XHCIState {
+ PCIDevice pci_dev;
+ USBBus bus;
+ qemu_irq irq;
+ MemoryRegion mem;
+ const char *name;
+ uint32_t msi;
+ unsigned int devaddr;
+
+ /* Operational Registers */
+ uint32_t usbcmd;
+ uint32_t usbsts;
+ uint32_t dnctrl;
+ uint32_t crcr_low;
+ uint32_t crcr_high;
+ uint32_t dcbaap_low;
+ uint32_t dcbaap_high;
+ uint32_t config;
+
+ XHCIPort ports[MAXPORTS];
+ XHCISlot slots[MAXSLOTS];
+
+ /* Runtime Registers */
+ uint32_t mfindex;
+ /* note: we only support one interrupter */
+ uint32_t iman;
+ uint32_t imod;
+ uint32_t erstsz;
+ uint32_t erstba_low;
+ uint32_t erstba_high;
+ uint32_t erdp_low;
+ uint32_t erdp_high;
+
+ target_phys_addr_t er_start;
+ uint32_t er_size;
+ bool er_pcs;
+ unsigned int er_ep_idx;
+ bool er_full;
+
+ XHCIEvent ev_buffer[EV_QUEUE];
+ unsigned int ev_buffer_put;
+ unsigned int ev_buffer_get;
+
+ XHCIRing cmd_ring;
+};
+
+typedef struct XHCIEvRingSeg {
+ uint32_t addr_low;
+ uint32_t addr_high;
+ uint32_t size;
+ uint32_t rsvd;
+} XHCIEvRingSeg;
+
+static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid);
+
+static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high)
+{
+#if TARGET_PHYS_ADDR_BITS > 32
+ return low | ((target_phys_addr_t)high << 32);
+#else
+ return low;
+#endif
+}
+
+static inline target_phys_addr_t xhci_mask64(uint64_t addr)
+{
+#if TARGET_PHYS_ADDR_BITS > 32
+ return addr;
+#else
+ return addr & 0xffffffff;
+#endif
+}
+
+static void xhci_irq_update(XHCIState *xhci)
+{
+ int level = 0;
+
+ if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
+ xhci->usbcmd && USBCMD_INTE) {
+ level = 1;
+ }
+
+ DPRINTF("xhci_irq_update(): %d\n", level);
+
+ if (xhci->msi && msi_enabled(&xhci->pci_dev)) {
+ if (level) {
+ DPRINTF("xhci_irq_update(): MSI signal\n");
+ msi_notify(&xhci->pci_dev, 0);
+ }
+ } else {
+ qemu_set_irq(xhci->irq, level);
+ }
+}
+
+static inline int xhci_running(XHCIState *xhci)
+{
+ return !(xhci->usbsts & USBSTS_HCH) && !xhci->er_full;
+}
+
+static void xhci_die(XHCIState *xhci)
+{
+ xhci->usbsts |= USBSTS_HCE;
+ fprintf(stderr, "xhci: asserted controller error\n");
+}
+
+static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
+{
+ XHCITRB ev_trb;
+ target_phys_addr_t addr;
+
+ ev_trb.parameter = cpu_to_le64(event->ptr);
+ ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
+ ev_trb.control = (event->slotid << 24) | (event->epid << 16) |
+ event->flags | (event->type << TRB_TYPE_SHIFT);
+ if (xhci->er_pcs) {
+ ev_trb.control |= TRB_C;
+ }
+ ev_trb.control = cpu_to_le32(ev_trb.control);
+
+ DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x\n",
+ xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control);
+
+ addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
+ cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
+
+ xhci->er_ep_idx++;
+ if (xhci->er_ep_idx >= xhci->er_size) {
+ xhci->er_ep_idx = 0;
+ xhci->er_pcs = !xhci->er_pcs;
+ }
+}
+
+static void xhci_events_update(XHCIState *xhci)
+{
+ target_phys_addr_t erdp;
+ unsigned int dp_idx;
+ bool do_irq = 0;
+
+ if (xhci->usbsts & USBSTS_HCH) {
+ return;
+ }
+
+ erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
+ if (erdp < xhci->er_start ||
+ erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+ fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
+ fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ xhci->er_start, xhci->er_size);
+ xhci_die(xhci);
+ return;
+ }
+ dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
+ assert(dp_idx < xhci->er_size);
+
+ /* NEC didn't read section 4.9.4 of the spec (v1.0 p139 top Note) and thus
+ * deadlocks when the ER is full. Hack it by holding off events until
+ * the driver decides to free at least half of the ring */
+ if (xhci->er_full) {
+ int er_free = dp_idx - xhci->er_ep_idx;
+ if (er_free <= 0) {
+ er_free += xhci->er_size;
+ }
+ if (er_free < (xhci->er_size/2)) {
+ DPRINTF("xhci_events_update(): event ring still "
+ "more than half full (hack)\n");
+ return;
+ }
+ }
+
+ while (xhci->ev_buffer_put != xhci->ev_buffer_get) {
+ assert(xhci->er_full);
+ if (((xhci->er_ep_idx+1) % xhci->er_size) == dp_idx) {
+ DPRINTF("xhci_events_update(): event ring full again\n");
+#ifndef ER_FULL_HACK
+ XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
+ xhci_write_event(xhci, &full);
+#endif
+ do_irq = 1;
+ break;
+ }
+ XHCIEvent *event = &xhci->ev_buffer[xhci->ev_buffer_get];
+ xhci_write_event(xhci, event);
+ xhci->ev_buffer_get++;
+ do_irq = 1;
+ if (xhci->ev_buffer_get == EV_QUEUE) {
+ xhci->ev_buffer_get = 0;
+ }
+ }
+
+ if (do_irq) {
+ xhci->erdp_low |= ERDP_EHB;
+ xhci->iman |= IMAN_IP;
+ xhci->usbsts |= USBSTS_EINT;
+ xhci_irq_update(xhci);
+ }
+
+ if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
+ DPRINTF("xhci_events_update(): event ring no longer full\n");
+ xhci->er_full = 0;
+ }
+ return;
+}
+
+static void xhci_event(XHCIState *xhci, XHCIEvent *event)
+{
+ target_phys_addr_t erdp;
+ unsigned int dp_idx;
+
+ if (xhci->er_full) {
+ DPRINTF("xhci_event(): ER full, queueing\n");
+ if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+ fprintf(stderr, "xhci: event queue full, dropping event!\n");
+ return;
+ }
+ xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
+ if (xhci->ev_buffer_put == EV_QUEUE) {
+ xhci->ev_buffer_put = 0;
+ }
+ return;
+ }
+
+ erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
+ if (erdp < xhci->er_start ||
+ erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+ fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
+ fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ xhci->er_start, xhci->er_size);
+ xhci_die(xhci);
+ return;
+ }
+
+ dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
+ assert(dp_idx < xhci->er_size);
+
+ if ((xhci->er_ep_idx+1) % xhci->er_size == dp_idx) {
+ DPRINTF("xhci_event(): ER full, queueing\n");
+#ifndef ER_FULL_HACK
+ XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
+ xhci_write_event(xhci, &full);
+#endif
+ xhci->er_full = 1;
+ if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+ fprintf(stderr, "xhci: event queue full, dropping event!\n");
+ return;
+ }
+ xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
+ if (xhci->ev_buffer_put == EV_QUEUE) {
+ xhci->ev_buffer_put = 0;
+ }
+ } else {
+ xhci_write_event(xhci, event);
+ }
+
+ xhci->erdp_low |= ERDP_EHB;
+ xhci->iman |= IMAN_IP;
+ xhci->usbsts |= USBSTS_EINT;
+
+ xhci_irq_update(xhci);
+}
+
+static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
+ target_phys_addr_t base)
+{
+ ring->base = base;
+ ring->dequeue = base;
+ ring->ccs = 1;
+}
+
+static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
+ target_phys_addr_t *addr)
+{
+ while (1) {
+ TRBType type;
+ cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE);
+ trb->addr = ring->dequeue;
+ trb->ccs = ring->ccs;
+ le64_to_cpus(&trb->parameter);
+ le32_to_cpus(&trb->status);
+ le32_to_cpus(&trb->control);
+
+ DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
+ "%016" PRIx64 " %08x %08x\n",
+ ring->dequeue, trb->parameter, trb->status, trb->control);
+
+ if ((trb->control & TRB_C) != ring->ccs) {
+ return 0;
+ }
+
+ type = TRB_TYPE(*trb);
+
+ if (type != TR_LINK) {
+ if (addr) {
+ *addr = ring->dequeue;
+ }
+ ring->dequeue += TRB_SIZE;
+ return type;
+ } else {
+ ring->dequeue = xhci_mask64(trb->parameter);
+ if (trb->control & TRB_LK_TC) {
+ ring->ccs = !ring->ccs;
+ }
+ }
+ }
+}
+
+static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
+{
+ XHCITRB trb;
+ int length = 0;
+ target_phys_addr_t dequeue = ring->dequeue;
+ bool ccs = ring->ccs;
+ /* hack to bundle together the two/three TDs that make a setup transfer */
+ bool control_td_set = 0;
+
+ while (1) {
+ TRBType type;
+ cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE);
+ le64_to_cpus(&trb.parameter);
+ le32_to_cpus(&trb.status);
+ le32_to_cpus(&trb.control);
+
+ DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: "
+ "%016" PRIx64 " %08x %08x\n",
+ dequeue, trb.parameter, trb.status, trb.control);
+
+ if ((trb.control & TRB_C) != ccs) {
+ return -length;
+ }
+
+ type = TRB_TYPE(trb);
+
+ if (type == TR_LINK) {
+ dequeue = xhci_mask64(trb.parameter);
+ if (trb.control & TRB_LK_TC) {
+ ccs = !ccs;
+ }
+ continue;
+ }
+
+ length += 1;
+ dequeue += TRB_SIZE;
+
+ if (type == TR_SETUP) {
+ control_td_set = 1;
+ } else if (type == TR_STATUS) {
+ control_td_set = 0;
+ }
+
+ if (!control_td_set && !(trb.control & TRB_TR_CH)) {
+ return length;
+ }
+ }
+}
+
+static void xhci_er_reset(XHCIState *xhci)
+{
+ XHCIEvRingSeg seg;
+
+ /* cache the (sole) event ring segment location */
+ if (xhci->erstsz != 1) {
+ fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", xhci->erstsz);
+ xhci_die(xhci);
+ return;
+ }
+ target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
+ cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg));
+ le32_to_cpus(&seg.addr_low);
+ le32_to_cpus(&seg.addr_high);
+ le32_to_cpus(&seg.size);
+ if (seg.size < 16 || seg.size > 4096) {
+ fprintf(stderr, "xhci: invalid value for segment size: %d\n", seg.size);
+ xhci_die(xhci);
+ return;
+ }
+ xhci->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
+ xhci->er_size = seg.size;
+
+ xhci->er_ep_idx = 0;
+ xhci->er_pcs = 1;
+ xhci->er_full = 0;
+
+ DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n",
+ xhci->er_start, xhci->er_size);
+}
+
+static void xhci_run(XHCIState *xhci)
+{
+ DPRINTF("xhci_run()\n");
+
+ xhci->usbsts &= ~USBSTS_HCH;
+}
+
+static void xhci_stop(XHCIState *xhci)
+{
+ DPRINTF("xhci_stop()\n");
+ xhci->usbsts |= USBSTS_HCH;
+ xhci->crcr_low &= ~CRCR_CRR;
+}
+
+static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
+ uint32_t state)
+{
+ uint32_t ctx[5];
+ if (epctx->state == state) {
+ return;
+ }
+
+ cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ ctx[0] &= ~EP_STATE_MASK;
+ ctx[0] |= state;
+ ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
+ ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
+ DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n",
+ epctx->pctx, state, ctx[3], ctx[2]);
+ cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ epctx->state = state;
+}
+
+static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid, target_phys_addr_t pctx,
+ uint32_t *ctx)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+ target_phys_addr_t dequeue;
+ int i;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ assert(epid >= 1 && epid <= 31);
+
+ DPRINTF("xhci_enable_ep(%d, %d)\n", slotid, epid);
+
+ slot = &xhci->slots[slotid-1];
+ if (slot->eps[epid-1]) {
+ fprintf(stderr, "xhci: slot %d ep %d already enabled!\n", slotid, epid);
+ return CC_TRB_ERROR;
+ }
+
+ epctx = g_malloc(sizeof(XHCIEPContext));
+ memset(epctx, 0, sizeof(XHCIEPContext));
+
+ slot->eps[epid-1] = epctx;
+
+ dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]);
+ xhci_ring_init(xhci, &epctx->ring, dequeue);
+ epctx->ring.ccs = ctx[2] & 1;
+
+ epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK;
+ DPRINTF("xhci: endpoint %d.%d type is %d\n", epid/2, epid%2, epctx->type);
+ epctx->pctx = pctx;
+ epctx->max_psize = ctx[1]>>16;
+ epctx->max_psize *= 1+((ctx[1]>>8)&0xff);
+ epctx->has_bg = false;
+ if (epctx->type == ET_ISO_IN) {
+ epctx->has_bg = true;
+ }
+ DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n",
+ epid/2, epid%2, epctx->max_psize);
+ for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
+ usb_packet_init(&epctx->transfers[i].packet);
+ }
+
+ epctx->state = EP_RUNNING;
+ ctx[0] &= ~EP_STATE_MASK;
+ ctx[0] |= EP_RUNNING;
+
+ return CC_SUCCESS;
+}
+
+static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+ int i, xferi, killed = 0;
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ assert(epid >= 1 && epid <= 31);
+
+ DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid);
+
+ slot = &xhci->slots[slotid-1];
+
+ if (!slot->eps[epid-1]) {
+ return 0;
+ }
+
+ epctx = slot->eps[epid-1];
+
+ xferi = epctx->next_xfer;
+ for (i = 0; i < TD_QUEUE; i++) {
+ XHCITransfer *t = &epctx->transfers[xferi];
+ if (t->running) {
+ t->cancelled = 1;
+ /* libusb_cancel_transfer(t->usbxfer) */
+ DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
+ killed++;
+ }
+ if (t->backgrounded) {
+ t->backgrounded = 0;
+ }
+ if (t->trbs) {
+ g_free(t->trbs);
+ }
+ if (t->data) {
+ g_free(t->data);
+ }
+
+ t->trbs = NULL;
+ t->data = NULL;
+ t->trb_count = t->trb_alloced = 0;
+ t->data_length = t->data_alloced = 0;
+ xferi = (xferi + 1) % TD_QUEUE;
+ }
+ if (epctx->has_bg) {
+ xferi = epctx->next_bg;
+ for (i = 0; i < BG_XFERS; i++) {
+ XHCITransfer *t = &epctx->bg_transfers[xferi];
+ if (t->running) {
+ t->cancelled = 1;
+ /* libusb_cancel_transfer(t->usbxfer); */
+ DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
+ killed++;
+ }
+ if (t->data) {
+ g_free(t->data);
+ }
+
+ t->data = NULL;
+ xferi = (xferi + 1) % BG_XFERS;
+ }
+ }
+ return killed;
+}
+
+static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ assert(epid >= 1 && epid <= 31);
+
+ DPRINTF("xhci_disable_ep(%d, %d)\n", slotid, epid);
+
+ slot = &xhci->slots[slotid-1];
+
+ if (!slot->eps[epid-1]) {
+ DPRINTF("xhci: slot %d ep %d already disabled\n", slotid, epid);
+ return CC_SUCCESS;
+ }
+
+ xhci_ep_nuke_xfers(xhci, slotid, epid);
+
+ epctx = slot->eps[epid-1];
+
+ xhci_set_ep_state(xhci, epctx, EP_DISABLED);
+
+ g_free(epctx);
+ slot->eps[epid-1] = NULL;
+
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+
+ DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+
+ if (epid < 1 || epid > 31) {
+ fprintf(stderr, "xhci: bad ep %d\n", epid);
+ return CC_TRB_ERROR;
+ }
+
+ slot = &xhci->slots[slotid-1];
+
+ if (!slot->eps[epid-1]) {
+ DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+ return CC_EP_NOT_ENABLED_ERROR;
+ }
+
+ if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+ fprintf(stderr, "xhci: FIXME: endpoint stopped w/ xfers running, "
+ "data might be lost\n");
+ }
+
+ epctx = slot->eps[epid-1];
+
+ xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+ USBDevice *dev;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+
+ DPRINTF("xhci_reset_ep(%d, %d)\n", slotid, epid);
+
+ if (epid < 1 || epid > 31) {
+ fprintf(stderr, "xhci: bad ep %d\n", epid);
+ return CC_TRB_ERROR;
+ }
+
+ slot = &xhci->slots[slotid-1];
+
+ if (!slot->eps[epid-1]) {
+ DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+ return CC_EP_NOT_ENABLED_ERROR;
+ }
+
+ epctx = slot->eps[epid-1];
+
+ if (epctx->state != EP_HALTED) {
+ fprintf(stderr, "xhci: reset EP while EP %d not halted (%d)\n",
+ epid, epctx->state);
+ return CC_CONTEXT_STATE_ERROR;
+ }
+
+ if (xhci_ep_nuke_xfers(xhci, slotid, epid) > 0) {
+ fprintf(stderr, "xhci: FIXME: endpoint reset w/ xfers running, "
+ "data might be lost\n");
+ }
+
+ uint8_t ep = epid>>1;
+
+ if (epid & 1) {
+ ep |= 0x80;
+ }
+
+ dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev;
+ if (!dev) {
+ return CC_USB_TRANSACTION_ERROR;
+ }
+
+ xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
+ unsigned int epid, uint64_t pdequeue)
+{
+ XHCISlot *slot;
+ XHCIEPContext *epctx;
+ target_phys_addr_t dequeue;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+
+ if (epid < 1 || epid > 31) {
+ fprintf(stderr, "xhci: bad ep %d\n", epid);
+ return CC_TRB_ERROR;
+ }
+
+ DPRINTF("xhci_set_ep_dequeue(%d, %d, %016"PRIx64")\n", slotid, epid, pdequeue);
+ dequeue = xhci_mask64(pdequeue);
+
+ slot = &xhci->slots[slotid-1];
+
+ if (!slot->eps[epid-1]) {
+ DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
+ return CC_EP_NOT_ENABLED_ERROR;
+ }
+
+ epctx = slot->eps[epid-1];
+
+
+ if (epctx->state != EP_STOPPED) {
+ fprintf(stderr, "xhci: set EP dequeue pointer while EP %d not stopped\n", epid);
+ return CC_CONTEXT_STATE_ERROR;
+ }
+
+ xhci_ring_init(xhci, &epctx->ring, dequeue & ~0xF);
+ epctx->ring.ccs = dequeue & 1;
+
+ xhci_set_ep_state(xhci, epctx, EP_STOPPED);
+
+ return CC_SUCCESS;
+}
+
+static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
+ unsigned int length, bool in_xfer, bool out_xfer,
+ bool report)
+{
+ int i;
+ uint32_t edtla = 0;
+ unsigned int transferred = 0;
+ unsigned int left = length;
+ bool reported = 0;
+ bool shortpkt = 0;
+ XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
+ XHCIState *xhci = xfer->xhci;
+
+ DPRINTF("xhci_xfer_data(len=%d, in_xfer=%d, out_xfer=%d, report=%d)\n",
+ length, in_xfer, out_xfer, report);
+
+ assert(!(in_xfer && out_xfer));
+
+ for (i = 0; i < xfer->trb_count; i++) {
+ XHCITRB *trb = &xfer->trbs[i];
+ target_phys_addr_t addr;
+ unsigned int chunk = 0;
+
+ switch (TRB_TYPE(*trb)) {
+ case TR_DATA:
+ if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) {
+ fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n");
+ xhci_die(xhci);
+ return transferred;
+ }
+ /* fallthrough */
+ case TR_NORMAL:
+ case TR_ISOCH:
+ addr = xhci_mask64(trb->parameter);
+ chunk = trb->status & 0x1ffff;
+ if (chunk > left) {
+ chunk = left;
+ shortpkt = 1;
+ }
+ if (in_xfer || out_xfer) {
+ if (trb->control & TRB_TR_IDT) {
+ uint64_t idata;
+ if (chunk > 8 || in_xfer) {
+ fprintf(stderr, "xhci: invalid immediate data TRB\n");
+ xhci_die(xhci);
+ return transferred;
+ }
+ idata = le64_to_cpu(trb->parameter);
+ memcpy(data, &idata, chunk);
+ } else {
+ DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
+ TARGET_FMT_plx "\n", in_xfer, chunk, addr);
+ if (in_xfer) {
+ cpu_physical_memory_write(addr, data, chunk);
+ } else {
+ cpu_physical_memory_read(addr, data, chunk);
+ }
+#ifdef DEBUG_DATA
+ unsigned int count = chunk;
+ int i;
+ if (count > 16) {
+ count = 16;
+ }
+ DPRINTF(" ::");
+ for (i = 0; i < count; i++) {
+ DPRINTF(" %02x", data[i]);
+ }
+ DPRINTF("\n");
+#endif
+ }
+ }
+ left -= chunk;
+ data += chunk;
+ edtla += chunk;
+ transferred += chunk;
+ break;
+ case TR_STATUS:
+ reported = 0;
+ shortpkt = 0;
+ break;
+ }
+
+ if (report && !reported && (trb->control & TRB_TR_IOC ||
+ (shortpkt && (trb->control & TRB_TR_ISP)))) {
+ event.slotid = xfer->slotid;
+ event.epid = xfer->epid;
+ event.length = (trb->status & 0x1ffff) - chunk;
+ event.flags = 0;
+ event.ptr = trb->addr;
+ if (xfer->status == CC_SUCCESS) {
+ event.ccode = shortpkt ? CC_SHORT_PACKET : CC_SUCCESS;
+ } else {
+ event.ccode = xfer->status;
+ }
+ if (TRB_TYPE(*trb) == TR_EVDATA) {
+ event.ptr = trb->parameter;
+ event.flags |= TRB_EV_ED;
+ event.length = edtla & 0xffffff;
+ DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length);
+ edtla = 0;
+ }
+ xhci_event(xhci, &event);
+ reported = 1;
+ }
+ }
+ return transferred;
+}
+
+static void xhci_stall_ep(XHCITransfer *xfer)
+{
+ XHCIState *xhci = xfer->xhci;
+ XHCISlot *slot = &xhci->slots[xfer->slotid-1];
+ XHCIEPContext *epctx = slot->eps[xfer->epid-1];
+
+ epctx->ring.dequeue = xfer->trbs[0].addr;
+ epctx->ring.ccs = xfer->trbs[0].ccs;
+ xhci_set_ep_state(xhci, epctx, EP_HALTED);
+ DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid);
+ DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue);
+}
+
+static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
+ XHCIEPContext *epctx);
+
+static void xhci_bg_update(XHCIState *xhci, XHCIEPContext *epctx)
+{
+ if (epctx->bg_updating) {
+ return;
+ }
+ DPRINTF("xhci_bg_update(%p, %p)\n", xhci, epctx);
+ assert(epctx->has_bg);
+ DPRINTF("xhci: fg=%d bg=%d\n", epctx->comp_xfer, epctx->next_bg);
+ epctx->bg_updating = 1;
+ while (epctx->transfers[epctx->comp_xfer].backgrounded &&
+ epctx->bg_transfers[epctx->next_bg].complete) {
+ XHCITransfer *fg = &epctx->transfers[epctx->comp_xfer];
+ XHCITransfer *bg = &epctx->bg_transfers[epctx->next_bg];
+#if 0
+ DPRINTF("xhci: completing fg %d from bg %d.%d (stat: %d)\n",
+ epctx->comp_xfer, epctx->next_bg, bg->cur_pkt,
+ bg->usbxfer->iso_packet_desc[bg->cur_pkt].status
+ );
+#endif
+ assert(epctx->type == ET_ISO_IN);
+ assert(bg->iso_xfer);
+ assert(bg->in_xfer);
+ uint8_t *p = bg->data + bg->cur_pkt * bg->pktsize;
+#if 0
+ int len = bg->usbxfer->iso_packet_desc[bg->cur_pkt].actual_length;
+ fg->status = libusb_to_ccode(bg->usbxfer->iso_packet_desc[bg->cur_pkt].status);
+#else
+ int len = 0;
+ FIXME();
+#endif
+ fg->complete = 1;
+ fg->backgrounded = 0;
+
+ if (fg->status == CC_STALL_ERROR) {
+ xhci_stall_ep(fg);
+ }
+
+ xhci_xfer_data(fg, p, len, 1, 0, 1);
+
+ epctx->comp_xfer++;
+ if (epctx->comp_xfer == TD_QUEUE) {
+ epctx->comp_xfer = 0;
+ }
+ DPRINTF("next fg xfer: %d\n", epctx->comp_xfer);
+ bg->cur_pkt++;
+ if (bg->cur_pkt == bg->pkts) {
+ bg->complete = 0;
+ if (xhci_submit(xhci, bg, epctx) < 0) {
+ fprintf(stderr, "xhci: bg resubmit failed\n");
+ }
+ epctx->next_bg++;
+ if (epctx->next_bg == BG_XFERS) {
+ epctx->next_bg = 0;
+ }
+ DPRINTF("next bg xfer: %d\n", epctx->next_bg);
+
+ xhci_kick_ep(xhci, fg->slotid, fg->epid);
+ }
+ }
+ epctx->bg_updating = 0;
+}
+
+#if 0
+static void xhci_xfer_cb(struct libusb_transfer *transfer)
+{
+ XHCIState *xhci;
+ XHCITransfer *xfer;
+
+ xfer = (XHCITransfer *)transfer->user_data;
+ xhci = xfer->xhci;
+
+ DPRINTF("xhci_xfer_cb(slot=%d, ep=%d, status=%d)\n", xfer->slotid,
+ xfer->epid, transfer->status);
+
+ assert(xfer->slotid >= 1 && xfer->slotid <= MAXSLOTS);
+ assert(xfer->epid >= 1 && xfer->epid <= 31);
+
+ if (xfer->cancelled) {
+ DPRINTF("xhci: transfer cancelled, not reporting anything\n");
+ xfer->running = 0;
+ return;
+ }
+
+ XHCIEPContext *epctx;
+ XHCISlot *slot;
+ slot = &xhci->slots[xfer->slotid-1];
+ assert(slot->eps[xfer->epid-1]);
+ epctx = slot->eps[xfer->epid-1];
+
+ if (xfer->bg_xfer) {
+ DPRINTF("xhci: background transfer, updating\n");
+ xfer->complete = 1;
+ xfer->running = 0;
+ xhci_bg_update(xhci, epctx);
+ return;
+ }
+
+ if (xfer->iso_xfer) {
+ transfer->status = transfer->iso_packet_desc[0].status;
+ transfer->actual_length = transfer->iso_packet_desc[0].actual_length;
+ }
+
+ xfer->status = libusb_to_ccode(transfer->status);
+
+ xfer->complete = 1;
+ xfer->running = 0;
+
+ if (transfer->status == LIBUSB_TRANSFER_STALL)
+ xhci_stall_ep(xhci, epctx, xfer);
+
+ DPRINTF("xhci: transfer actual length = %d\n", transfer->actual_length);
+
+ if (xfer->in_xfer) {
+ if (xfer->epid == 1) {
+ xhci_xfer_data(xhci, xfer, xfer->data + 8,
+ transfer->actual_length, 1, 0, 1);
+ } else {
+ xhci_xfer_data(xhci, xfer, xfer->data,
+ transfer->actual_length, 1, 0, 1);
+ }
+ } else {
+ xhci_xfer_data(xhci, xfer, NULL, transfer->actual_length, 0, 0, 1);
+ }
+
+ xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+}
+
+static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
+ uint8_t bmRequestType, uint8_t bRequest,
+ uint16_t wValue, uint16_t wIndex, uint16_t wLength)
+{
+ uint16_t type_req = (bmRequestType << 8) | bRequest;
+
+ switch (type_req) {
+ case 0x0000 | USB_REQ_SET_CONFIGURATION:
+ DPRINTF("xhci: HLE switch configuration\n");
+ return xhci_switch_config(xhci, xfer->slotid, wValue) == 0;
+ case 0x0100 | USB_REQ_SET_INTERFACE:
+ DPRINTF("xhci: HLE set interface altsetting\n");
+ return xhci_set_iface_alt(xhci, xfer->slotid, wIndex, wValue) == 0;
+ case 0x0200 | USB_REQ_CLEAR_FEATURE:
+ if (wValue == 0) { // endpoint halt
+ DPRINTF("xhci: HLE clear halt\n");
+ return xhci_clear_halt(xhci, xfer->slotid, wIndex);
+ }
+ case 0x0000 | USB_REQ_SET_ADDRESS:
+ fprintf(stderr, "xhci: warn: illegal SET_ADDRESS request\n");
+ return 0;
+ default:
+ return 0;
+ }
+}
+#endif
+
+static int xhci_setup_packet(XHCITransfer *xfer, XHCIPort *port, int ep)
+{
+ usb_packet_setup(&xfer->packet,
+ xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT,
+ xfer->xhci->slots[xfer->slotid-1].devaddr,
+ ep & 0x7f);
+ usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
+ DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
+ xfer->packet.pid, xfer->packet.devaddr, xfer->packet.devep);
+ return 0;
+}
+
+static int xhci_complete_packet(XHCITransfer *xfer, int ret)
+{
+ if (ret == USB_RET_ASYNC) {
+ xfer->running = 1;
+ xfer->complete = 0;
+ xfer->cancelled = 0;
+ return 0;
+ } else {
+ xfer->running = 0;
+ xfer->complete = 1;
+ }
+
+ if (ret >= 0) {
+ xfer->status = CC_SUCCESS;
+ xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
+ return 0;
+ }
+
+ /* error */
+ switch (ret) {
+ case USB_RET_NODEV:
+ xfer->status = CC_USB_TRANSACTION_ERROR;
+ xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+ xhci_stall_ep(xfer);
+ break;
+ case USB_RET_STALL:
+ xfer->status = CC_STALL_ERROR;
+ xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+ xhci_stall_ep(xfer);
+ break;
+ default:
+ fprintf(stderr, "%s: FIXME: ret = %d\n", __FUNCTION__, ret);
+ FIXME();
+ }
+ return 0;
+}
+
+static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
+{
+ XHCITRB *trb_setup, *trb_status;
+ uint8_t bmRequestType, bRequest;
+ uint16_t wValue, wLength, wIndex;
+ XHCIPort *port;
+ USBDevice *dev;
+ int ret;
+
+ DPRINTF("xhci_fire_ctl_transfer(slot=%d)\n", xfer->slotid);
+
+ trb_setup = &xfer->trbs[0];
+ trb_status = &xfer->trbs[xfer->trb_count-1];
+
+ /* at most one Event Data TRB allowed after STATUS */
+ if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
+ trb_status--;
+ }
+
+ /* do some sanity checks */
+ if (TRB_TYPE(*trb_setup) != TR_SETUP) {
+ fprintf(stderr, "xhci: ep0 first TD not SETUP: %d\n",
+ TRB_TYPE(*trb_setup));
+ return -1;
+ }
+ if (TRB_TYPE(*trb_status) != TR_STATUS) {
+ fprintf(stderr, "xhci: ep0 last TD not STATUS: %d\n",
+ TRB_TYPE(*trb_status));
+ return -1;
+ }
+ if (!(trb_setup->control & TRB_TR_IDT)) {
+ fprintf(stderr, "xhci: Setup TRB doesn't have IDT set\n");
+ return -1;
+ }
+ if ((trb_setup->status & 0x1ffff) != 8) {
+ fprintf(stderr, "xhci: Setup TRB has bad length (%d)\n",
+ (trb_setup->status & 0x1ffff));
+ return -1;
+ }
+
+ bmRequestType = trb_setup->parameter;
+ bRequest = trb_setup->parameter >> 8;
+ wValue = trb_setup->parameter >> 16;
+ wIndex = trb_setup->parameter >> 32;
+ wLength = trb_setup->parameter >> 48;
+
+ if (xfer->data && xfer->data_alloced < wLength) {
+ xfer->data_alloced = 0;
+ g_free(xfer->data);
+ xfer->data = NULL;
+ }
+ if (!xfer->data) {
+ DPRINTF("xhci: alloc %d bytes data\n", wLength);
+ xfer->data = g_malloc(wLength+1);
+ xfer->data_alloced = wLength;
+ }
+ xfer->data_length = wLength;
+
+ port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
+ dev = port->port.dev;
+ if (!dev) {
+ fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
+ xhci->slots[xfer->slotid-1].port);
+ return -1;
+ }
+
+ xfer->in_xfer = bmRequestType & USB_DIR_IN;
+ xfer->iso_xfer = false;
+
+ xhci_setup_packet(xfer, port, 0);
+ if (!xfer->in_xfer) {
+ xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
+ }
+ ret = usb_device_handle_control(dev, &xfer->packet,
+ (bmRequestType << 8) | bRequest,
+ wValue, wIndex, wLength, xfer->data);
+
+ xhci_complete_packet(xfer, ret);
+ if (!xfer->running) {
+ xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+ }
+ return 0;
+}
+
+static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
+{
+ XHCIPort *port;
+ USBDevice *dev;
+ int ret;
+
+ DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
+ uint8_t ep = xfer->epid>>1;
+
+ xfer->in_xfer = epctx->type>>2;
+ if (xfer->in_xfer) {
+ ep |= 0x80;
+ }
+
+ if (xfer->data && xfer->data_alloced < xfer->data_length) {
+ xfer->data_alloced = 0;
+ g_free(xfer->data);
+ xfer->data = NULL;
+ }
+ if (!xfer->data && xfer->data_length) {
+ DPRINTF("xhci: alloc %d bytes data\n", xfer->data_length);
+ xfer->data = g_malloc(xfer->data_length);
+ xfer->data_alloced = xfer->data_length;
+ }
+ if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
+ if (!xfer->bg_xfer) {
+ xfer->pkts = 1;
+ }
+ } else {
+ xfer->pkts = 0;
+ }
+
+ port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
+ dev = port->port.dev;
+ if (!dev) {
+ fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
+ xhci->slots[xfer->slotid-1].port);
+ return -1;
+ }
+
+ xhci_setup_packet(xfer, port, ep);
+
+ switch(epctx->type) {
+ case ET_INTR_OUT:
+ case ET_INTR_IN:
+ case ET_BULK_OUT:
+ case ET_BULK_IN:
+ break;
+ case ET_ISO_OUT:
+ case ET_ISO_IN:
+ FIXME();
+ break;
+ default:
+ fprintf(stderr, "xhci: unknown or unhandled EP type %d (ep %02x)\n",
+ epctx->type, ep);
+ return -1;
+ }
+
+ if (!xfer->in_xfer) {
+ xhci_xfer_data(xfer, xfer->data, xfer->data_length, 0, 1, 0);
+ }
+ ret = usb_handle_packet(dev, &xfer->packet);
+
+ xhci_complete_packet(xfer, ret);
+ if (!xfer->running) {
+ xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
+ }
+ return 0;
+}
+
+static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
+{
+ int i;
+ unsigned int length = 0;
+ XHCITRB *trb;
+
+ DPRINTF("xhci_fire_transfer(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
+
+ for (i = 0; i < xfer->trb_count; i++) {
+ trb = &xfer->trbs[i];
+ if (TRB_TYPE(*trb) == TR_NORMAL || TRB_TYPE(*trb) == TR_ISOCH) {
+ length += trb->status & 0x1ffff;
+ }
+ }
+ DPRINTF("xhci: total TD length=%d\n", length);
+
+ if (!epctx->has_bg) {
+ xfer->data_length = length;
+ xfer->backgrounded = 0;
+ return xhci_submit(xhci, xfer, epctx);
+ } else {
+ if (!epctx->bg_running) {
+ for (i = 0; i < BG_XFERS; i++) {
+ XHCITransfer *t = &epctx->bg_transfers[i];
+ t->xhci = xhci;
+ t->epid = xfer->epid;
+ t->slotid = xfer->slotid;
+ t->pkts = BG_PKTS;
+ t->pktsize = epctx->max_psize;
+ t->data_length = t->pkts * t->pktsize;
+ t->bg_xfer = 1;
+ if (xhci_submit(xhci, t, epctx) < 0) {
+ fprintf(stderr, "xhci: bg submit failed\n");
+ return -1;
+ }
+ }
+ epctx->bg_running = 1;
+ }
+ xfer->backgrounded = 1;
+ xhci_bg_update(xhci, epctx);
+ return 0;
+ }
+}
+
+static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
+{
+ XHCIEPContext *epctx;
+ int length;
+ int i;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ assert(epid >= 1 && epid <= 31);
+ DPRINTF("xhci_kick_ep(%d, %d)\n", slotid, epid);
+
+ if (!xhci->slots[slotid-1].enabled) {
+ fprintf(stderr, "xhci: xhci_kick_ep for disabled slot %d\n", slotid);
+ return;
+ }
+ epctx = xhci->slots[slotid-1].eps[epid-1];
+ if (!epctx) {
+ fprintf(stderr, "xhci: xhci_kick_ep for disabled endpoint %d,%d\n",
+ epid, slotid);
+ return;
+ }
+
+ if (epctx->state == EP_HALTED) {
+ DPRINTF("xhci: ep halted, not running schedule\n");
+ return;
+ }
+
+ xhci_set_ep_state(xhci, epctx, EP_RUNNING);
+
+ while (1) {
+ XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
+ if (xfer->running || xfer->backgrounded) {
+ DPRINTF("xhci: ep is busy\n");
+ break;
+ }
+ length = xhci_ring_chain_length(xhci, &epctx->ring);
+ if (length < 0) {
+ DPRINTF("xhci: incomplete TD (%d TRBs)\n", -length);
+ break;
+ } else if (length == 0) {
+ break;
+ }
+ DPRINTF("xhci: fetching %d-TRB TD\n", length);
+ if (xfer->trbs && xfer->trb_alloced < length) {
+ xfer->trb_count = 0;
+ xfer->trb_alloced = 0;
+ g_free(xfer->trbs);
+ xfer->trbs = NULL;
+ }
+ if (!xfer->trbs) {
+ xfer->trbs = g_malloc(sizeof(XHCITRB) * length);
+ xfer->trb_alloced = length;
+ }
+ xfer->trb_count = length;
+
+ for (i = 0; i < length; i++) {
+ assert(xhci_ring_fetch(xhci, &epctx->ring, &xfer->trbs[i], NULL));
+ }
+ xfer->xhci = xhci;
+ xfer->epid = epid;
+ xfer->slotid = slotid;
+
+ if (epid == 1) {
+ if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) {
+ epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+ } else {
+ fprintf(stderr, "xhci: error firing CTL transfer\n");
+ }
+ } else {
+ if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) {
+ epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+ } else {
+ fprintf(stderr, "xhci: error firing data transfer\n");
+ }
+ }
+
+ /*
+ * Qemu usb can't handle multiple in-flight xfers.
+ * Also xfers might be finished here already,
+ * possibly with an error. Stop here for now.
+ */
+ break;
+ }
+}
+
+static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
+{
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_enable_slot(%d)\n", slotid);
+ xhci->slots[slotid-1].enabled = 1;
+ xhci->slots[slotid-1].port = 0;
+ memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31);
+
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
+{
+ int i;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_disable_slot(%d)\n", slotid);
+
+ for (i = 1; i <= 31; i++) {
+ if (xhci->slots[slotid-1].eps[i-1]) {
+ xhci_disable_ep(xhci, slotid, i);
+ }
+ }
+
+ xhci->slots[slotid-1].enabled = 0;
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
+ uint64_t pictx, bool bsr)
+{
+ XHCISlot *slot;
+ USBDevice *dev;
+ target_phys_addr_t ictx, octx, dcbaap;
+ uint64_t poctx;
+ uint32_t ictl_ctx[2];
+ uint32_t slot_ctx[4];
+ uint32_t ep0_ctx[5];
+ unsigned int port;
+ int i;
+ TRBCCode res;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_address_slot(%d)\n", slotid);
+
+ dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
+ cpu_physical_memory_read(dcbaap + 8*slotid,
+ (uint8_t *) &poctx, sizeof(poctx));
+ ictx = xhci_mask64(pictx);
+ octx = xhci_mask64(le64_to_cpu(poctx));
+
+ DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+ DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+ cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+ if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
+ fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+ ictl_ctx[0], ictl_ctx[1]);
+ return CC_TRB_ERROR;
+ }
+
+ cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+ DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+ DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
+ ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+ port = (slot_ctx[1]>>16) & 0xFF;
+ dev = xhci->ports[port-1].port.dev;
+
+ if (port < 1 || port > MAXPORTS) {
+ fprintf(stderr, "xhci: bad port %d\n", port);
+ return CC_TRB_ERROR;
+ } else if (!dev) {
+ fprintf(stderr, "xhci: port %d not connected\n", port);
+ return CC_USB_TRANSACTION_ERROR;
+ }
+
+ for (i = 0; i < MAXSLOTS; i++) {
+ if (xhci->slots[i].port == port) {
+ fprintf(stderr, "xhci: port %d already assigned to slot %d\n",
+ port, i+1);
+ return CC_TRB_ERROR;
+ }
+ }
+
+ slot = &xhci->slots[slotid-1];
+ slot->port = port;
+ slot->ctx = octx;
+
+ if (bsr) {
+ slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
+ } else {
+ slot->devaddr = xhci->devaddr++;
+ slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr;
+ DPRINTF("xhci: device address is %d\n", slot->devaddr);
+ usb_device_handle_control(dev, NULL,
+ DeviceOutRequest | USB_REQ_SET_ADDRESS,
+ slot->devaddr, 0, 0, NULL);
+ }
+
+ res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);
+
+ DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+ DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
+ ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+ cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+ return res;
+}
+
+
+static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
+ uint64_t pictx, bool dc)
+{
+ target_phys_addr_t ictx, octx;
+ uint32_t ictl_ctx[2];
+ uint32_t slot_ctx[4];
+ uint32_t islot_ctx[4];
+ uint32_t ep_ctx[5];
+ int i;
+ TRBCCode res;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_configure_slot(%d)\n", slotid);
+
+ ictx = xhci_mask64(pictx);
+ octx = xhci->slots[slotid-1].ctx;
+
+ DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+ DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+ if (dc) {
+ for (i = 2; i <= 31; i++) {
+ if (xhci->slots[slotid-1].eps[i-1]) {
+ xhci_disable_ep(xhci, slotid, i);
+ }
+ }
+
+ cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+ slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
+ DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+ cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+ return CC_SUCCESS;
+ }
+
+ cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+ if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
+ fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+ ictl_ctx[0], ictl_ctx[1]);
+ return CC_TRB_ERROR;
+ }
+
+ cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx));
+ cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+ if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
+ fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
+ return CC_CONTEXT_STATE_ERROR;
+ }
+
+ for (i = 2; i <= 31; i++) {
+ if (ictl_ctx[0] & (1<<i)) {
+ xhci_disable_ep(xhci, slotid, i);
+ }
+ if (ictl_ctx[1] & (1<<i)) {
+ cpu_physical_memory_read(ictx+32+(32*i),
+ (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
+ i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
+ ep_ctx[3], ep_ctx[4]);
+ xhci_disable_ep(xhci, slotid, i);
+ res = xhci_enable_ep(xhci, slotid, i, octx+(32*i), ep_ctx);
+ if (res != CC_SUCCESS) {
+ return res;
+ }
+ DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
+ i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
+ ep_ctx[3], ep_ctx[4]);
+ cpu_physical_memory_write(octx+(32*i),
+ (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ }
+ }
+
+ slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+ slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
+ slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
+ slot_ctx[0] |= islot_ctx[0] & (SLOT_CONTEXT_ENTRIES_MASK <<
+ SLOT_CONTEXT_ENTRIES_SHIFT);
+ DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+ cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+ return CC_SUCCESS;
+}
+
+
+static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
+ uint64_t pictx)
+{
+ target_phys_addr_t ictx, octx;
+ uint32_t ictl_ctx[2];
+ uint32_t iep0_ctx[5];
+ uint32_t ep0_ctx[5];
+ uint32_t islot_ctx[4];
+ uint32_t slot_ctx[4];
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
+
+ ictx = xhci_mask64(pictx);
+ octx = xhci->slots[slotid-1].ctx;
+
+ DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
+ DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+ cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+
+ if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
+ fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
+ ictl_ctx[0], ictl_ctx[1]);
+ return CC_TRB_ERROR;
+ }
+
+ if (ictl_ctx[1] & 0x1) {
+ cpu_physical_memory_read(ictx+32,
+ (uint8_t *) islot_ctx, sizeof(islot_ctx));
+
+ DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
+ islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
+
+ cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+ slot_ctx[1] &= ~0xFFFF; /* max exit latency */
+ slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
+ slot_ctx[2] &= ~0xFF00000; /* interrupter target */
+ slot_ctx[2] |= islot_ctx[2] & 0xFF000000;
+
+ DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+
+ cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ }
+
+ if (ictl_ctx[1] & 0x2) {
+ cpu_physical_memory_read(ictx+64,
+ (uint8_t *) iep0_ctx, sizeof(iep0_ctx));
+
+ DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
+ iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
+ iep0_ctx[3], iep0_ctx[4]);
+
+ cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+
+ ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
+ ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
+
+ DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
+ ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
+
+ cpu_physical_memory_write(octx+32,
+ (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ }
+
+ return CC_SUCCESS;
+}
+
+static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
+{
+ uint32_t slot_ctx[4];
+ target_phys_addr_t octx;
+ int i;
+
+ assert(slotid >= 1 && slotid <= MAXSLOTS);
+ DPRINTF("xhci_reset_slot(%d)\n", slotid);
+
+ octx = xhci->slots[slotid-1].ctx;
+
+ DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+
+ for (i = 2; i <= 31; i++) {
+ if (xhci->slots[slotid-1].eps[i-1]) {
+ xhci_disable_ep(xhci, slotid, i);
+ }
+ }
+
+ cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
+ slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
+ DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
+ slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
+ cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+
+ return CC_SUCCESS;
+}
+
+static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *trb)
+{
+ unsigned int slotid;
+ slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK;
+ if (slotid < 1 || slotid > MAXSLOTS) {
+ fprintf(stderr, "xhci: bad slot id %d\n", slotid);
+ event->ccode = CC_TRB_ERROR;
+ return 0;
+ } else if (!xhci->slots[slotid-1].enabled) {
+ fprintf(stderr, "xhci: slot id %d not enabled\n", slotid);
+ event->ccode = CC_SLOT_NOT_ENABLED_ERROR;
+ return 0;
+ }
+ return slotid;
+}
+
+static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
+{
+ target_phys_addr_t ctx;
+ uint8_t bw_ctx[MAXPORTS+1];
+
+ DPRINTF("xhci_get_port_bandwidth()\n");
+
+ ctx = xhci_mask64(pctx);
+
+ DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx);
+
+ /* TODO: actually implement real values here */
+ bw_ctx[0] = 0;
+ memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
+ cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx));
+
+ return CC_SUCCESS;
+}
+
+static uint32_t rotl(uint32_t v, unsigned count)
+{
+ count &= 31;
+ return (v << count) | (v >> (32 - count));
+}
+
+
+static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo)
+{
+ uint32_t val;
+ val = rotl(lo - 0x49434878, 32 - ((hi>>8) & 0x1F));
+ val += rotl(lo + 0x49434878, hi & 0x1F);
+ val -= rotl(hi ^ 0x49434878, (lo >> 16) & 0x1F);
+ return ~val;
+}
+
+static void xhci_via_challenge(uint64_t addr)
+{
+ uint32_t buf[8];
+ uint32_t obuf[8];
+ target_phys_addr_t paddr = xhci_mask64(addr);
+
+ cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32);
+
+ memcpy(obuf, buf, sizeof(obuf));
+
+ if ((buf[0] & 0xff) == 2) {
+ obuf[0] = 0x49932000 + 0x54dc200 * buf[2] + 0x7429b578 * buf[3];
+ obuf[0] |= (buf[2] * buf[3]) & 0xff;
+ obuf[1] = 0x0132bb37 + 0xe89 * buf[2] + 0xf09 * buf[3];
+ obuf[2] = 0x0066c2e9 + 0x2091 * buf[2] + 0x19bd * buf[3];
+ obuf[3] = 0xd5281342 + 0x2cc9691 * buf[2] + 0x2367662 * buf[3];
+ obuf[4] = 0x0123c75c + 0x1595 * buf[2] + 0x19ec * buf[3];
+ obuf[5] = 0x00f695de + 0x26fd * buf[2] + 0x3e9 * buf[3];
+ obuf[6] = obuf[2] ^ obuf[3] ^ 0x29472956;
+ obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
+ }
+
+ cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32);
+}
+
+static void xhci_process_commands(XHCIState *xhci)
+{
+ XHCITRB trb;
+ TRBType type;
+ XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
+ target_phys_addr_t addr;
+ unsigned int i, slotid = 0;
+
+ DPRINTF("xhci_process_commands()\n");
+ if (!xhci_running(xhci)) {
+ DPRINTF("xhci_process_commands() called while xHC stopped or paused\n");
+ return;
+ }
+
+ xhci->crcr_low |= CRCR_CRR;
+
+ while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) {
+ event.ptr = addr;
+ switch (type) {
+ case CR_ENABLE_SLOT:
+ for (i = 0; i < MAXSLOTS; i++) {
+ if (!xhci->slots[i].enabled) {
+ break;
+ }
+ }
+ if (i >= MAXSLOTS) {
+ fprintf(stderr, "xhci: no device slots available\n");
+ event.ccode = CC_NO_SLOTS_ERROR;
+ } else {
+ slotid = i+1;
+ event.ccode = xhci_enable_slot(xhci, slotid);
+ }
+ break;
+ case CR_DISABLE_SLOT:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ event.ccode = xhci_disable_slot(xhci, slotid);
+ }
+ break;
+ case CR_ADDRESS_DEVICE:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ event.ccode = xhci_address_slot(xhci, slotid, trb.parameter,
+ trb.control & TRB_CR_BSR);
+ }
+ break;
+ case CR_CONFIGURE_ENDPOINT:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ event.ccode = xhci_configure_slot(xhci, slotid, trb.parameter,
+ trb.control & TRB_CR_DC);
+ }
+ break;
+ case CR_EVALUATE_CONTEXT:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ event.ccode = xhci_evaluate_slot(xhci, slotid, trb.parameter);
+ }
+ break;
+ case CR_STOP_ENDPOINT:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+ & TRB_CR_EPID_MASK;
+ event.ccode = xhci_stop_ep(xhci, slotid, epid);
+ }
+ break;
+ case CR_RESET_ENDPOINT:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+ & TRB_CR_EPID_MASK;
+ event.ccode = xhci_reset_ep(xhci, slotid, epid);
+ }
+ break;
+ case CR_SET_TR_DEQUEUE:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
+ & TRB_CR_EPID_MASK;
+ event.ccode = xhci_set_ep_dequeue(xhci, slotid, epid,
+ trb.parameter);
+ }
+ break;
+ case CR_RESET_DEVICE:
+ slotid = xhci_get_slot(xhci, &event, &trb);
+ if (slotid) {
+ event.ccode = xhci_reset_slot(xhci, slotid);
+ }
+ break;
+ case CR_GET_PORT_BANDWIDTH:
+ event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
+ break;
+ case CR_VENDOR_VIA_CHALLENGE_RESPONSE:
+ xhci_via_challenge(trb.parameter);
+ break;
+ case CR_VENDOR_NEC_FIRMWARE_REVISION:
+ event.type = 48; /* NEC reply */
+ event.length = 0x3025;
+ break;
+ case CR_VENDOR_NEC_CHALLENGE_RESPONSE:
+ {
+ uint32_t chi = trb.parameter >> 32;
+ uint32_t clo = trb.parameter;
+ uint32_t val = xhci_nec_challenge(chi, clo);
+ event.length = val & 0xFFFF;
+ event.epid = val >> 16;
+ slotid = val >> 24;
+ event.type = 48; /* NEC reply */
+ }
+ break;
+ default:
+ fprintf(stderr, "xhci: unimplemented command %d\n", type);
+ event.ccode = CC_TRB_ERROR;
+ break;
+ }
+ event.slotid = slotid;
+ xhci_event(xhci, &event);
+ }
+}
+
+static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
+{
+ int nr = port->port.index + 1;
+
+ port->portsc = PORTSC_PP;
+ if (port->port.dev && !is_detach) {
+ port->portsc |= PORTSC_CCS;
+ switch (port->port.dev->speed) {
+ case USB_SPEED_LOW:
+ port->portsc |= PORTSC_SPEED_LOW;
+ break;
+ case USB_SPEED_FULL:
+ port->portsc |= PORTSC_SPEED_FULL;
+ break;
+ case USB_SPEED_HIGH:
+ port->portsc |= PORTSC_SPEED_HIGH;
+ break;
+ }
+ }
+
+ if (xhci_running(xhci)) {
+ port->portsc |= PORTSC_CSC;
+ XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+ xhci_event(xhci, &ev);
+ DPRINTF("xhci: port change event for port %d\n", nr);
+ }
+}
+
+static void xhci_reset(void *opaque)
+{
+ XHCIState *xhci = opaque;
+ int i;
+
+ DPRINTF("xhci: full reset\n");
+ if (!(xhci->usbsts & USBSTS_HCH)) {
+ fprintf(stderr, "xhci: reset while running!\n");
+ }
+
+ xhci->usbcmd = 0;
+ xhci->usbsts = USBSTS_HCH;
+ xhci->dnctrl = 0;
+ xhci->crcr_low = 0;
+ xhci->crcr_high = 0;
+ xhci->dcbaap_low = 0;
+ xhci->dcbaap_high = 0;
+ xhci->config = 0;
+ xhci->devaddr = 2;
+
+ for (i = 0; i < MAXSLOTS; i++) {
+ xhci_disable_slot(xhci, i+1);
+ }
+
+ for (i = 0; i < MAXPORTS; i++) {
+ xhci_update_port(xhci, xhci->ports + i, 0);
+ }
+
+ xhci->mfindex = 0;
+ xhci->iman = 0;
+ xhci->imod = 0;
+ xhci->erstsz = 0;
+ xhci->erstba_low = 0;
+ xhci->erstba_high = 0;
+ xhci->erdp_low = 0;
+ xhci->erdp_high = 0;
+
+ xhci->er_ep_idx = 0;
+ xhci->er_pcs = 1;
+ xhci->er_full = 0;
+ xhci->ev_buffer_put = 0;
+ xhci->ev_buffer_get = 0;
+}
+
+static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
+{
+ DPRINTF("xhci_cap_read(0x%x)\n", reg);
+
+ switch (reg) {
+ case 0x00: /* HCIVERSION, CAPLENGTH */
+ return 0x01000000 | LEN_CAP;
+ case 0x04: /* HCSPARAMS 1 */
+ return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+ case 0x08: /* HCSPARAMS 2 */
+ return 0x0000000f;
+ case 0x0c: /* HCSPARAMS 3 */
+ return 0x00000000;
+ case 0x10: /* HCCPARAMS */
+#if TARGET_PHYS_ADDR_BITS > 32
+ return 0x00081001;
+#else
+ return 0x00081000;
+#endif
+ case 0x14: /* DBOFF */
+ return OFF_DOORBELL;
+ case 0x18: /* RTSOFF */
+ return OFF_RUNTIME;
+
+ /* extended capabilities */
+ case 0x20: /* Supported Protocol:00 */
+#if USB3_PORTS > 0
+ return 0x02000402; /* USB 2.0 */
+#else
+ return 0x02000002; /* USB 2.0 */
+#endif
+ case 0x24: /* Supported Protocol:04 */
+ return 0x20425455; /* "USB " */
+ case 0x28: /* Supported Protocol:08 */
+ return 0x00000001 | (USB2_PORTS<<8);
+ case 0x2c: /* Supported Protocol:0c */
+ return 0x00000000; /* reserved */
+#if USB3_PORTS > 0
+ case 0x30: /* Supported Protocol:00 */
+ return 0x03000002; /* USB 3.0 */
+ case 0x34: /* Supported Protocol:04 */
+ return 0x20425455; /* "USB " */
+ case 0x38: /* Supported Protocol:08 */
+ return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+ case 0x3c: /* Supported Protocol:0c */
+ return 0x00000000; /* reserved */
+#endif
+ default:
+ fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+ }
+ return 0;
+}
+
+static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
+{
+ uint32_t port = reg >> 4;
+ if (port >= MAXPORTS) {
+ fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
+ return 0;
+ }
+
+ switch (reg & 0xf) {
+ case 0x00: /* PORTSC */
+ return xhci->ports[port].portsc;
+ case 0x04: /* PORTPMSC */
+ case 0x08: /* PORTLI */
+ return 0;
+ case 0x0c: /* reserved */
+ default:
+ fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
+ port, reg);
+ return 0;
+ }
+}
+
+static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+ uint32_t port = reg >> 4;
+ uint32_t portsc;
+
+ if (port >= MAXPORTS) {
+ fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
+ return;
+ }
+
+ switch (reg & 0xf) {
+ case 0x00: /* PORTSC */
+ portsc = xhci->ports[port].portsc;
+ /* write-1-to-clear bits*/
+ portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC|
+ PORTSC_PRC|PORTSC_PLC|PORTSC_CEC));
+ if (val & PORTSC_LWS) {
+ /* overwrite PLS only when LWS=1 */
+ portsc &= ~(PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
+ portsc |= val & (PORTSC_PLS_MASK << PORTSC_PLS_SHIFT);
+ }
+ /* read/write bits */
+ portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE);
+ portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE));
+ /* write-1-to-start bits */
+ if (val & PORTSC_PR) {
+ DPRINTF("xhci: port %d reset\n", port);
+ if (xhci->ports[port].port.dev) {
+ usb_send_msg(xhci->ports[port].port.dev, USB_MSG_RESET);
+ }
+ portsc |= PORTSC_PRC | PORTSC_PED;
+ }
+ xhci->ports[port].portsc = portsc;
+ break;
+ case 0x04: /* PORTPMSC */
+ case 0x08: /* PORTLI */
+ default:
+ fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n",
+ port, reg);
+ }
+}
+
+static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
+{
+ DPRINTF("xhci_oper_read(0x%x)\n", reg);
+
+ if (reg >= 0x400) {
+ return xhci_port_read(xhci, reg - 0x400);
+ }
+
+ switch (reg) {
+ case 0x00: /* USBCMD */
+ return xhci->usbcmd;
+ case 0x04: /* USBSTS */
+ return xhci->usbsts;
+ case 0x08: /* PAGESIZE */
+ return 1; /* 4KiB */
+ case 0x14: /* DNCTRL */
+ return xhci->dnctrl;
+ case 0x18: /* CRCR low */
+ return xhci->crcr_low & ~0xe;
+ case 0x1c: /* CRCR high */
+ return xhci->crcr_high;
+ case 0x30: /* DCBAAP low */
+ return xhci->dcbaap_low;
+ case 0x34: /* DCBAAP high */
+ return xhci->dcbaap_high;
+ case 0x38: /* CONFIG */
+ return xhci->config;
+ default:
+ fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+ }
+ return 0;
+}
+
+static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+ DPRINTF("xhci_oper_write(0x%x, 0x%08x)\n", reg, val);
+
+ if (reg >= 0x400) {
+ xhci_port_write(xhci, reg - 0x400, val);
+ return;
+ }
+
+ switch (reg) {
+ case 0x00: /* USBCMD */
+ if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
+ xhci_run(xhci);
+ } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) {
+ xhci_stop(xhci);
+ }
+ xhci->usbcmd = val & 0xc0f;
+ if (val & USBCMD_HCRST) {
+ xhci_reset(xhci);
+ }
+ xhci_irq_update(xhci);
+ break;
+
+ case 0x04: /* USBSTS */
+ /* these bits are write-1-to-clear */
+ xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
+ xhci_irq_update(xhci);
+ break;
+
+ case 0x14: /* DNCTRL */
+ xhci->dnctrl = val & 0xffff;
+ break;
+ case 0x18: /* CRCR low */
+ xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR);
+ break;
+ case 0x1c: /* CRCR high */
+ xhci->crcr_high = val;
+ if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) {
+ XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED};
+ xhci->crcr_low &= ~CRCR_CRR;
+ xhci_event(xhci, &event);
+ DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
+ } else {
+ target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
+ xhci_ring_init(xhci, &xhci->cmd_ring, base);
+ }
+ xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
+ break;
+ case 0x30: /* DCBAAP low */
+ xhci->dcbaap_low = val & 0xffffffc0;
+ break;
+ case 0x34: /* DCBAAP high */
+ xhci->dcbaap_high = val;
+ break;
+ case 0x38: /* CONFIG */
+ xhci->config = val & 0xff;
+ break;
+ default:
+ fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+ }
+}
+
+static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
+{
+ DPRINTF("xhci_runtime_read(0x%x)\n", reg);
+
+ switch (reg) {
+ case 0x00: /* MFINDEX */
+ fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
+ return xhci->mfindex;
+ case 0x20: /* IMAN */
+ return xhci->iman;
+ case 0x24: /* IMOD */
+ return xhci->imod;
+ case 0x28: /* ERSTSZ */
+ return xhci->erstsz;
+ case 0x30: /* ERSTBA low */
+ return xhci->erstba_low;
+ case 0x34: /* ERSTBA high */
+ return xhci->erstba_high;
+ case 0x38: /* ERDP low */
+ return xhci->erdp_low;
+ case 0x3c: /* ERDP high */
+ return xhci->erdp_high;
+ default:
+ fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+ }
+ return 0;
+}
+
+static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+ DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
+
+ switch (reg) {
+ case 0x20: /* IMAN */
+ if (val & IMAN_IP) {
+ xhci->iman &= ~IMAN_IP;
+ }
+ xhci->iman &= ~IMAN_IE;
+ xhci->iman |= val & IMAN_IE;
+ xhci_irq_update(xhci);
+ break;
+ case 0x24: /* IMOD */
+ xhci->imod = val;
+ break;
+ case 0x28: /* ERSTSZ */
+ xhci->erstsz = val & 0xffff;
+ break;
+ case 0x30: /* ERSTBA low */
+ /* XXX NEC driver bug: it doesn't align this to 64 bytes
+ xhci->erstba_low = val & 0xffffffc0; */
+ xhci->erstba_low = val & 0xfffffff0;
+ break;
+ case 0x34: /* ERSTBA high */
+ xhci->erstba_high = val;
+ xhci_er_reset(xhci);
+ break;
+ case 0x38: /* ERDP low */
+ if (val & ERDP_EHB) {
+ xhci->erdp_low &= ~ERDP_EHB;
+ }
+ xhci->erdp_low = (val & ~ERDP_EHB) | (xhci->erdp_low & ERDP_EHB);
+ break;
+ case 0x3c: /* ERDP high */
+ xhci->erdp_high = val;
+ xhci_events_update(xhci);
+ break;
+ default:
+ fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+ }
+}
+
+static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
+{
+ DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
+ /* doorbells always read as 0 */
+ return 0;
+}
+
+static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+{
+ DPRINTF("xhci_doorbell_write(0x%x, 0x%08x)\n", reg, val);
+
+ if (!xhci_running(xhci)) {
+ fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
+ return;
+ }
+
+ reg >>= 2;
+
+ if (reg == 0) {
+ if (val == 0) {
+ xhci_process_commands(xhci);
+ } else {
+ fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", val);
+ }
+ } else {
+ if (reg > MAXSLOTS) {
+ fprintf(stderr, "xhci: bad doorbell %d\n", reg);
+ } else if (val > 31) {
+ fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", reg, val);
+ } else {
+ xhci_kick_ep(xhci, reg, val);
+ }
+ }
+}
+
+static uint64_t xhci_mem_read(void *ptr, target_phys_addr_t addr,
+ unsigned size)
+{
+ XHCIState *xhci = ptr;
+
+ /* Only aligned reads are allowed on xHCI */
+ if (addr & 3) {
+ fprintf(stderr, "xhci_mem_read: Mis-aligned read\n");
+ return 0;
+ }
+
+ if (addr < LEN_CAP) {
+ return xhci_cap_read(xhci, addr);
+ } else if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
+ return xhci_oper_read(xhci, addr - OFF_OPER);
+ } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
+ return xhci_runtime_read(xhci, addr - OFF_RUNTIME);
+ } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
+ return xhci_doorbell_read(xhci, addr - OFF_DOORBELL);
+ } else {
+ fprintf(stderr, "xhci_mem_read: Bad offset %x\n", (int)addr);
+ return 0;
+ }
+}
+
+static void xhci_mem_write(void *ptr, target_phys_addr_t addr,
+ uint64_t val, unsigned size)
+{
+ XHCIState *xhci = ptr;
+
+ /* Only aligned writes are allowed on xHCI */
+ if (addr & 3) {
+ fprintf(stderr, "xhci_mem_write: Mis-aligned write\n");
+ return;
+ }
+
+ if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
+ xhci_oper_write(xhci, addr - OFF_OPER, val);
+ } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
+ xhci_runtime_write(xhci, addr - OFF_RUNTIME, val);
+ } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
+ xhci_doorbell_write(xhci, addr - OFF_DOORBELL, val);
+ } else {
+ fprintf(stderr, "xhci_mem_write: Bad offset %x\n", (int)addr);
+ }
+}
+
+static const MemoryRegionOps xhci_mem_ops = {
+ .read = xhci_mem_read,
+ .write = xhci_mem_write,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void xhci_attach(USBPort *usbport)
+{
+ XHCIState *xhci = usbport->opaque;
+ XHCIPort *port = &xhci->ports[usbport->index];
+
+ xhci_update_port(xhci, port, 0);
+}
+
+static void xhci_detach(USBPort *usbport)
+{
+ XHCIState *xhci = usbport->opaque;
+ XHCIPort *port = &xhci->ports[usbport->index];
+
+ xhci_update_port(xhci, port, 1);
+}
+
+static void xhci_complete(USBPort *port, USBPacket *packet)
+{
+ XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
+
+ xhci_complete_packet(xfer, packet->result);
+ xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid);
+}
+
+static void xhci_child_detach(USBPort *port, USBDevice *child)
+{
+ FIXME();
+}
+
+static USBPortOps xhci_port_ops = {
+ .attach = xhci_attach,
+ .detach = xhci_detach,
+ .complete = xhci_complete,
+ .child_detach = xhci_child_detach,
+};
+
+static USBBusOps xhci_bus_ops = {
+};
+
+static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
+{
+ int i;
+
+ xhci->usbsts = USBSTS_HCH;
+
+ usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
+
+ for (i = 0; i < MAXPORTS; i++) {
+ memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
+ usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
+ &xhci_port_ops, USB_SPEED_MASK_HIGH);
+ }
+ for (i = 0; i < MAXSLOTS; i++) {
+ xhci->slots[i].enabled = 0;
+ }
+
+ qemu_register_reset(xhci_reset, xhci);
+}
+
+static int usb_xhci_initfn(struct PCIDevice *dev)
+{
+ int ret;
+
+ XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
+
+ xhci->pci_dev.config[PCI_CLASS_PROG] = 0x30; /* xHCI */
+ xhci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
+ xhci->pci_dev.config[PCI_CACHE_LINE_SIZE] = 0x10;
+ xhci->pci_dev.config[0x60] = 0x30; /* release number */
+
+ usb_xhci_init(xhci, &dev->qdev);
+
+ xhci->irq = xhci->pci_dev.irq[0];
+
+ memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci,
+ "xhci", LEN_REGS);
+ pci_register_bar(&xhci->pci_dev, 0,
+ PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
+ &xhci->mem);
+
+ ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
+ assert(ret >= 0);
+
+ if (xhci->msi) {
+ ret = msi_init(&xhci->pci_dev, 0x70, 1, true, false);
+ assert(ret >= 0);
+ }
+
+ return 0;
+}
+
+static void xhci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
+ int len)
+{
+ XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
+
+ pci_default_write_config(dev, addr, val, len);
+ if (xhci->msi) {
+ msi_write_config(dev, addr, val, len);
+ }
+}
+
+static const VMStateDescription vmstate_xhci = {
+ .name = "xhci",
+ .unmigratable = 1,
+};
+
+static Property xhci_properties[] = {
+ DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xhci_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_xhci;
+ dc->props = xhci_properties;
+ k->init = usb_xhci_initfn;
+ k->vendor_id = PCI_VENDOR_ID_NEC;
+ k->device_id = PCI_DEVICE_ID_NEC_UPD720200;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ k->revision = 0x03;
+ k->is_express = 1;
+ k->config_write = xhci_write_config;
+}
+
+static TypeInfo xhci_info = {
+ .name = "nec-usb-xhci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XHCIState),
+ .class_init = xhci_class_init,
+};
+
+static void xhci_register(void)
+{
+ type_register_static(&xhci_info);
+}
+device_init(xhci_register);
diff --git a/hw/usb.c b/hw/usb.c
index 2216efe077..c3ff5b7093 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -95,8 +95,8 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
if (s->setup_buf[0] & USB_DIR_IN) {
- ret = s->info->handle_control(s, p, request, value, index,
- s->setup_len, s->data_buf);
+ ret = usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
if (ret == USB_RET_ASYNC) {
s->setup_state = SETUP_STATE_SETUP;
return USB_RET_ASYNC;
@@ -129,7 +129,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
int ret = 0;
if (p->devep != 0)
- return s->info->handle_data(s, p);
+ return usb_device_handle_data(s, p);
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -138,8 +138,8 @@ static int do_token_in(USBDevice *s, USBPacket *p)
switch(s->setup_state) {
case SETUP_STATE_ACK:
if (!(s->setup_buf[0] & USB_DIR_IN)) {
- ret = s->info->handle_control(s, p, request, value, index,
- s->setup_len, s->data_buf);
+ ret = usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
if (ret == USB_RET_ASYNC) {
return USB_RET_ASYNC;
}
@@ -176,7 +176,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
static int do_token_out(USBDevice *s, USBPacket *p)
{
if (p->devep != 0)
- return s->info->handle_data(s, p);
+ return usb_device_handle_data(s, p);
switch(s->setup_state) {
case SETUP_STATE_ACK:
@@ -220,9 +220,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
switch(p->pid) {
case USB_MSG_ATTACH:
s->state = USB_STATE_ATTACHED;
- if (s->info->handle_attach) {
- s->info->handle_attach(s);
- }
+ usb_device_handle_attach(s);
return 0;
case USB_MSG_DETACH:
@@ -233,9 +231,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
s->remote_wakeup = 0;
s->addr = 0;
s->state = USB_STATE_DEFAULT;
- if (s->info->handle_reset) {
- s->info->handle_reset(s);
- }
+ usb_device_handle_reset(s);
return 0;
}
@@ -326,10 +322,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
int ret;
assert(p->owner == NULL);
- ret = dev->info->handle_packet(dev, p);
+ ret = usb_device_handle_packet(dev, p);
if (ret == USB_RET_ASYNC) {
if (p->owner == NULL) {
- p->owner = dev;
+ p->owner = usb_ep_get(dev, p->pid, p->devep);
} else {
/* We'll end up here when usb_handle_packet is called
* recursively due to a hub being in the chain. Nothing
@@ -357,7 +353,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
void usb_cancel_packet(USBPacket * p)
{
assert(p->owner != NULL);
- p->owner->info->cancel_packet(p->owner, p);
+ usb_device_cancel_packet(p->owner->dev, p);
p->owner = NULL;
}
@@ -414,3 +410,124 @@ void usb_packet_cleanup(USBPacket *p)
{
qemu_iovec_destroy(&p->iov);
}
+
+void usb_ep_init(USBDevice *dev)
+{
+ int ep;
+
+ dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
+ dev->ep_ctl.ifnum = 0;
+ dev->ep_ctl.dev = dev;
+ for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+ dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
+ dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
+ dev->ep_in[ep].ifnum = 0;
+ dev->ep_out[ep].ifnum = 0;
+ dev->ep_in[ep].dev = dev;
+ dev->ep_out[ep].dev = dev;
+ }
+}
+
+void usb_ep_dump(USBDevice *dev)
+{
+ static const char *tname[] = {
+ [USB_ENDPOINT_XFER_CONTROL] = "control",
+ [USB_ENDPOINT_XFER_ISOC] = "isoc",
+ [USB_ENDPOINT_XFER_BULK] = "bulk",
+ [USB_ENDPOINT_XFER_INT] = "int",
+ };
+ int ifnum, ep, first;
+
+ fprintf(stderr, "Device \"%s\", config %d\n",
+ dev->product_desc, dev->configuration);
+ for (ifnum = 0; ifnum < 16; ifnum++) {
+ first = 1;
+ for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+ if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
+ dev->ep_in[ep].ifnum == ifnum) {
+ if (first) {
+ first = 0;
+ fprintf(stderr, " Interface %d, alternative %d\n",
+ ifnum, dev->altsetting[ifnum]);
+ }
+ fprintf(stderr, " Endpoint %d, IN, %s, %d max\n", ep,
+ tname[dev->ep_in[ep].type],
+ dev->ep_in[ep].max_packet_size);
+ }
+ if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
+ dev->ep_out[ep].ifnum == ifnum) {
+ if (first) {
+ first = 0;
+ fprintf(stderr, " Interface %d, alternative %d\n",
+ ifnum, dev->altsetting[ifnum]);
+ }
+ fprintf(stderr, " Endpoint %d, OUT, %s, %d max\n", ep,
+ tname[dev->ep_out[ep].type],
+ dev->ep_out[ep].max_packet_size);
+ }
+ }
+ }
+ fprintf(stderr, "--\n");
+}
+
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
+{
+ struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev->ep_in : dev->ep_out;
+ if (ep == 0) {
+ return &dev->ep_ctl;
+ }
+ assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
+ assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
+ return eps + ep - 1;
+}
+
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ return uep->type;
+}
+
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ uep->type = type;
+}
+
+uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ return uep->ifnum;
+}
+
+void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ uep->ifnum = ifnum;
+}
+
+void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
+ uint16_t raw)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ int size, microframes;
+
+ size = raw & 0x7ff;
+ switch ((raw >> 11) & 3) {
+ case 1:
+ microframes = 2;
+ break;
+ case 2:
+ microframes = 3;
+ break;
+ default:
+ microframes = 1;
+ break;
+ }
+ uep->max_packet_size = size * microframes;
+}
+
+int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ return uep->max_packet_size;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 7ea90e4d9c..13e7c8ea7f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -1,3 +1,6 @@
+#ifndef QEMU_USB_H
+#define QEMU_USB_H
+
/*
* QEMU USB API
*
@@ -79,6 +82,11 @@
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
+#define USB_SUBCLASS_UNDEFINED 0
+#define USB_SUBCLASS_AUDIO_CONTROL 1
+#define USB_SUBCLASS_AUDIO_STREAMING 2
+#define USB_SUBCLASS_AUDIO_MIDISTREAMING 3
+
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
@@ -132,18 +140,21 @@
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_DEBUG 0x0A
#define USB_DT_INTERFACE_ASSOC 0x0B
+#define USB_DT_CS_INTERFACE 0x24
+#define USB_DT_CS_ENDPOINT 0x25
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
+#define USB_ENDPOINT_XFER_INVALID 255
typedef struct USBBus USBBus;
typedef struct USBBusOps USBBusOps;
typedef struct USBPort USBPort;
typedef struct USBDevice USBDevice;
-typedef struct USBDeviceInfo USBDeviceInfo;
typedef struct USBPacket USBPacket;
+typedef struct USBEndpoint USBEndpoint;
typedef struct USBDesc USBDesc;
typedef struct USBDescID USBDescID;
@@ -161,10 +172,19 @@ struct USBDescString {
QLIST_ENTRY(USBDescString) next;
};
+#define USB_MAX_ENDPOINTS 15
+#define USB_MAX_INTERFACES 16
+
+struct USBEndpoint {
+ uint8_t type;
+ uint8_t ifnum;
+ int max_packet_size;
+ USBDevice *dev;
+};
+
/* definition of a USB device */
struct USBDevice {
DeviceState qdev;
- USBDeviceInfo *info;
USBPort *port;
char *port_path;
void *opaque;
@@ -186,13 +206,31 @@ struct USBDevice {
int32_t setup_len;
int32_t setup_index;
+ USBEndpoint ep_ctl;
+ USBEndpoint ep_in[USB_MAX_ENDPOINTS];
+ USBEndpoint ep_out[USB_MAX_ENDPOINTS];
+
QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device;
+
+ int configuration;
+ int ninterfaces;
+ int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
+ const USBDescIface *ifaces[USB_MAX_INTERFACES];
};
-struct USBDeviceInfo {
- DeviceInfo qdev;
+#define TYPE_USB_DEVICE "usb-device"
+#define USB_DEVICE(obj) \
+ OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE)
+#define USB_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE)
+#define USB_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE)
+
+typedef struct USBDeviceClass {
+ DeviceClass parent_class;
+
int (*init)(USBDevice *dev);
/*
@@ -241,13 +279,12 @@ struct USBDeviceInfo {
*/
int (*handle_data)(USBDevice *dev, USBPacket *p);
+ void (*set_interface)(USBDevice *dev, int interface,
+ int alt_old, int alt_new);
+
const char *product_desc;
const USBDesc *usb_desc;
-
- /* handle legacy -usbdevice command line options */
- const char *usbdevice_name;
- USBDevice *(*usbdevice_init)(const char *params);
-};
+} USBDeviceClass;
typedef struct USBPortOps {
void (*attach)(USBPort *port);
@@ -288,7 +325,7 @@ struct USBPacket {
QEMUIOVector iov;
int result; /* transfer length or USB_RET_* status code */
/* Internal use by the USB layer. */
- USBDevice *owner;
+ USBEndpoint *owner;
};
void usb_packet_init(USBPacket *p);
@@ -304,6 +341,17 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p);
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
+void usb_ep_init(USBDevice *dev);
+void usb_ep_dump(USBDevice *dev);
+struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
+uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
+uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep);
+void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type);
+void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
+void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
+ uint16_t raw);
+int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
+
void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
void usb_reset(USBPort *port);
@@ -370,8 +418,8 @@ struct USBBusOps {
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
USBBus *usb_bus_find(int busnr);
-void usb_qdev_register(USBDeviceInfo *info);
-void usb_qdev_register_many(USBDeviceInfo *info);
+void usb_legacy_register(const char *typename, const char *usbdevice_name,
+ USBDevice *(*usbdevice_init)(const char *params));
USBDevice *usb_create(USBBus *bus, const char *name);
USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
@@ -403,4 +451,25 @@ extern const VMStateDescription vmstate_usb_device;
.offset = vmstate_offset_value(_state, _field, USBDevice), \
}
+int usb_device_handle_packet(USBDevice *dev, USBPacket *p);
+
+void usb_device_cancel_packet(USBDevice *dev, USBPacket *p);
+
+void usb_device_handle_attach(USBDevice *dev);
+
+void usb_device_handle_reset(USBDevice *dev);
+
+int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, int value,
+ int index, int length, uint8_t *data);
+
+int usb_device_handle_data(USBDevice *dev, USBPacket *p);
+
+void usb_device_set_interface(USBDevice *dev, int interface,
+ int alt_old, int alt_new);
+
+const char *usb_device_get_product_desc(USBDevice *dev);
+
+const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
+
+#endif
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index a285f7f383..c4105e977b 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -109,22 +109,56 @@ static int versatile_pci_host_init(PCIDevice *d)
return 0;
}
-static PCIDeviceInfo versatile_pci_host_info = {
- .qdev.name = "versatile_pci_host",
- .qdev.size = sizeof(PCIDevice),
- .init = versatile_pci_host_init,
- .vendor_id = PCI_VENDOR_ID_XILINX,
- /* Both boards have the same device ID. Oh well. */
- .device_id = PCI_DEVICE_ID_XILINX_XC2VP30,
- .class_id = PCI_CLASS_PROCESSOR_CO,
+static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = versatile_pci_host_init;
+ k->vendor_id = PCI_VENDOR_ID_XILINX;
+ k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
+ k->class_id = PCI_CLASS_PROCESSOR_CO;
+}
+
+static TypeInfo versatile_pci_host_info = {
+ .name = "versatile_pci_host",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = versatile_pci_host_class_init,
+};
+
+static void pci_vpb_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pci_vpb_init;
+}
+
+static TypeInfo pci_vpb_info = {
+ .name = "versatile_pci",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PCIVPBState),
+ .class_init = pci_vpb_class_init,
+};
+
+static void pci_realview_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = pci_realview_init;
+}
+
+static TypeInfo pci_realview_info = {
+ .name = "realview_pci",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PCIVPBState),
+ .class_init = pci_realview_class_init,
};
static void versatile_pci_register_devices(void)
{
- sysbus_register_dev("versatile_pci", sizeof(PCIVPBState), pci_vpb_init);
- sysbus_register_dev("realview_pci", sizeof(PCIVPBState),
- pci_realview_init);
- pci_qdev_register(&versatile_pci_host_info);
+ type_register_static(&pci_vpb_info);
+ type_register_static(&pci_realview_info);
+ type_register_static(&versatile_pci_host_info);
}
device_init(versatile_pci_register_devices)
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 0312b7564a..6e28e78f44 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -365,17 +365,26 @@ static void versatile_machine_init(void)
machine_init(versatile_machine_init);
-static SysBusDeviceInfo vpb_sic_info = {
- .init = vpb_sic_init,
- .qdev.name = "versatilepb_sic",
- .qdev.size = sizeof(vpb_sic_state),
- .qdev.vmsd = &vmstate_vpb_sic,
- .qdev.no_user = 1,
+static void vpb_sic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = vpb_sic_init;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_vpb_sic;
+}
+
+static TypeInfo vpb_sic_info = {
+ .name = "versatilepb_sic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(vpb_sic_state),
+ .class_init = vpb_sic_class_init,
};
static void versatilepb_register_devices(void)
{
- sysbus_register_withprop(&vpb_sic_info);
+ type_register_static(&vpb_sic_info);
}
device_init(versatilepb_register_devices)
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 71115564e0..64fab4574c 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -182,6 +182,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
/* 0x100ec000 TrustZone Address Space Controller */
/* 0x10200000 CoreSight debug APB */
/* 0x1e00a000 PL310 L2 Cache Controller */
+ sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
/* CS0: NOR0 flash : 0x40000000 .. 0x44000000 */
/* CS4: NOR1 flash : 0x44000000 .. 0x48000000 */
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 4825313f67..8d3ff0d47b 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -69,16 +69,24 @@ static int vga_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo vga_info = {
- .qdev.name = "isa-vga",
- .qdev.size = sizeof(ISAVGAState),
- .qdev.vmsd = &vmstate_vga_common,
- .qdev.reset = vga_reset_isa,
- .init = vga_initfn,
+static void vga_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = vga_initfn;
+ dc->reset = vga_reset_isa;
+ dc->vmsd = &vmstate_vga_common;
+}
+
+static TypeInfo vga_info = {
+ .name = "isa-vga",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(ISAVGAState),
+ .class_init = vga_class_initfn,
};
static void vga_register(void)
{
- isa_qdev_register(&vga_info);
+ type_register_static(&vga_info);
}
device_init(vga_register)
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index a75dbf3974..974a7a9d6f 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -75,22 +75,29 @@ DeviceState *pci_vga_init(PCIBus *bus)
return &pci_create_simple(bus, -1, "VGA")->qdev;
}
-static PCIDeviceInfo vga_info = {
- .qdev.name = "VGA",
- .qdev.size = sizeof(PCIVGAState),
- .qdev.vmsd = &vmstate_vga_pci,
- .no_hotplug = 1,
- .init = pci_vga_initfn,
- .romfile = "vgabios-stdvga.bin",
+static void vga_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = pci_vga_initfn;
+ k->romfile = "vgabios-stdvga.bin";
+ k->vendor_id = PCI_VENDOR_ID_QEMU;
+ k->device_id = PCI_DEVICE_ID_QEMU_VGA;
+ k->class_id = PCI_CLASS_DISPLAY_VGA;
+ dc->vmsd = &vmstate_vga_pci;
+}
- /* dummy VGA (same as Bochs ID) */
- .vendor_id = PCI_VENDOR_ID_QEMU,
- .device_id = PCI_DEVICE_ID_QEMU_VGA,
- .class_id = PCI_CLASS_DISPLAY_VGA,
+static TypeInfo vga_info = {
+ .name = "VGA",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIVGAState),
+ .class_init = vga_class_init,
};
static void vga_register(void)
{
- pci_qdev_register(&vga_info);
+ type_register_static(&vga_info);
}
device_init(vga_register);
diff --git a/hw/vga.c b/hw/vga.c
index 950f97e440..d87c4f9f5b 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
+#include "vga.h"
#include "console.h"
#include "pc.h"
#include "pci.h"
@@ -36,6 +37,18 @@
//#define DEBUG_BOCHS_VBE
+/*
+ * Video Graphics Array (VGA)
+ *
+ * Chipset docs for original IBM VGA:
+ * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
+ *
+ * FreeVGA site:
+ * http://www.osdever.net/FreeVGA/home.htm
+ *
+ * Standard VGA features and Bochs VBE extensions are implemented.
+ */
+
/* force some bits to zero */
const uint8_t sr_mask[8] = {
0x03,
@@ -160,9 +173,10 @@ static void vga_update_memory_access(VGACommonState *s)
s->chain4_alias = NULL;
- if ((s->sr[0x02] & 0xf) == 0xf && s->sr[0x04] & 0x08) {
+ if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
+ VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
offset = 0;
- switch ((s->gr[6] >> 2) & 3) {
+ switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
case 0:
base = 0xa0000;
size = 0x20000;
@@ -223,22 +237,20 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
int64_t chars_per_sec;
struct vga_precise_retrace *r = &s->retrace_info.precise;
- htotal_chars = s->cr[0x00] + 5;
- hretr_start_char = s->cr[0x04];
- hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
- hretr_end_char = s->cr[0x05] & 0x1f;
+ htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
+ hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
+ hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
+ hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
- vtotal_lines = (s->cr[0x06]
- | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
- ;
- vretr_start_line = s->cr[0x10]
- | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
- ;
- vretr_end_line = s->cr[0x11] & 0xf;
+ vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
+ (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
+ ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
+ vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
+ ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
+ ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
+ vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
-
-
- clocking_mode = (s->sr[0x01] >> 3) & 1;
+ clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
clock_sel = (s->msr >> 2) & 3;
dots = (s->msr & 1) ? 8 : 9;
@@ -261,8 +273,8 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
r->htotal = htotal_chars;
#if 0
- div2 = (s->cr[0x17] >> 2) & 1;
- sldiv2 = (s->cr[0x17] >> 3) & 1;
+ div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
+ sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
printf (
"hz=%f\n"
"htotal = %d\n"
@@ -332,7 +344,7 @@ static uint8_t vga_dumb_retrace(VGACommonState *s)
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
{
- if (s->msr & MSR_COLOR_EMULATION) {
+ if (s->msr & VGA_MIS_COLOR) {
/* Color */
return (addr >= 0x3b0 && addr <= 0x3bf);
} else {
@@ -350,73 +362,74 @@ uint32_t vga_ioport_read(void *opaque, uint32_t addr)
val = 0xff;
} else {
switch(addr) {
- case 0x3c0:
+ case VGA_ATT_W:
if (s->ar_flip_flop == 0) {
val = s->ar_index;
} else {
val = 0;
}
break;
- case 0x3c1:
+ case VGA_ATT_R:
index = s->ar_index & 0x1f;
- if (index < 21)
+ if (index < VGA_ATT_C) {
val = s->ar[index];
- else
+ } else {
val = 0;
+ }
break;
- case 0x3c2:
+ case VGA_MIS_W:
val = s->st00;
break;
- case 0x3c4:
+ case VGA_SEQ_I:
val = s->sr_index;
break;
- case 0x3c5:
+ case VGA_SEQ_D:
val = s->sr[s->sr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
#endif
break;
- case 0x3c7:
+ case VGA_PEL_IR:
val = s->dac_state;
break;
- case 0x3c8:
+ case VGA_PEL_IW:
val = s->dac_write_index;
break;
- case 0x3c9:
+ case VGA_PEL_D:
val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
if (++s->dac_sub_index == 3) {
s->dac_sub_index = 0;
s->dac_read_index++;
}
break;
- case 0x3ca:
+ case VGA_FTC_R:
val = s->fcr;
break;
- case 0x3cc:
+ case VGA_MIS_R:
val = s->msr;
break;
- case 0x3ce:
+ case VGA_GFX_I:
val = s->gr_index;
break;
- case 0x3cf:
+ case VGA_GFX_D:
val = s->gr[s->gr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
#endif
break;
- case 0x3b4:
- case 0x3d4:
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
val = s->cr_index;
break;
- case 0x3b5:
- case 0x3d5:
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
val = s->cr[s->cr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
#endif
break;
- case 0x3ba:
- case 0x3da:
+ case VGA_IS1_RM:
+ case VGA_IS1_RC:
/* just toggle to fool polling */
val = s->st01 = s->retrace(s);
s->ar_flip_flop = 0;
@@ -446,29 +459,29 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
#endif
switch(addr) {
- case 0x3c0:
+ case VGA_ATT_W:
if (s->ar_flip_flop == 0) {
val &= 0x3f;
s->ar_index = val;
} else {
index = s->ar_index & 0x1f;
switch(index) {
- case 0x00 ... 0x0f:
+ case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
s->ar[index] = val & 0x3f;
break;
- case 0x10:
+ case VGA_ATC_MODE:
s->ar[index] = val & ~0x10;
break;
- case 0x11:
+ case VGA_ATC_OVERSCAN:
s->ar[index] = val;
break;
- case 0x12:
+ case VGA_ATC_PLANE_ENABLE:
s->ar[index] = val & ~0xc0;
break;
- case 0x13:
+ case VGA_ATC_PEL:
s->ar[index] = val & ~0xf0;
break;
- case 0x14:
+ case VGA_ATC_COLOR_PAGE:
s->ar[index] = val & ~0xf0;
break;
default:
@@ -477,32 +490,34 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
s->ar_flip_flop ^= 1;
break;
- case 0x3c2:
+ case VGA_MIS_W:
s->msr = val & ~0x10;
s->update_retrace_info(s);
break;
- case 0x3c4:
+ case VGA_SEQ_I:
s->sr_index = val & 7;
break;
- case 0x3c5:
+ case VGA_SEQ_D:
#ifdef DEBUG_VGA_REG
printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
#endif
s->sr[s->sr_index] = val & sr_mask[s->sr_index];
- if (s->sr_index == 1) s->update_retrace_info(s);
+ if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
+ s->update_retrace_info(s);
+ }
vga_update_memory_access(s);
break;
- case 0x3c7:
+ case VGA_PEL_IR:
s->dac_read_index = val;
s->dac_sub_index = 0;
s->dac_state = 3;
break;
- case 0x3c8:
+ case VGA_PEL_IW:
s->dac_write_index = val;
s->dac_sub_index = 0;
s->dac_state = 0;
break;
- case 0x3c9:
+ case VGA_PEL_D:
s->dac_cache[s->dac_sub_index] = val;
if (++s->dac_sub_index == 3) {
memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
@@ -510,48 +525,51 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->dac_write_index++;
}
break;
- case 0x3ce:
+ case VGA_GFX_I:
s->gr_index = val & 0x0f;
break;
- case 0x3cf:
+ case VGA_GFX_D:
#ifdef DEBUG_VGA_REG
printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
#endif
s->gr[s->gr_index] = val & gr_mask[s->gr_index];
vga_update_memory_access(s);
break;
- case 0x3b4:
- case 0x3d4:
+ case VGA_CRT_IM:
+ case VGA_CRT_IC:
s->cr_index = val;
break;
- case 0x3b5:
- case 0x3d5:
+ case VGA_CRT_DM:
+ case VGA_CRT_DC:
#ifdef DEBUG_VGA_REG
printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
#endif
/* handle CR0-7 protection */
- if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
+ if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
+ s->cr_index <= VGA_CRTC_OVERFLOW) {
/* can always write bit 4 of CR7 */
- if (s->cr_index == 7)
- s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
+ if (s->cr_index == VGA_CRTC_OVERFLOW) {
+ s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
+ (val & 0x10);
+ }
return;
}
s->cr[s->cr_index] = val;
switch(s->cr_index) {
- case 0x00:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- case 0x11:
- case 0x17:
+ case VGA_CRTC_H_TOTAL:
+ case VGA_CRTC_H_SYNC_START:
+ case VGA_CRTC_H_SYNC_END:
+ case VGA_CRTC_V_TOTAL:
+ case VGA_CRTC_OVERFLOW:
+ case VGA_CRTC_V_SYNC_END:
+ case VGA_CRTC_MODE:
s->update_retrace_info(s);
break;
}
break;
- case 0x3ba:
- case 0x3da:
+ case VGA_IS1_RM:
+ case VGA_IS1_RC:
s->fcr = val & 0x10;
break;
}
@@ -681,31 +699,37 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
/* we initialize the VGA graphic mode (should be done
in BIOS) */
- s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
- s->cr[0x17] |= 3; /* no CGA modes */
- s->cr[0x13] = s->vbe_line_offset >> 3;
+ /* graphic mode + memory map 1 */
+ s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
+ VGA_GR06_GRAPHICS_MODE;
+ s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
+ s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
/* width */
- s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
+ s->cr[VGA_CRTC_H_DISP] =
+ (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
/* height (only meaningful if < 1024) */
h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
- s->cr[0x12] = h;
- s->cr[0x07] = (s->cr[0x07] & ~0x42) |
+ s->cr[VGA_CRTC_V_DISP_END] = h;
+ s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
((h >> 7) & 0x02) | ((h >> 3) & 0x40);
/* line compare to 1023 */
- s->cr[0x18] = 0xff;
- s->cr[0x07] |= 0x10;
- s->cr[0x09] |= 0x40;
+ s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
+ s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
+ s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
shift_control = 0;
- s->sr[0x01] &= ~8; /* no double line */
+ s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
} else {
shift_control = 2;
- s->sr[4] |= 0x08; /* set chain 4 mode */
- s->sr[2] |= 0x0f; /* activate all planes */
+ /* set chain 4 mode */
+ s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
+ /* activate all planes */
+ s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
}
- s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
- s->cr[0x09] &= ~0x9f; /* no double scan */
+ s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
+ (shift_control << 5);
+ s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
} else {
/* XXX: the bios should do that */
s->bank_offset = 0;
@@ -762,7 +786,7 @@ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
uint32_t ret;
/* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
+ memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
addr &= 0x1ffff;
switch(memory_map_mode) {
case 0:
@@ -785,24 +809,25 @@ uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
break;
}
- if (s->sr[4] & 0x08) {
+ if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
ret = s->vram_ptr[addr];
- } else if (s->gr[5] & 0x10) {
+ } else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
+ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
ret = s->vram_ptr[((addr & ~1) << 1) | plane];
} else {
/* standard VGA latched access */
s->latch = ((uint32_t *)s->vram_ptr)[addr];
- if (!(s->gr[5] & 0x08)) {
+ if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
/* read mode 0 */
- plane = s->gr[4];
+ plane = s->gr[VGA_GFX_PLANE_READ];
ret = GET_PLANE(s->latch, plane);
} else {
/* read mode 1 */
- ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
+ ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
+ mask16[s->gr[VGA_GFX_COMPARE_MASK]];
ret |= ret >> 16;
ret |= ret >> 8;
ret = (~ret) & 0xff;
@@ -821,7 +846,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
#endif
/* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
+ memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
addr &= 0x1ffff;
switch(memory_map_mode) {
case 0:
@@ -844,67 +869,68 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
break;
}
- if (s->sr[4] & 0x08) {
+ if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
plane = addr & 3;
mask = (1 << plane);
- if (s->sr[2] & mask) {
+ if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
#endif
s->plane_updated |= mask; /* only used to detect font change */
- memory_region_set_dirty(&s->vram, addr);
+ memory_region_set_dirty(&s->vram, addr, 1);
}
- } else if (s->gr[5] & 0x10) {
+ } else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
+ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
mask = (1 << plane);
- if (s->sr[2] & mask) {
+ if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
addr = ((addr & ~1) << 1) | plane;
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
#endif
s->plane_updated |= mask; /* only used to detect font change */
- memory_region_set_dirty(&s->vram, addr);
+ memory_region_set_dirty(&s->vram, addr, 1);
}
} else {
/* standard VGA latched access */
- write_mode = s->gr[5] & 3;
+ write_mode = s->gr[VGA_GFX_MODE] & 3;
switch(write_mode) {
default:
case 0:
/* rotate */
- b = s->gr[3] & 7;
+ b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
val = ((val >> b) | (val << (8 - b))) & 0xff;
val |= val << 8;
val |= val << 16;
/* apply set/reset mask */
- set_mask = mask16[s->gr[1]];
- val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
- bit_mask = s->gr[8];
+ set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
+ val = (val & ~set_mask) |
+ (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
+ bit_mask = s->gr[VGA_GFX_BIT_MASK];
break;
case 1:
val = s->latch;
goto do_write;
case 2:
val = mask16[val & 0x0f];
- bit_mask = s->gr[8];
+ bit_mask = s->gr[VGA_GFX_BIT_MASK];
break;
case 3:
/* rotate */
- b = s->gr[3] & 7;
+ b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
val = (val >> b) | (val << (8 - b));
- bit_mask = s->gr[8] & val;
- val = mask16[s->gr[0]];
+ bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
+ val = mask16[s->gr[VGA_GFX_SR_VALUE]];
break;
}
/* apply logical operation */
- func_select = s->gr[3] >> 3;
+ func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
switch(func_select) {
case 0:
default:
@@ -931,7 +957,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
do_write:
/* mask data according to sr[2] */
- mask = s->sr[2];
+ mask = s->sr[VGA_SEQ_PLANE_WRITE];
s->plane_updated |= mask; /* only used to detect font change */
write_mask = mask16[mask];
((uint32_t *)s->vram_ptr)[addr] =
@@ -941,7 +967,7 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
addr * 4, write_mask, val);
#endif
- memory_region_set_dirty(&s->vram, addr << 2);
+ memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
}
}
@@ -1045,10 +1071,11 @@ static int update_palette16(VGACommonState *s)
palette = s->last_palette;
for(i = 0; i < 16; i++) {
v = s->ar[i];
- if (s->ar[0x10] & 0x80)
- v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
- else
- v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
+ if (s->ar[VGA_ATC_MODE] & 0x80) {
+ v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
+ } else {
+ v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
+ }
v = v * 3;
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
c6_to_8(s->palette[v + 1]),
@@ -1104,16 +1131,17 @@ static void vga_get_offsets(VGACommonState *s,
#endif
{
/* compute line_offset in bytes */
- line_offset = s->cr[0x13];
+ line_offset = s->cr[VGA_CRTC_OFFSET];
line_offset <<= 3;
/* starting address */
- start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
+ start_addr = s->cr[VGA_CRTC_START_LO] |
+ (s->cr[VGA_CRTC_START_HI] << 8);
/* line compare */
- line_compare = s->cr[0x18] |
- ((s->cr[0x07] & 0x10) << 4) |
- ((s->cr[0x09] & 0x40) << 3);
+ line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
+ ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
}
*pline_offset = line_offset;
*pstart_addr = start_addr;
@@ -1216,20 +1244,22 @@ static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight
int width, cwidth, height, cheight;
/* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
+ cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
cwidth = 8;
- if (!(s->sr[1] & 0x01))
+ if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
cwidth = 9;
- if (s->sr[1] & 0x08)
+ }
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
cwidth = 16; /* NOTE: no 18 pixel wide */
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
+ }
+ width = (s->cr[VGA_CRTC_H_DISP] + 1);
+ if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
/* ugly hack for CGA 160x100x16 - explain me the logic */
height = 100;
} else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1) / cheight;
}
@@ -1273,7 +1303,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
vga_draw_glyph9_func *vga_draw_glyph9;
/* compute font data address (in plane 2) */
- v = s->sr[3];
+ v = s->sr[VGA_SEQ_CHARACTER_MAP];
offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
if (offset != s->font_offsets[0]) {
s->font_offsets[0] = offset;
@@ -1321,10 +1351,11 @@ static void vga_draw_text(VGACommonState *s, int full_update)
palette = s->last_palette;
x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
+ s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
if (cursor_offset != s->cursor_offset ||
- s->cr[0xa] != s->cursor_start ||
- s->cr[0xb] != s->cursor_end) {
+ s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
+ s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
/* if the cursor position changed, we update the old and new
chars */
if (s->cursor_offset < CH_ATTR_SIZE)
@@ -1332,8 +1363,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
if (cursor_offset < CH_ATTR_SIZE)
s->last_ch_attr[cursor_offset] = -1;
s->cursor_offset = cursor_offset;
- s->cursor_start = s->cr[0xa];
- s->cursor_end = s->cr[0xb];
+ s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
+ s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
}
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
@@ -1378,17 +1409,19 @@ static void vga_draw_text(VGACommonState *s, int full_update)
font_ptr, cheight, fgcol, bgcol);
} else {
dup9 = 0;
- if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
+ if (ch >= 0xb0 && ch <= 0xdf &&
+ (s->ar[VGA_ATC_MODE] & 0x04)) {
dup9 = 1;
+ }
vga_draw_glyph9(d1, linesize,
font_ptr, cheight, fgcol, bgcol, dup9);
}
if (src == cursor_ptr &&
- !(s->cr[0x0a] & 0x20)) {
+ !(s->cr[VGA_CRTC_CURSOR_START] & 0x20)) {
int line_start, line_last, h;
/* draw the cursor */
- line_start = s->cr[0x0a] & 0x1f;
- line_last = s->cr[0x0b] & 0x1f;
+ line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
+ line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
/* XXX: check that */
if (line_last > cheight - 1)
line_last = cheight - 1;
@@ -1544,10 +1577,10 @@ static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
} else
#endif
{
- width = (s->cr[0x01] + 1) * 8;
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1);
}
*pwidth = width;
@@ -1602,10 +1635,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->get_resolution(s, &width, &height);
disp_width = width;
- shift_control = (s->gr[0x05] >> 5) & 3;
- double_scan = (s->cr[0x09] >> 7);
+ shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
+ double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
if (shift_control != 1) {
- multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
+ multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
+ - 1;
} else {
/* in CGA modes, multi_scan is ignored */
/* XXX: is it correct ? */
@@ -1620,11 +1654,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
if (shift_control == 0) {
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
disp_width <<= 1;
}
} else if (shift_control == 1) {
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
disp_width <<= 1;
}
}
@@ -1668,7 +1702,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (shift_control == 0) {
full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
v = VGA_DRAW_LINE4D2;
} else {
v = VGA_DRAW_LINE4;
@@ -1676,7 +1710,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
bits = 4;
} else if (shift_control == 1) {
full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
v = VGA_DRAW_LINE2D2;
} else {
v = VGA_DRAW_LINE2;
@@ -1721,7 +1755,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
line_offset = s->line_offset;
#if 0
printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
- width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
+ width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
+ s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
#endif
addr1 = (s->start_addr * 4);
bwidth = (width * bits + 7) / 8;
@@ -1733,26 +1768,19 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
y1 = 0;
for(y = 0; y < height; y++) {
addr = addr1;
- if (!(s->cr[0x17] & 1)) {
+ if (!(s->cr[VGA_CRTC_MODE] & 1)) {
int shift;
/* CGA compatibility handling */
- shift = 14 + ((s->cr[0x17] >> 6) & 1);
+ shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
}
- if (!(s->cr[0x17] & 2)) {
+ if (!(s->cr[VGA_CRTC_MODE] & 2)) {
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
}
- page0 = addr & TARGET_PAGE_MASK;
- page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
- update = full_update |
- memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
- memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
- if ((page1 - page0) > TARGET_PAGE_SIZE) {
- /* if wide line, can use another page */
- update |= memory_region_get_dirty(&s->vram,
- page0 + TARGET_PAGE_SIZE,
- DIRTY_MEMORY_VGA);
- }
+ page0 = addr;
+ page1 = addr + bwidth - 1;
+ update = memory_region_get_dirty(&s->vram, page0, page1,
+ DIRTY_MEMORY_VGA);
/* explicit invalidation for the hardware cursor */
update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
if (update) {
@@ -1776,7 +1804,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
}
}
if (!multi_run) {
- mask = (s->cr[0x17] & 3) ^ 3;
+ mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
if ((y1 & mask) == mask)
addr1 += line_offset;
y1++;
@@ -1798,7 +1826,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (page_max >= page_min) {
memory_region_reset_dirty(&s->vram,
page_min,
- page_max + TARGET_PAGE_SIZE - page_min,
+ page_max - page_min,
DIRTY_MEMORY_VGA);
}
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
@@ -1848,7 +1876,7 @@ static void vga_update_display(void *opaque)
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
} else {
- graphic_mode = s->gr[6] & 1;
+ graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
@@ -1966,7 +1994,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
} else {
- graphic_mode = s->gr[6] & 1;
+ graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
@@ -1983,20 +2011,22 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
full_update |= update_basic_params(s);
/* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
+ cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
cw = 8;
- if (!(s->sr[1] & 0x01))
+ if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
cw = 9;
- if (s->sr[1] & 0x08)
+ }
+ if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
cw = 16; /* NOTE: no 18 pixel wide */
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
+ }
+ width = (s->cr[VGA_CRTC_H_DISP] + 1);
+ if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
/* ugly hack for CGA 160x100x16 - explain me the logic */
height = 100;
} else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
+ height = s->cr[VGA_CRTC_V_DISP_END] |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
+ ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
height = (height + 1) / cheight;
}
@@ -2025,11 +2055,12 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
}
/* Update "hardware" cursor */
- cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
+ s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
if (cursor_offset != s->cursor_offset ||
- s->cr[0xa] != s->cursor_start ||
- s->cr[0xb] != s->cursor_end || full_update) {
- cursor_visible = !(s->cr[0xa] & 0x20);
+ s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
+ s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
+ cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
dpy_cursor(s->ds,
TEXTMODE_X(cursor_offset),
@@ -2037,8 +2068,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
else
dpy_cursor(s->ds, -1, -1);
s->cursor_offset = cursor_offset;
- s->cursor_start = s->cr[0xa];
- s->cursor_end = s->cr[0xb];
+ s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
+ s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
}
src = (uint32_t *) s->vram_ptr + s->start_addr;
diff --git a/hw/vga.h b/hw/vga.h
new file mode 100644
index 0000000000..d917046da6
--- /dev/null
+++ b/hw/vga.h
@@ -0,0 +1,159 @@
+/*
+ * linux/include/video/vga.h -- standard VGA chipset interaction
+ *
+ * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ *
+ * Copyright history from vga16fb.c:
+ * Copyright 1999 Ben Pfaff and Petr Vandrovec
+ * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ */
+
+#ifndef __linux_video_vga_h__
+#define __linux_video_vga_h__
+
+/* Some of the code below is taken from SVGAlib. The original,
+ unmodified copyright notice for that code is below. */
+/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it without any restrictions. This library is distributed */
+/* in the hope that it will be useful, but without any warranty. */
+
+/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
+/* partially copyrighted (C) 1993 by Hartmut Schirmer */
+
+/* VGA data register ports */
+#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
+#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
+#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */
+#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */
+#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */
+#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */
+#define VGA_MIS_R 0x3CC /* Misc Output Read Register */
+#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */
+#define VGA_FTC_R 0x3CA /* Feature Control Read Register */
+#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
+#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
+#define VGA_PEL_D 0x3C9 /* PEL Data Register */
+#define VGA_PEL_MSK 0x3C6 /* PEL mask register */
+
+/* EGA-specific registers */
+#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */
+#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */
+
+/* VGA index register ports */
+#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
+#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
+#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
+#define VGA_GFX_I 0x3CE /* Graphics Controller Index */
+#define VGA_SEQ_I 0x3C4 /* Sequencer Index */
+#define VGA_PEL_IW 0x3C8 /* PEL Write Index */
+#define VGA_PEL_IR 0x3C7 /* PEL Read Index */
+
+/* standard VGA indexes max counts */
+#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */
+#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */
+#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */
+#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */
+#define VGA_MIS_C 0x01 /* Number of Misc Output Register */
+
+/* VGA misc register bit masks */
+#define VGA_MIS_COLOR 0x01
+#define VGA_MIS_ENB_MEM_ACCESS 0x02
+#define VGA_MIS_DCLK_28322_720 0x04
+#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08)
+#define VGA_MIS_SEL_HIGH_PAGE 0x20
+
+/* VGA CRT controller register indices */
+#define VGA_CRTC_H_TOTAL 0
+#define VGA_CRTC_H_DISP 1
+#define VGA_CRTC_H_BLANK_START 2
+#define VGA_CRTC_H_BLANK_END 3
+#define VGA_CRTC_H_SYNC_START 4
+#define VGA_CRTC_H_SYNC_END 5
+#define VGA_CRTC_V_TOTAL 6
+#define VGA_CRTC_OVERFLOW 7
+#define VGA_CRTC_PRESET_ROW 8
+#define VGA_CRTC_MAX_SCAN 9
+#define VGA_CRTC_CURSOR_START 0x0A
+#define VGA_CRTC_CURSOR_END 0x0B
+#define VGA_CRTC_START_HI 0x0C
+#define VGA_CRTC_START_LO 0x0D
+#define VGA_CRTC_CURSOR_HI 0x0E
+#define VGA_CRTC_CURSOR_LO 0x0F
+#define VGA_CRTC_V_SYNC_START 0x10
+#define VGA_CRTC_V_SYNC_END 0x11
+#define VGA_CRTC_V_DISP_END 0x12
+#define VGA_CRTC_OFFSET 0x13
+#define VGA_CRTC_UNDERLINE 0x14
+#define VGA_CRTC_V_BLANK_START 0x15
+#define VGA_CRTC_V_BLANK_END 0x16
+#define VGA_CRTC_MODE 0x17
+#define VGA_CRTC_LINE_COMPARE 0x18
+#define VGA_CRTC_REGS VGA_CRT_C
+
+/* VGA CRT controller bit masks */
+#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */
+#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
+
+/* VGA attribute controller register indices */
+#define VGA_ATC_PALETTE0 0x00
+#define VGA_ATC_PALETTE1 0x01
+#define VGA_ATC_PALETTE2 0x02
+#define VGA_ATC_PALETTE3 0x03
+#define VGA_ATC_PALETTE4 0x04
+#define VGA_ATC_PALETTE5 0x05
+#define VGA_ATC_PALETTE6 0x06
+#define VGA_ATC_PALETTE7 0x07
+#define VGA_ATC_PALETTE8 0x08
+#define VGA_ATC_PALETTE9 0x09
+#define VGA_ATC_PALETTEA 0x0A
+#define VGA_ATC_PALETTEB 0x0B
+#define VGA_ATC_PALETTEC 0x0C
+#define VGA_ATC_PALETTED 0x0D
+#define VGA_ATC_PALETTEE 0x0E
+#define VGA_ATC_PALETTEF 0x0F
+#define VGA_ATC_MODE 0x10
+#define VGA_ATC_OVERSCAN 0x11
+#define VGA_ATC_PLANE_ENABLE 0x12
+#define VGA_ATC_PEL 0x13
+#define VGA_ATC_COLOR_PAGE 0x14
+
+#define VGA_AR_ENABLE_DISPLAY 0x20
+
+/* VGA sequencer register indices */
+#define VGA_SEQ_RESET 0x00
+#define VGA_SEQ_CLOCK_MODE 0x01
+#define VGA_SEQ_PLANE_WRITE 0x02
+#define VGA_SEQ_CHARACTER_MAP 0x03
+#define VGA_SEQ_MEMORY_MODE 0x04
+
+/* VGA sequencer register bit masks */
+#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */
+#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */
+#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */
+#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */
+#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */
+#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */
+
+/* VGA graphics controller register indices */
+#define VGA_GFX_SR_VALUE 0x00
+#define VGA_GFX_SR_ENABLE 0x01
+#define VGA_GFX_COMPARE_VALUE 0x02
+#define VGA_GFX_DATA_ROTATE 0x03
+#define VGA_GFX_PLANE_READ 0x04
+#define VGA_GFX_MODE 0x05
+#define VGA_GFX_MISC 0x06
+#define VGA_GFX_COMPARE_MASK 0x07
+#define VGA_GFX_BIT_MASK 0x08
+
+/* VGA graphics controller bit masks */
+#define VGA_GR06_GRAPHICS_MODE 0x01
+
+#endif /* __linux_video_vga_h__ */
diff --git a/hw/vga_int.h b/hw/vga_int.h
index c1e700fa0b..7685b2b167 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -25,9 +25,6 @@
#include <hw/hw.h>
#include "memory.h"
-#define MSR_COLOR_EMULATION 0x01
-#define MSR_PAGE_SELECT 0x20
-
#define ST01_V_RETRACE 0x08
#define ST01_DISP_ENABLE 0x01
@@ -205,19 +202,6 @@ void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
int ppm_save(const char *filename, struct DisplaySurface *ds);
-void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-
int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space);
diff --git a/hw/vga_template.h b/hw/vga_template.h
index 681425f9a2..f6f6a01d84 100644
--- a/hw/vga_template.h
+++ b/hw/vga_template.h
@@ -161,7 +161,7 @@ static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -203,7 +203,7 @@ static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -236,7 +236,7 @@ static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -268,7 +268,7 @@ static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
int x;
palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
+ plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
@@ -340,72 +340,6 @@ static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
}
}
-void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
- const uint8_t *src1,
- int poffset, int w,
- unsigned int color0,
- unsigned int color1,
- unsigned int color_xor)
-{
- const uint8_t *plane0, *plane1;
- int x, b0, b1;
- uint8_t *d;
-
- d = d1;
- plane0 = src1;
- plane1 = src1 + poffset;
- for(x = 0; x < w; x++) {
- b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
- b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
-#if DEPTH == 8
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- d[0] ^= color_xor;
- break;
- case 2:
- d[0] = color0;
- break;
- case 3:
- d[0] = color1;
- break;
- }
-#elif DEPTH == 16
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint16_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint16_t *)d)[0] = color0;
- break;
- case 3:
- ((uint16_t *)d)[0] = color1;
- break;
- }
-#elif DEPTH == 32
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint32_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint32_t *)d)[0] = color0;
- break;
- case 3:
- ((uint32_t *)d)[0] = color1;
- break;
- }
-#else
-#error unsupported depth
-#endif
- d += BPP;
- }
-}
-
#endif /* DEPTH != 15 */
diff --git a/hw/vhost.c b/hw/vhost.c
index 4778521102..5ece659f4a 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -55,7 +55,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
ram_addr_t ram_addr;
bit -= 1;
ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE;
- memory_region_set_dirty(section->mr, ram_addr);
+ memory_region_set_dirty(section->mr, ram_addr, VHOST_LOG_PAGE);
log &= ~(0x1ull << bit);
}
addr += VHOST_LOG_CHUNK;
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index bd16b97934..f8d2b1be04 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -38,7 +38,6 @@
#include "ppc.h"
#include "ppc4xx.h"
-#include "ppc440.h"
#include "ppc405.h"
#include "blockdev.h"
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 5b416c36ee..a5a439668b 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -346,6 +346,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
+ trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
+
if (sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 0b28a30b8c..4f2c3e4379 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -109,10 +109,9 @@ static void chr_event(void *opaque, int event)
static int virtconsole_initfn(VirtIOSerialPort *port)
{
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
- VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
- vcon->port.dev.info);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
- if (port->id == 0 && !info->is_console) {
+ if (port->id == 0 && !k->is_console) {
error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
return -1;
}
@@ -125,41 +124,63 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
return 0;
}
-static VirtIOSerialPortInfo virtconsole_info = {
- .qdev.name = "virtconsole",
- .qdev.size = sizeof(VirtConsole),
- .is_console = true,
- .init = virtconsole_initfn,
- .have_data = flush_buf,
- .guest_open = guest_open,
- .guest_close = guest_close,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", VirtConsole, chr),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property virtconsole_properties[] = {
+ DEFINE_PROP_CHR("chardev", VirtConsole, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtconsole_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
+
+ k->is_console = true;
+ k->init = virtconsole_initfn;
+ k->have_data = flush_buf;
+ k->guest_open = guest_open;
+ k->guest_close = guest_close;
+ dc->props = virtconsole_properties;
+}
+
+static TypeInfo virtconsole_info = {
+ .name = "virtconsole",
+ .parent = TYPE_VIRTIO_SERIAL_PORT,
+ .instance_size = sizeof(VirtConsole),
+ .class_init = virtconsole_class_init,
};
static void virtconsole_register(void)
{
- virtio_serial_port_qdev_register(&virtconsole_info);
+ type_register_static(&virtconsole_info);
}
device_init(virtconsole_register)
-static VirtIOSerialPortInfo virtserialport_info = {
- .qdev.name = "virtserialport",
- .qdev.size = sizeof(VirtConsole),
- .init = virtconsole_initfn,
- .have_data = flush_buf,
- .guest_open = guest_open,
- .guest_close = guest_close,
- .qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", VirtConsole, chr),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property virtserialport_properties[] = {
+ DEFINE_PROP_CHR("chardev", VirtConsole, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtserialport_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
+
+ k->init = virtconsole_initfn;
+ k->have_data = flush_buf;
+ k->guest_open = guest_open;
+ k->guest_close = guest_close;
+ dc->props = virtserialport_properties;
+}
+
+static TypeInfo virtserialport_info = {
+ .name = "virtserialport",
+ .parent = TYPE_VIRTIO_SERIAL_PORT,
+ .instance_size = sizeof(VirtConsole),
+ .class_init = virtserialport_class_init,
};
static void virtserialport_register(void)
{
- virtio_serial_port_qdev_register(&virtserialport_info);
+ type_register_static(&virtserialport_info);
}
device_init(virtserialport_register)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 8c2f460147..bc5e3a83d1 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -1030,7 +1030,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
memcpy(&n->mac[0], &conf->macaddr, sizeof(n->mac));
n->status = VIRTIO_NET_S_LINK_UP;
- n->nic = qemu_new_nic(&net_virtio_info, conf, dev->info->name, dev->id, n);
+ n->nic = qemu_new_nic(&net_virtio_info, conf, object_get_typename(OBJECT(dev)), dev->id, n);
qemu_format_nic_info_str(&n->nic->nc, conf->macaddr.a);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index caff0aa2eb..93fff54782 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -91,6 +91,9 @@
*/
#define wmb() do { } while (0)
+/* HACK for virtio to determine if it's running a big endian guest */
+bool virtio_is_big_endian(void);
+
/* virtio device */
static void virtio_pci_notify(void *opaque, uint16_t vector)
@@ -414,20 +417,35 @@ static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
{
VirtIOPCIProxy *proxy = opaque;
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+ uint16_t val;
if (addr < config)
return virtio_ioport_read(proxy, addr);
addr -= config;
- return virtio_config_readw(proxy->vdev, addr);
+ val = virtio_config_readw(proxy->vdev, addr);
+ if (virtio_is_big_endian()) {
+ /*
+ * virtio is odd, ioports are LE but config space is target native
+ * endian. However, in qemu, all PIO is LE, so we need to re-swap
+ * on BE targets
+ */
+ val = bswap16(val);
+ }
+ return val;
}
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
{
VirtIOPCIProxy *proxy = opaque;
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+ uint32_t val;
if (addr < config)
return virtio_ioport_read(proxy, addr);
addr -= config;
- return virtio_config_readl(proxy->vdev, addr);
+ val = virtio_config_readl(proxy->vdev, addr);
+ if (virtio_is_big_endian()) {
+ val = bswap32(val);
+ }
+ return val;
}
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
@@ -451,6 +469,9 @@ static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
return;
}
addr -= config;
+ if (virtio_is_big_endian()) {
+ val = bswap16(val);
+ }
virtio_config_writew(proxy->vdev, addr, val);
}
@@ -463,6 +484,9 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
return;
}
addr -= config;
+ if (virtio_is_big_endian()) {
+ val = bswap32(val);
+ }
virtio_config_writel(proxy->vdev, addr, val);
}
@@ -782,98 +806,136 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
return virtio_exit_pci(pci_dev);
}
-static PCIDeviceInfo virtio_info[] = {
- {
- .qdev.name = "virtio-blk-pci",
- .qdev.alias = "virtio-blk",
- .qdev.size = sizeof(VirtIOPCIProxy),
- .init = virtio_blk_init_pci,
- .exit = virtio_blk_exit_pci,
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
- .revision = VIRTIO_PCI_ABI_VERSION,
- .class_id = PCI_CLASS_STORAGE_SCSI,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
- DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
- DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
- DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
- VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
- DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = virtio_pci_reset,
- },{
- .qdev.name = "virtio-net-pci",
- .qdev.alias = "virtio-net",
- .qdev.size = sizeof(VirtIOPCIProxy),
- .init = virtio_net_init_pci,
- .exit = virtio_net_exit_pci,
- .romfile = "pxe-virtio.rom",
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = PCI_DEVICE_ID_VIRTIO_NET,
- .revision = VIRTIO_PCI_ABI_VERSION,
- .class_id = PCI_CLASS_NETWORK_ETHERNET,
- .qdev.props = (Property[]) {
- DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
- VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
- DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
- DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
- DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
- net.txtimer, TX_TIMER_INTERVAL),
- DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy,
- net.txburst, TX_BURST),
- DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = virtio_pci_reset,
- },{
- .qdev.name = "virtio-serial-pci",
- .qdev.alias = "virtio-serial",
- .qdev.size = sizeof(VirtIOPCIProxy),
- .init = virtio_serial_init_pci,
- .exit = virtio_serial_exit_pci,
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
- .revision = VIRTIO_PCI_ABI_VERSION,
- .class_id = PCI_CLASS_COMMUNICATION_OTHER,
- .qdev.props = (Property[]) {
- DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
- VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
- DEV_NVECTORS_UNSPECIFIED),
- DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
- DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
- DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy,
- serial.max_virtserial_ports, 31),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = virtio_pci_reset,
- },{
- .qdev.name = "virtio-balloon-pci",
- .qdev.alias = "virtio-balloon",
- .qdev.size = sizeof(VirtIOPCIProxy),
- .init = virtio_balloon_init_pci,
- .exit = virtio_balloon_exit_pci,
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
- .revision = VIRTIO_PCI_ABI_VERSION,
- .class_id = PCI_CLASS_MEMORY_RAM,
- .qdev.props = (Property[]) {
- DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
- DEFINE_PROP_END_OF_LIST(),
- },
- .qdev.reset = virtio_pci_reset,
- },{
- /* end of list */
- }
+static Property virtio_blk_properties[] = {
+ DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+ DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
+ DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+ DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_blk_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_blk_init_pci;
+ k->exit = virtio_blk_exit_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_STORAGE_SCSI;
+ dc->reset = virtio_pci_reset;
+ dc->props = virtio_blk_properties;
+}
+
+static TypeInfo virtio_blk_info = {
+ .name = "virtio-blk-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_blk_class_init,
+};
+
+static Property virtio_net_properties[] = {
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+ DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
+ DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
+ DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
+ DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_net_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_net_init_pci;
+ k->exit = virtio_net_exit_pci;
+ k->romfile = "pxe-virtio.rom";
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ dc->reset = virtio_pci_reset;
+ dc->props = virtio_net_properties;
+}
+
+static TypeInfo virtio_net_info = {
+ .name = "virtio-net-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_net_class_init,
+};
+
+static Property virtio_serial_properties[] = {
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
+ DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_serial_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_serial_init_pci;
+ k->exit = virtio_serial_exit_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+ dc->reset = virtio_pci_reset;
+ dc->props = virtio_serial_properties;
+}
+
+static TypeInfo virtio_serial_info = {
+ .name = "virtio-serial-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_serial_class_init,
+};
+
+static Property virtio_balloon_properties[] = {
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_balloon_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_balloon_init_pci;
+ k->exit = virtio_balloon_exit_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_MEMORY_RAM;
+ dc->reset = virtio_pci_reset;
+ dc->props = virtio_balloon_properties;
+}
+
+static TypeInfo virtio_balloon_info = {
+ .name = "virtio-balloon-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_balloon_class_init,
};
static void virtio_pci_register_devices(void)
{
- pci_qdev_register_many(virtio_info);
+ type_register_static(&virtio_blk_info);
+ type_register_static(&virtio_net_info);
+ type_register_static(&virtio_serial_info);
+ type_register_static(&virtio_balloon_info);
}
device_init(virtio_pci_register_devices)
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 32e46e98cb..61176299a3 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -133,12 +133,12 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
VirtIODevice *vdev)
{
- VirtIOSerialPortInfo *info;
+ VirtIOSerialPortClass *vsc;
assert(port);
assert(virtio_queue_ready(vq));
- info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
while (!port->throttled) {
unsigned int i;
@@ -157,7 +157,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
ssize_t ret;
buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
- ret = info->have_data(port,
+ ret = vsc->have_data(port,
port->elem.out_sg[i].iov_base
+ port->iov_offset,
buf_size);
@@ -176,7 +176,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
* 1: chardevs can notify frondends
* 2: the guest driver does not spin in these cases
*/
- if (!info->is_console) {
+ if (!vsc->is_console) {
virtio_serial_throttle_port(port, true);
}
port->iov_idx = i;
@@ -331,7 +331,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
{
struct VirtIOSerialPort *port;
- struct VirtIOSerialPortInfo *info;
+ VirtIOSerialPortClass *vsc;
struct virtio_console_control cpkt, *gcpkt;
uint8_t *buffer;
size_t buffer_len;
@@ -373,7 +373,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
trace_virtio_serial_handle_control_message_port(port->id);
- info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
switch(cpkt.event) {
case VIRTIO_CONSOLE_PORT_READY:
@@ -389,7 +389,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
* this port is a console port so that the guest can hook it
* up to hvc.
*/
- if (info->is_console) {
+ if (vsc->is_console) {
send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
}
@@ -418,21 +418,21 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
* initialised. If some app is interested in knowing about
* this event, let it know.
*/
- if (info->guest_ready) {
- info->guest_ready(port);
+ if (vsc->guest_ready) {
+ vsc->guest_ready(port);
}
break;
case VIRTIO_CONSOLE_PORT_OPEN:
port->guest_connected = cpkt.value;
- if (cpkt.value && info->guest_open) {
+ if (cpkt.value && vsc->guest_open) {
/* Send the guest opened notification if an app is interested */
- info->guest_open(port);
+ vsc->guest_open(port);
}
- if (!cpkt.value && info->guest_close) {
+ if (!cpkt.value && vsc->guest_close) {
/* Send the guest closed notification if an app is interested */
- info->guest_close(port);
+ vsc->guest_close(port);
}
break;
}
@@ -748,10 +748,10 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
}
-static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int virtser_port_qdev_init(DeviceState *qdev)
{
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
- VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev, base);
+ VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
int ret, max_nr_ports;
bool plugging_port0;
@@ -759,14 +759,14 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
port->vser = bus->vser;
port->bh = qemu_bh_new(flush_queued_data_bh, port);
- assert(info->have_data);
+ assert(vsc->have_data);
/*
* Is the first console port we're seeing? If so, put it up at
* location 0. This is done for backward compatibility (old
* kernel, new qemu).
*/
- plugging_port0 = info->is_console && !find_port_by_id(port->vser, 0);
+ plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
if (find_port_by_id(port->vser, port->id)) {
error_report("virtio-serial-bus: A port already exists at id %u",
@@ -793,7 +793,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
return -1;
}
- ret = info->init(port);
+ ret = vsc->init(port);
if (ret) {
return ret;
}
@@ -823,8 +823,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
static int virtser_port_qdev_exit(DeviceState *qdev)
{
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
- VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
- port->dev.info);
+ VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
VirtIOSerial *vser = port->vser;
qemu_bh_delete(port->bh);
@@ -832,21 +831,12 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
QTAILQ_REMOVE(&vser->ports, port, next);
- if (info->exit) {
- info->exit(port);
+ if (vsc->exit) {
+ vsc->exit(port);
}
return 0;
}
-void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info)
-{
- info->qdev.init = virtser_port_qdev_init;
- info->qdev.bus_info = &virtser_bus_info;
- info->qdev.exit = virtser_port_qdev_exit;
- info->qdev.unplug = qdev_simple_unplug_cb;
- qdev_register(&info->qdev);
-}
-
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
{
VirtIOSerial *vser;
@@ -940,3 +930,28 @@ void virtio_serial_exit(VirtIODevice *vdev)
virtio_cleanup(vdev);
}
+
+static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = virtser_port_qdev_init;
+ k->bus_info = &virtser_bus_info;
+ k->exit = virtser_port_qdev_exit;
+ k->unplug = qdev_simple_unplug_cb;
+}
+
+static TypeInfo virtio_serial_port_type_info = {
+ .name = TYPE_VIRTIO_SERIAL_PORT,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(VirtIOSerialPort),
+ .abstract = true,
+ .class_size = sizeof(VirtIOSerialPortClass),
+ .class_init = virtio_serial_port_class_init,
+};
+
+static void virtio_serial_register_devices(void)
+{
+ type_register_static(&virtio_serial_port_type_info);
+}
+
+device_init(virtio_serial_register_devices);
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index ab138038c0..16e39820a2 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -62,10 +62,52 @@ struct virtio_serial_conf {
/* == In-qemu interface == */
+#define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port"
+#define VIRTIO_SERIAL_PORT(obj) \
+ OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT)
+#define VIRTIO_SERIAL_PORT_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VirtIOSerialPortClass, (klass), TYPE_VIRTIO_SERIAL_PORT)
+#define VIRTIO_SERIAL_PORT_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VirtIOSerialPortClass, (obj), TYPE_VIRTIO_SERIAL_PORT)
+
typedef struct VirtIOSerial VirtIOSerial;
typedef struct VirtIOSerialBus VirtIOSerialBus;
typedef struct VirtIOSerialPort VirtIOSerialPort;
-typedef struct VirtIOSerialPortInfo VirtIOSerialPortInfo;
+
+typedef struct VirtIOSerialPortClass {
+ DeviceClass parent_class;
+
+ /* Is this a device that binds with hvc in the guest? */
+ bool is_console;
+
+ /*
+ * The per-port (or per-app) init function that's called when a
+ * new device is found on the bus.
+ */
+ int (*init)(VirtIOSerialPort *port);
+ /*
+ * Per-port exit function that's called when a port gets
+ * hot-unplugged or removed.
+ */
+ int (*exit)(VirtIOSerialPort *port);
+
+ /* Callbacks for guest events */
+ /* Guest opened device. */
+ void (*guest_open)(VirtIOSerialPort *port);
+ /* Guest closed device. */
+ void (*guest_close)(VirtIOSerialPort *port);
+
+ /* Guest is now ready to accept data (virtqueues set up). */
+ void (*guest_ready)(VirtIOSerialPort *port);
+
+ /*
+ * Guest wrote some data to the port. This data is handed over to
+ * the app via this callback. The app can return a size less than
+ * 'len'. In this case, throttling will be enabled for this port.
+ */
+ ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
+ size_t len);
+} VirtIOSerialPortClass;
/*
* This is the state that's shared between all the ports. Some of the
@@ -131,50 +173,9 @@ struct VirtIOSerialPort {
bool throttled;
};
-struct VirtIOSerialPortInfo {
- DeviceInfo qdev;
-
- /* Is this a device that binds with hvc in the guest? */
- bool is_console;
-
- /*
- * The per-port (or per-app) init function that's called when a
- * new device is found on the bus.
- */
- int (*init)(VirtIOSerialPort *port);
- /*
- * Per-port exit function that's called when a port gets
- * hot-unplugged or removed.
- */
- int (*exit)(VirtIOSerialPort *port);
-
- /* Callbacks for guest events */
- /* Guest opened device. */
- void (*guest_open)(VirtIOSerialPort *port);
- /* Guest closed device. */
- void (*guest_close)(VirtIOSerialPort *port);
-
- /* Guest is now ready to accept data (virtqueues set up). */
- void (*guest_ready)(VirtIOSerialPort *port);
-
- /*
- * Guest wrote some data to the port. This data is handed over to
- * the app via this callback. The app can return a size less than
- * 'len'. In this case, throttling will be enabled for this port.
- */
- ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
- size_t len);
-};
-
/* Interface to the virtio-serial bus */
/*
- * Individual ports/apps should call this function to register the port
- * with the virtio-serial bus
- */
-void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info);
-
-/*
* Open a connection to the port
* Returns 0 on success (always).
*/
diff --git a/hw/virtio.c b/hw/virtio.c
index 81ecc40b31..74cc038af9 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -539,7 +539,7 @@ uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
- memcpy(&val, vdev->config + addr, sizeof(val));
+ val = ldub_p(vdev->config + addr);
return val;
}
@@ -552,7 +552,7 @@ uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
- memcpy(&val, vdev->config + addr, sizeof(val));
+ val = lduw_p(vdev->config + addr);
return val;
}
@@ -565,7 +565,7 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
- memcpy(&val, vdev->config + addr, sizeof(val));
+ val = ldl_p(vdev->config + addr);
return val;
}
@@ -576,7 +576,7 @@ void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
if (addr > (vdev->config_len - sizeof(val)))
return;
- memcpy(vdev->config + addr, &val, sizeof(val));
+ stb_p(vdev->config + addr, val);
if (vdev->set_config)
vdev->set_config(vdev, vdev->config);
@@ -589,7 +589,7 @@ void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
if (addr > (vdev->config_len - sizeof(val)))
return;
- memcpy(vdev->config + addr, &val, sizeof(val));
+ stw_p(vdev->config + addr, val);
if (vdev->set_config)
vdev->set_config(vdev, vdev->config);
@@ -602,7 +602,7 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
if (addr > (vdev->config_len - sizeof(val)))
return;
- memcpy(vdev->config + addr, &val, sizeof(val));
+ stl_p(vdev->config + addr, val);
if (vdev->set_config)
vdev->set_config(vdev, vdev->config);
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index 1113f33d68..fda4f89a76 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -254,6 +254,8 @@ static void vmmouse_reset(DeviceState *d)
s->status = 0xffff;
s->queue_size = VMMOUSE_QUEUE_SIZE;
+
+ vmmouse_disable(s);
}
static int vmmouse_initfn(ISADevice *dev)
@@ -269,21 +271,31 @@ static int vmmouse_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo vmmouse_info = {
- .init = vmmouse_initfn,
- .qdev.name = "vmmouse",
- .qdev.size = sizeof(VMMouseState),
- .qdev.vmsd = &vmstate_vmmouse,
- .qdev.no_user = 1,
- .qdev.reset = vmmouse_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_PTR("ps2_mouse", VMMouseState, ps2_mouse),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property vmmouse_properties[] = {
+ DEFINE_PROP_PTR("ps2_mouse", VMMouseState, ps2_mouse),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmmouse_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = vmmouse_initfn;
+ dc->no_user = 1;
+ dc->reset = vmmouse_reset;
+ dc->vmsd = &vmstate_vmmouse;
+ dc->props = vmmouse_properties;
+}
+
+static TypeInfo vmmouse_info = {
+ .name = "vmmouse",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(VMMouseState),
+ .class_init = vmmouse_class_initfn,
};
static void vmmouse_dev_register(void)
{
- isa_qdev_register(&vmmouse_info);
+ type_register_static(&vmmouse_info);
}
device_init(vmmouse_dev_register)
diff --git a/hw/vmport.c b/hw/vmport.c
index 0a3dbc5ef5..a2c45e1950 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -144,15 +144,23 @@ static int vmport_initfn(ISADevice *dev)
return 0;
}
-static ISADeviceInfo vmport_info = {
- .qdev.name = "vmport",
- .qdev.size = sizeof(VMPortState),
- .qdev.no_user = 1,
- .init = vmport_initfn,
+static void vmport_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = vmport_initfn;
+ dc->no_user = 1;
+}
+
+static TypeInfo vmport_info = {
+ .name = "vmport",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(VMPortState),
+ .class_init = vmport_class_initfn,
};
static void vmport_dev_register(void)
{
- isa_qdev_register(&vmport_info);
+ type_register_static(&vmport_info);
}
device_init(vmport_dev_register)
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index b1885c3c19..3f3eb21d02 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1199,24 +1199,32 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
return 0;
}
-static PCIDeviceInfo vmsvga_info = {
- .qdev.name = "vmware-svga",
- .qdev.size = sizeof(struct pci_vmsvga_state_s),
- .qdev.vmsd = &vmstate_vmware_vga,
- .qdev.reset = vmsvga_reset,
- .no_hotplug = 1,
- .init = pci_vmsvga_initfn,
- .romfile = "vgabios-vmware.bin",
-
- .vendor_id = PCI_VENDOR_ID_VMWARE,
- .device_id = SVGA_PCI_DEVICE_ID,
- .class_id = PCI_CLASS_DISPLAY_VGA,
- .subsystem_vendor_id = PCI_VENDOR_ID_VMWARE,
- .subsystem_id = SVGA_PCI_DEVICE_ID,
+static void vmsvga_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = pci_vmsvga_initfn;
+ k->romfile = "vgabios-vmware.bin";
+ k->vendor_id = PCI_VENDOR_ID_VMWARE;
+ k->device_id = SVGA_PCI_DEVICE_ID;
+ k->class_id = PCI_CLASS_DISPLAY_VGA;
+ k->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
+ k->subsystem_id = SVGA_PCI_DEVICE_ID;
+ dc->reset = vmsvga_reset;
+ dc->vmsd = &vmstate_vmware_vga;
+}
+
+static TypeInfo vmsvga_info = {
+ .name = "vmware-svga",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(struct pci_vmsvga_state_s),
+ .class_init = vmsvga_class_init,
};
static void vmsvga_register(void)
{
- pci_qdev_register(&vmsvga_info);
+ type_register_static(&vmsvga_info);
}
device_init(vmsvga_register);
diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h
index db11cbfac8..000fbddc0f 100644
--- a/hw/vmware_vga.h
+++ b/hw/vmware_vga.h
@@ -8,12 +8,8 @@ static inline DeviceState *pci_vmsvga_init(PCIBus *bus)
{
PCIDevice *dev;
- dev = pci_try_create(bus, -1, "vmware-svga");
- if (!dev || qdev_init(&dev->qdev) < 0) {
- return NULL;
- } else {
- return &dev->qdev;
- }
+ dev = pci_create_simple(bus, -1, "vmware-svga");
+ return &dev->qdev;
}
#endif
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 7fb88a53bf..aa0954f487 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -346,20 +346,29 @@ void vt82c686b_ac97_init(PCIBus *bus, int devfn)
qdev_init_nofail(&dev->qdev);
}
-static PCIDeviceInfo via_ac97_info = {
- .qdev.name = "VT82C686B_AC97",
- .qdev.desc = "AC97",
- .qdev.size = sizeof(VT686AC97State),
- .init = vt82c686b_ac97_initfn,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_AC97,
- .revision = 0x50,
- .class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
+static void via_ac97_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = vt82c686b_ac97_initfn;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_AC97;
+ k->revision = 0x50;
+ k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ dc->desc = "AC97";
+}
+
+static TypeInfo via_ac97_info = {
+ .name = "VT82C686B_AC97",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VT686AC97State),
+ .class_init = via_ac97_class_init,
};
static void vt82c686b_ac97_register(void)
{
- pci_qdev_register(&via_ac97_info);
+ type_register_static(&via_ac97_info);
}
device_init(vt82c686b_ac97_register);
@@ -385,20 +394,29 @@ void vt82c686b_mc97_init(PCIBus *bus, int devfn)
qdev_init_nofail(&dev->qdev);
}
-static PCIDeviceInfo via_mc97_info = {
- .qdev.name = "VT82C686B_MC97",
- .qdev.desc = "MC97",
- .qdev.size = sizeof(VT686MC97State),
- .init = vt82c686b_mc97_initfn,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_MC97,
- .class_id = PCI_CLASS_COMMUNICATION_OTHER,
- .revision = 0x30,
+static void via_mc97_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = vt82c686b_mc97_initfn;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_MC97;
+ k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+ k->revision = 0x30;
+ dc->desc = "MC97";
+}
+
+static TypeInfo via_mc97_info = {
+ .name = "VT82C686B_MC97",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VT686MC97State),
+ .class_init = via_mc97_class_init,
};
static void vt82c686b_mc97_register(void)
{
- pci_qdev_register(&via_mc97_info);
+ type_register_static(&via_mc97_info);
}
device_init(vt82c686b_mc97_register);
@@ -451,26 +469,37 @@ i2c_bus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
return s->smb.smbus;
}
-static PCIDeviceInfo via_pm_info = {
- .qdev.name = "VT82C686B_PM",
- .qdev.desc = "PM",
- .qdev.size = sizeof(VT686PMState),
- .qdev.vmsd = &vmstate_acpi,
- .init = vt82c686b_pm_initfn,
- .config_write = pm_write_config,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_ACPI,
- .class_id = PCI_CLASS_BRIDGE_OTHER,
- .revision = 0x40,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property via_pm_properties[] = {
+ DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void via_pm_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = vt82c686b_pm_initfn;
+ k->config_write = pm_write_config;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_ACPI;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+ k->revision = 0x40;
+ dc->desc = "PM";
+ dc->vmsd = &vmstate_acpi;
+ dc->props = via_pm_properties;
+}
+
+static TypeInfo via_pm_info = {
+ .name = "VT82C686B_PM",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VT686PMState),
+ .class_init = via_pm_class_init,
};
static void vt82c686b_pm_register(void)
{
- pci_qdev_register(&via_pm_info);
+ type_register_static(&via_pm_info);
}
device_init(vt82c686b_pm_register);
@@ -519,22 +548,31 @@ ISABus *vt82c686b_init(PCIBus *bus, int devfn)
return DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&d->qdev, "isa.0"));
}
-static PCIDeviceInfo via_info = {
- .qdev.name = "VT82C686B",
- .qdev.desc = "ISA bridge",
- .qdev.size = sizeof(VT82C686BState),
- .qdev.vmsd = &vmstate_via,
- .qdev.no_user = 1,
- .init = vt82c686b_initfn,
- .config_write = vt82c686b_write_config,
- .vendor_id = PCI_VENDOR_ID_VIA,
- .device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE,
- .class_id = PCI_CLASS_BRIDGE_ISA,
- .revision = 0x40,
+static void via_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = vt82c686b_initfn;
+ k->config_write = vt82c686b_write_config;
+ k->vendor_id = PCI_VENDOR_ID_VIA;
+ k->device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+ k->revision = 0x40;
+ dc->desc = "ISA bridge";
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_via;
+}
+
+static TypeInfo via_info = {
+ .name = "VT82C686B",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VT82C686BState),
+ .class_init = via_class_init,
};
static void vt82c686b_register(void)
{
- pci_qdev_register(&via_info);
+ type_register_static(&via_info);
}
device_init(vt82c686b_register);
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 20d8673186..41325f0955 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -143,7 +143,7 @@ static void i6300esb_disable_timer(I6300State *d)
static void i6300esb_reset(DeviceState *dev)
{
- PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
+ PCIDevice *pdev = PCI_DEVICE(dev);
I6300State *d = DO_UPCAST(I6300State, dev, pdev);
i6300esb_debug("I6300State = %p\n", d);
@@ -425,24 +425,33 @@ static WatchdogTimerModel model = {
.wdt_description = "Intel 6300ESB",
};
-static PCIDeviceInfo i6300esb_info = {
- .qdev.name = "i6300esb",
- .qdev.size = sizeof(I6300State),
- .qdev.vmsd = &vmstate_i6300esb,
- .qdev.reset = i6300esb_reset,
- .config_read = i6300esb_config_read,
- .config_write = i6300esb_config_write,
- .init = i6300esb_init,
- .exit = i6300esb_exit,
- .vendor_id = PCI_VENDOR_ID_INTEL,
- .device_id = PCI_DEVICE_ID_INTEL_ESB_9,
- .class_id = PCI_CLASS_SYSTEM_OTHER,
+static void i6300esb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->config_read = i6300esb_config_read;
+ k->config_write = i6300esb_config_write;
+ k->init = i6300esb_init;
+ k->exit = i6300esb_exit;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_ESB_9;
+ k->class_id = PCI_CLASS_SYSTEM_OTHER;
+ dc->reset = i6300esb_reset;
+ dc->vmsd = &vmstate_i6300esb;
+}
+
+static TypeInfo i6300esb_info = {
+ .name = "i6300esb",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(I6300State),
+ .class_init = i6300esb_class_init,
};
static void i6300esb_register_devices(void)
{
watchdog_add_model(&model);
- pci_qdev_register(&i6300esb_info);
+ type_register_static(&i6300esb_info);
}
device_init(i6300esb_register_devices);
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index ba1d92d615..8faa2316c9 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -120,18 +120,26 @@ static WatchdogTimerModel model = {
.wdt_description = "iBASE 700",
};
-static ISADeviceInfo wdt_ib700_info = {
- .qdev.name = "ib700",
- .qdev.size = sizeof(IB700State),
- .qdev.vmsd = &vmstate_ib700,
- .qdev.reset = wdt_ib700_reset,
- .init = wdt_ib700_init,
+static void wdt_ib700_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ ic->init = wdt_ib700_init;
+ dc->reset = wdt_ib700_reset;
+ dc->vmsd = &vmstate_ib700;
+}
+
+static TypeInfo wdt_ib700_info = {
+ .name = "ib700",
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(IB700State),
+ .class_init = wdt_ib700_class_init,
};
static void wdt_ib700_register_devices(void)
{
watchdog_add_model(&model);
- isa_qdev_register(&wdt_ib700_info);
+ type_register_static(&wdt_ib700_info);
}
device_init(wdt_ib700_register_devices);
diff --git a/hw/wm8750.c b/hw/wm8750.c
index 9fbdf3d54b..18afa4c1ac 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -24,7 +24,7 @@ typedef struct {
} WMRate;
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
uint8_t i2c_data[2];
int i2c_len;
QEMUSoundCard card;
@@ -254,7 +254,7 @@ static void wm8750_clk_update(WM8750State *s, int ext)
}
}
-static void wm8750_reset(i2c_slave *i2c)
+static void wm8750_reset(I2CSlave *i2c)
{
WM8750State *s = (WM8750State *) i2c;
s->rate = &wm_rate_table[0];
@@ -297,7 +297,7 @@ static void wm8750_reset(i2c_slave *i2c)
s->i2c_len = 0;
}
-static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
+static void wm8750_event(I2CSlave *i2c, enum i2c_event event)
{
WM8750State *s = (WM8750State *) i2c;
@@ -354,7 +354,7 @@ static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
#define WM8750_ROUT2V 0x29
#define WM8750_MOUTV 0x2a
-static int wm8750_tx(i2c_slave *i2c, uint8_t data)
+static int wm8750_tx(I2CSlave *i2c, uint8_t data)
{
WM8750State *s = (WM8750State *) i2c;
uint8_t cmd;
@@ -554,7 +554,7 @@ static int wm8750_tx(i2c_slave *i2c, uint8_t data)
return 0;
}
-static int wm8750_rx(i2c_slave *i2c)
+static int wm8750_rx(I2CSlave *i2c)
{
return 0x00;
}
@@ -609,7 +609,7 @@ static const VMStateDescription vmstate_wm8750 = {
}
};
-static int wm8750_init(i2c_slave *i2c)
+static int wm8750_init(I2CSlave *i2c)
{
WM8750State *s = FROM_I2C_SLAVE(WM8750State, i2c);
@@ -620,7 +620,7 @@ static int wm8750_init(i2c_slave *i2c)
}
#if 0
-static void wm8750_fini(i2c_slave *i2c)
+static void wm8750_fini(I2CSlave *i2c)
{
WM8750State *s = (WM8750State *) i2c;
wm8750_reset(&s->i2c);
@@ -689,19 +689,28 @@ void wm8750_set_bclk_in(void *opaque, int new_hz)
wm8750_clk_update(s, 1);
}
-static I2CSlaveInfo wm8750_info = {
- .qdev.name = "wm8750",
- .qdev.size = sizeof(WM8750State),
- .qdev.vmsd = &vmstate_wm8750,
- .init = wm8750_init,
- .event = wm8750_event,
- .recv = wm8750_rx,
- .send = wm8750_tx
+static void wm8750_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
+
+ sc->init = wm8750_init;
+ sc->event = wm8750_event;
+ sc->recv = wm8750_rx;
+ sc->send = wm8750_tx;
+ dc->vmsd = &vmstate_wm8750;
+}
+
+static TypeInfo wm8750_info = {
+ .name = "wm8750",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(WM8750State),
+ .class_init = wm8750_class_init,
};
static void wm8750_register_devices(void)
{
- i2c_register_slave(&wm8750_info);
+ type_register_static(&wm8750_info);
}
device_init(wm8750_register_devices)
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index e62eaef7d1..e7571022e4 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -372,25 +372,33 @@ static void platform_reset(DeviceState *dev)
platform_fixed_ioport_reset(s);
}
-static PCIDeviceInfo xen_platform_info = {
- .init = xen_platform_initfn,
- .qdev.name = "xen-platform",
- .qdev.desc = "XEN platform pci device",
- .qdev.size = sizeof(PCIXenPlatformState),
- .qdev.vmsd = &vmstate_xen_platform,
- .qdev.reset = platform_reset,
-
- .vendor_id = PCI_VENDOR_ID_XEN,
- .device_id = PCI_DEVICE_ID_XEN_PLATFORM,
- .class_id = PCI_CLASS_OTHERS << 8 | 0x80,
- .subsystem_vendor_id = PCI_VENDOR_ID_XEN,
- .subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
- .revision = 1,
+static void xen_platform_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = xen_platform_initfn;
+ k->vendor_id = PCI_VENDOR_ID_XEN;
+ k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
+ k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
+ k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
+ k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
+ k->revision = 1;
+ dc->desc = "XEN platform pci device";
+ dc->reset = platform_reset;
+ dc->vmsd = &vmstate_xen_platform;
+}
+
+static TypeInfo xen_platform_info = {
+ .name = "xen-platform",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIXenPlatformState),
+ .class_init = xen_platform_class_init,
};
static void xen_platform_register(void)
{
- pci_qdev_register(&xen_platform_info);
+ type_register_static(&xen_platform_info);
}
device_init(xen_platform_register);
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000000..d395b1cc2d
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,433 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+ fprintf(stderr, (message), ## args); \
+ } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL 0x00000000 /* MAC Configuration */
+#define XGMAC_FRAME_FILTER 0x00000001 /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL 0x00000006 /* MAC Flow Control */
+#define XGMAC_VLAN_TAG 0x00000007 /* VLAN Tags */
+#define XGMAC_VERSION 0x00000008 /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL 0x00000009
+#define XGMAC_LPI_CTRL 0x0000000a /* LPI Control and Status */
+#define XGMAC_LPI_TIMER 0x0000000b /* LPI Timers Control */
+#define XGMAC_TX_PACE 0x0000000c /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH 0x0000000d /* VLAN Hash Table */
+#define XGMAC_DEBUG 0x0000000e /* Debug */
+#define XGMAC_INT_STATUS 0x0000000f /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n) ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH 16
+/* Operation Mode */
+#define XGMAC_OPMODE (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg) (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg) (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE 0x000003c0 /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND 0x000003c1 /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND 0x000003c2 /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR 0x000003c3 /* Receive List Base */
+#define DMA_TX_BASE_ADDR 0x000003c4 /* Transmit List Base */
+#define DMA_STATUS 0x000003c5 /* Status Register */
+#define DMA_CONTROL 0x000003c6 /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA 0x000003c7 /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR 0x000003c8 /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER 0x000003c9
+#define DMA_AXI_BUS 0x000003ca /* AXI Bus Mode */
+#define DMA_AXI_STATUS 0x000003cb /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR 0x000003d2 /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR 0x000003d3 /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR 0x000003d4 /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR 0x000003d5 /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE 0x000003d6 /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
+#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT 20
+#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT 17
+#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */
+#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */
+#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */
+#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */
+#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */
+#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */
+#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */
+#define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */
+#define DMA_CONTROL_DFF 0x01000000 /* Disable flush of rx frames */
+
+struct desc {
+ uint32_t ctl_stat;
+ uint16_t buffer1_size;
+ uint16_t buffer2_size;
+ uint32_t buffer1_addr;
+ uint32_t buffer2_addr;
+ uint32_t ext_stat;
+ uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct RxTxStats {
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+
+ uint64_t rx;
+ uint64_t rx_bcast;
+ uint64_t rx_mcast;
+} RxTxStats;
+
+typedef struct XgmacState {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ qemu_irq sbd_irq;
+ qemu_irq pmt_irq;
+ qemu_irq mci_irq;
+ NICState *nic;
+ NICConf conf;
+
+ struct RxTxStats stats;
+ uint32_t regs[R_MAX];
+} XgmacState;
+
+const VMStateDescription vmstate_rxtx_stats = {
+ .name = "xgmac_stats",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(rx_bytes, RxTxStats),
+ VMSTATE_UINT64(tx_bytes, RxTxStats),
+ VMSTATE_UINT64(rx, RxTxStats),
+ VMSTATE_UINT64(rx_bcast, RxTxStats),
+ VMSTATE_UINT64(rx_mcast, RxTxStats),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+ .name = "xgmac",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(stats, XgmacState, 0, vmstate_rxtx_stats, RxTxStats),
+ VMSTATE_UINT32_ARRAY(regs, XgmacState, R_MAX),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void xgmac_read_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+ uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+ s->regs[DMA_CUR_TX_DESC_ADDR];
+ cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+ int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+ uint32_t addr = s->regs[reg];
+
+ if (!rx && (d->ctl_stat & 0x00200000)) {
+ s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+ } else if (rx && (d->buffer1_size & 0x8000)) {
+ s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+ } else {
+ s->regs[reg] += sizeof(*d);
+ }
+ cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct XgmacState *s)
+{
+ struct desc bd;
+ int frame_size;
+ int len;
+ uint8_t frame[8192];
+ uint8_t *ptr;
+
+ ptr = frame;
+ frame_size = 0;
+ while (1) {
+ xgmac_read_desc(s, &bd, 0);
+ if ((bd.ctl_stat & 0x80000000) == 0) {
+ /* Run out of descriptors to transmit. */
+ break;
+ }
+ len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+ if ((bd.buffer1_size & 0xfff) > 2048) {
+ DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+ "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+ __func__, bd.buffer1_size & 0xfff);
+ }
+ if ((bd.buffer2_size & 0xfff) != 0) {
+ DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+ "xgmac buffer 2 len on send != 0 (0x%x)\n",
+ __func__, bd.buffer2_size & 0xfff);
+ }
+ if (len >= sizeof(frame)) {
+ DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+ "buffer\n" , __func__, len, sizeof(frame));
+ DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+ __func__, bd.buffer1_size, bd.buffer2_size);
+ }
+
+ cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+ ptr += len;
+ frame_size += len;
+ if (bd.ctl_stat & 0x20000000) {
+ /* Last buffer in frame. */
+ qemu_send_packet(&s->nic->nc, frame, len);
+ ptr = frame;
+ frame_size = 0;
+ s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+ }
+ bd.ctl_stat &= ~0x80000000;
+ /* Write back the modified descriptor. */
+ xgmac_write_desc(s, &bd, 0);
+ }
+}
+
+static void enet_update_irq(struct XgmacState *s)
+{
+ int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+ qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+ struct XgmacState *s = opaque;
+ uint64_t r = 0;
+ addr >>= 2;
+
+ switch (addr) {
+ case XGMAC_VERSION:
+ r = 0x1012;
+ break;
+ default:
+ if (addr < ARRAY_SIZE(s->regs)) {
+ r = s->regs[addr];
+ }
+ break;
+ }
+ return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
+{
+ struct XgmacState *s = opaque;
+
+ addr >>= 2;
+ switch (addr) {
+ case DMA_BUS_MODE:
+ s->regs[DMA_BUS_MODE] = value & ~0x1;
+ break;
+ case DMA_XMT_POLL_DEMAND:
+ xgmac_enet_send(s);
+ break;
+ case DMA_STATUS:
+ s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+ break;
+ case DMA_RCV_BASE_ADDR:
+ s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+ break;
+ case DMA_TX_BASE_ADDR:
+ s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+ break;
+ default:
+ if (addr < ARRAY_SIZE(s->regs)) {
+ s->regs[addr] = value;
+ }
+ break;
+ }
+ enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+ .read = enet_read,
+ .write = enet_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+ struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+ /* RX enabled? */
+ return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+ struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+ static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff};
+ int unicast, broadcast, multicast;
+ struct desc bd;
+ ssize_t ret;
+
+ unicast = ~buf[0] & 0x1;
+ broadcast = memcmp(buf, sa_bcast, 6) == 0;
+ multicast = !unicast && !broadcast;
+ if (size < 12) {
+ s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+ ret = -1;
+ goto out;
+ }
+
+ xgmac_read_desc(s, &bd, 1);
+ if ((bd.ctl_stat & 0x80000000) == 0) {
+ s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+ ret = size;
+ goto out;
+ }
+
+ cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+ /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+ size += 4;
+ bd.ctl_stat = (size << 16) | 0x300;
+ xgmac_write_desc(s, &bd, 1);
+
+ s->stats.rx_bytes += size;
+ s->stats.rx++;
+ if (multicast) {
+ s->stats.rx_mcast++;
+ } else if (broadcast) {
+ s->stats.rx_bcast++;
+ }
+
+ s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+ ret = size;
+
+out:
+ enet_update_irq(s);
+ return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+ struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+ s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+ .type = NET_CLIENT_TYPE_NIC,
+ .size = sizeof(NICState),
+ .can_receive = eth_can_rx,
+ .receive = eth_rx,
+ .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+ struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
+
+ memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_irq(dev, &s->sbd_irq);
+ sysbus_init_irq(dev, &s->pmt_irq);
+ sysbus_init_irq(dev, &s->mci_irq);
+
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+ s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+ s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+ s->conf.macaddr.a[4];
+ s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+ (s->conf.macaddr.a[2] << 16) |
+ (s->conf.macaddr.a[1] << 8) |
+ s->conf.macaddr.a[0];
+
+ return 0;
+}
+
+static Property xgmac_properties[] = {
+ DEFINE_NIC_PROPERTIES(struct XgmacState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xgmac_enet_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ sbc->init = xgmac_enet_init;
+ dc->vmsd = &vmstate_xgmac;
+ dc->props = xgmac_properties;
+}
+
+static TypeInfo xgmac_enet_info = {
+ .name = "xgmac",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct XgmacState),
+ .class_init = xgmac_enet_class_init,
+};
+
+static void xgmac_enet_register(void)
+{
+ type_register_static(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index 0da20d9565..e8a53123f9 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -486,20 +486,31 @@ static int xilinx_axidma_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo axidma_info = {
- .init = xilinx_axidma_init,
- .qdev.name = "xilinx,axidma",
- .qdev.size = sizeof(struct XilinxAXIDMA),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("freqhz", struct XilinxAXIDMA, freqhz, 50000000),
- DEFINE_PROP_PTR("dmach", struct XilinxAXIDMA, dmach),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property axidma_properties[] = {
+ DEFINE_PROP_UINT32("freqhz", struct XilinxAXIDMA, freqhz, 50000000),
+ DEFINE_PROP_PTR("dmach", struct XilinxAXIDMA, dmach),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void axidma_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_axidma_init;
+ dc->props = axidma_properties;
+}
+
+static TypeInfo axidma_info = {
+ .name = "xilinx,axidma",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct XilinxAXIDMA),
+ .class_init = axidma_class_init,
};
static void xilinx_axidma_register(void)
{
- sysbus_register_withprop(&axidma_info);
+ type_register_static(&axidma_info);
}
device_init(xilinx_axidma_register)
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index a2eb3e6d5b..1ce2db4510 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -856,7 +856,7 @@ static int xilinx_enet_init(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
tdk_init(&s->TEMAC.phy);
@@ -870,22 +870,33 @@ static int xilinx_enet_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo xilinx_enet_info = {
- .init = xilinx_enet_init,
- .qdev.name = "xilinx,axienet",
- .qdev.size = sizeof(struct XilinxAXIEnet),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("phyaddr", struct XilinxAXIEnet, c_phyaddr, 7),
- DEFINE_PROP_UINT32("c_rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
- DEFINE_PROP_UINT32("c_txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
- DEFINE_PROP_PTR("dmach", struct XilinxAXIEnet, dmach),
- DEFINE_NIC_PROPERTIES(struct XilinxAXIEnet, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xilinx_enet_properties[] = {
+ DEFINE_PROP_UINT32("phyaddr", struct XilinxAXIEnet, c_phyaddr, 7),
+ DEFINE_PROP_UINT32("c_rxmem", struct XilinxAXIEnet, c_rxmem, 0x1000),
+ DEFINE_PROP_UINT32("c_txmem", struct XilinxAXIEnet, c_txmem, 0x1000),
+ DEFINE_PROP_PTR("dmach", struct XilinxAXIEnet, dmach),
+ DEFINE_NIC_PROPERTIES(struct XilinxAXIEnet, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xilinx_enet_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_enet_init;
+ dc->props = xilinx_enet_properties;
+}
+
+static TypeInfo xilinx_enet_info = {
+ .name = "xilinx,axienet",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct XilinxAXIEnet),
+ .class_init = xilinx_enet_class_init,
};
static void xilinx_enet_register(void)
{
- sysbus_register_withprop(&xilinx_enet_info);
+ type_register_static(&xilinx_enet_info);
}
device_init(xilinx_enet_register)
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 6777254f35..499feef488 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -221,26 +221,37 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
- dev->qdev.info->name, dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
}
-static SysBusDeviceInfo xilinx_ethlite_info = {
- .init = xilinx_ethlite_init,
- .qdev.name = "xilinx,ethlite",
- .qdev.size = sizeof(struct xlx_ethlite),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("txpingpong", struct xlx_ethlite, c_tx_pingpong, 1),
- DEFINE_PROP_UINT32("rxpingpong", struct xlx_ethlite, c_rx_pingpong, 1),
- DEFINE_NIC_PROPERTIES(struct xlx_ethlite, conf),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xilinx_ethlite_properties[] = {
+ DEFINE_PROP_UINT32("txpingpong", struct xlx_ethlite, c_tx_pingpong, 1),
+ DEFINE_PROP_UINT32("rxpingpong", struct xlx_ethlite, c_rx_pingpong, 1),
+ DEFINE_NIC_PROPERTIES(struct xlx_ethlite, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_ethlite_init;
+ dc->props = xilinx_ethlite_properties;
+}
+
+static TypeInfo xilinx_ethlite_info = {
+ .name = "xilinx,ethlite",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct xlx_ethlite),
+ .class_init = xilinx_ethlite_class_init,
};
static void xilinx_ethlite_register(void)
{
- sysbus_register_withprop(&xilinx_ethlite_info);
+ type_register_static(&xilinx_ethlite_info);
}
device_init(xilinx_ethlite_register)
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index c567885bcf..73eed6dc5f 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -161,19 +161,30 @@ static int xilinx_intc_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo xilinx_intc_info = {
- .init = xilinx_intc_init,
- .qdev.name = "xilinx,intc",
- .qdev.size = sizeof(struct xlx_pic),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xilinx_intc_properties[] = {
+ DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xilinx_intc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_intc_init;
+ dc->props = xilinx_intc_properties;
+}
+
+static TypeInfo xilinx_intc_info = {
+ .name = "xilinx,intc",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct xlx_pic),
+ .class_init = xilinx_intc_class_init,
};
static void xilinx_intc_register(void)
{
- sysbus_register_withprop(&xilinx_intc_info);
+ type_register_static(&xilinx_intc_info);
}
device_init(xilinx_intc_register)
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index adca53b98c..c8236d2e2a 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -219,20 +219,31 @@ static int xilinx_timer_init(SysBusDevice *dev)
return 0;
}
-static SysBusDeviceInfo xilinx_timer_info = {
- .init = xilinx_timer_init,
- .qdev.name = "xilinx,timer",
- .qdev.size = sizeof(struct timerblock),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 0),
- DEFINE_PROP_UINT32("nr-timers", struct timerblock, nr_timers, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xilinx_timer_properties[] = {
+ DEFINE_PROP_UINT32("frequency", struct timerblock, freq_hz, 0),
+ DEFINE_PROP_UINT32("nr-timers", struct timerblock, nr_timers, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xilinx_timer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xilinx_timer_init;
+ dc->props = xilinx_timer_properties;
+}
+
+static TypeInfo xilinx_timer_info = {
+ .name = "xilinx,timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct timerblock),
+ .class_init = xilinx_timer_class_init,
};
static void xilinx_timer_register(void)
{
- sysbus_register_withprop(&xilinx_timer_info);
+ type_register_static(&xilinx_timer_info);
}
device_init(xilinx_timer_register)
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index 6533df934f..1c2b9087b4 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -205,16 +205,29 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
memory_region_init_io(&s->mmio, &uart_ops, s, "xilinx-uartlite", R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
- s->chr = qdev_init_chardev(&dev->qdev);
+ s->chr = qemu_char_get_next_serial();
if (s->chr)
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
return 0;
}
+static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+ sdc->init = xilinx_uartlite_init;
+}
+
+static TypeInfo xilinx_uartlite_info = {
+ .name = "xilinx,uartlite",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof (struct xlx_uartlite),
+ .class_init = xilinx_uartlite_class_init,
+};
+
static void xilinx_uart_register(void)
{
- sysbus_register_dev("xilinx,uartlite", sizeof (struct xlx_uartlite),
- xilinx_uartlite_init);
+ type_register_static(&xilinx_uartlite_info);
}
device_init(xilinx_uart_register)
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index d3c387d6cb..07e4fc1018 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -47,7 +47,7 @@ static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
static void xio3130_downstream_reset(DeviceState *qdev)
{
- PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *d = PCI_DEVICE(qdev);
msi_reset(d);
pcie_cap_deverr_reset(d);
pcie_cap_slot_reset(d);
@@ -167,36 +167,45 @@ static const VMStateDescription vmstate_xio3130_downstream = {
}
};
-static PCIDeviceInfo xio3130_downstream_info = {
- .qdev.name = "xio3130-downstream",
- .qdev.desc = "TI X3130 Downstream Port of PCI Express Switch",
- .qdev.size = sizeof(PCIESlot),
- .qdev.reset = xio3130_downstream_reset,
- .qdev.vmsd = &vmstate_xio3130_downstream,
-
- .is_express = 1,
- .is_bridge = 1,
- .config_write = xio3130_downstream_write_config,
- .init = xio3130_downstream_initfn,
- .exit = xio3130_downstream_exitfn,
- .vendor_id = PCI_VENDOR_ID_TI,
- .device_id = PCI_DEVICE_ID_TI_XIO3130D,
- .revision = XIO3130_REVISION,
-
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
- DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
- DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
- port.br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xio3130_downstream_properties[] = {
+ DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+ DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+ DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+ DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+ port.br.dev.exp.aer_log.log_max,
+ PCIE_AER_LOG_MAX_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->is_express = 1;
+ k->is_bridge = 1;
+ k->config_write = xio3130_downstream_write_config;
+ k->init = xio3130_downstream_initfn;
+ k->exit = xio3130_downstream_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_TI;
+ k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
+ k->revision = XIO3130_REVISION;
+ dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
+ dc->reset = xio3130_downstream_reset;
+ dc->vmsd = &vmstate_xio3130_downstream;
+ dc->props = xio3130_downstream_properties;
+}
+
+static TypeInfo xio3130_downstream_info = {
+ .name = "xio3130-downstream",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIESlot),
+ .class_init = xio3130_downstream_class_init,
};
static void xio3130_downstream_register(void)
{
- pci_qdev_register(&xio3130_downstream_info);
+ type_register_static(&xio3130_downstream_info);
}
device_init(xio3130_downstream_register);
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 82836958a4..7887c92fcc 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -46,7 +46,7 @@ static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address,
static void xio3130_upstream_reset(DeviceState *qdev)
{
- PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *d = PCI_DEVICE(qdev);
msi_reset(d);
pci_bridge_reset(qdev);
pcie_cap_deverr_reset(d);
@@ -144,33 +144,42 @@ static const VMStateDescription vmstate_xio3130_upstream = {
}
};
-static PCIDeviceInfo xio3130_upstream_info = {
- .qdev.name = "x3130-upstream",
- .qdev.desc = "TI X3130 Upstream Port of PCI Express Switch",
- .qdev.size = sizeof(PCIEPort),
- .qdev.reset = xio3130_upstream_reset,
- .qdev.vmsd = &vmstate_xio3130_upstream,
-
- .is_express = 1,
- .is_bridge = 1,
- .config_write = xio3130_upstream_write_config,
- .init = xio3130_upstream_initfn,
- .exit = xio3130_upstream_exitfn,
- .vendor_id = PCI_VENDOR_ID_TI,
- .device_id = PCI_DEVICE_ID_TI_XIO3130U,
- .revision = XIO3130_REVISION,
-
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property xio3130_upstream_properties[] = {
+ DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
+ DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
+ PCIE_AER_LOG_MAX_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->is_express = 1;
+ k->is_bridge = 1;
+ k->config_write = xio3130_upstream_write_config;
+ k->init = xio3130_upstream_initfn;
+ k->exit = xio3130_upstream_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_TI;
+ k->device_id = PCI_DEVICE_ID_TI_XIO3130U;
+ k->revision = XIO3130_REVISION;
+ dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
+ dc->reset = xio3130_upstream_reset;
+ dc->vmsd = &vmstate_xio3130_upstream;
+ dc->props = xio3130_upstream_properties;
+}
+
+static TypeInfo xio3130_upstream_info = {
+ .name = "x3130-upstream",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIEPort),
+ .class_init = xio3130_upstream_class_init,
};
static void xio3130_upstream_register(void)
{
- pci_qdev_register(&xio3130_upstream_info);
+ type_register_static(&xio3130_upstream_info);
}
device_init(xio3130_upstream_register);
diff --git a/hw/z2.c b/hw/z2.c
index 8d48488331..654ac55f5c 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -174,21 +174,30 @@ static VMStateDescription vmstate_zipit_lcd_state = {
}
};
-static SSISlaveInfo zipit_lcd_info = {
- .qdev.name = "zipit-lcd",
- .qdev.size = sizeof(ZipitLCD),
- .qdev.vmsd = &vmstate_zipit_lcd_state,
- .init = zipit_lcd_init,
- .transfer = zipit_lcd_transfer
+static void zipit_lcd_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+ k->init = zipit_lcd_init;
+ k->transfer = zipit_lcd_transfer;
+ dc->vmsd = &vmstate_zipit_lcd_state;
+}
+
+static TypeInfo zipit_lcd_info = {
+ .name = "zipit-lcd",
+ .parent = TYPE_SSI_SLAVE,
+ .instance_size = sizeof(ZipitLCD),
+ .class_init = zipit_lcd_class_init,
};
typedef struct {
- i2c_slave i2c;
+ I2CSlave i2c;
int len;
uint8_t buf[3];
} AER915State;
-static int aer915_send(i2c_slave *i2c, uint8_t data)
+static int aer915_send(I2CSlave *i2c, uint8_t data)
{
AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
s->buf[s->len] = data;
@@ -206,7 +215,7 @@ static int aer915_send(i2c_slave *i2c, uint8_t data)
return 0;
}
-static void aer915_event(i2c_slave *i2c, enum i2c_event event)
+static void aer915_event(I2CSlave *i2c, enum i2c_event event)
{
AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
switch (event) {
@@ -225,7 +234,7 @@ static void aer915_event(i2c_slave *i2c, enum i2c_event event)
}
}
-static int aer915_recv(i2c_slave *slave)
+static int aer915_recv(I2CSlave *slave)
{
int retval = 0x00;
AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
@@ -248,7 +257,7 @@ static int aer915_recv(i2c_slave *slave)
return retval;
}
-static int aer915_init(i2c_slave *i2c)
+static int aer915_init(I2CSlave *i2c)
{
/* Nothing to do. */
return 0;
@@ -266,14 +275,23 @@ static VMStateDescription vmstate_aer915_state = {
}
};
-static I2CSlaveInfo aer915_info = {
- .qdev.name = "aer915",
- .qdev.size = sizeof(AER915State),
- .qdev.vmsd = &vmstate_aer915_state,
- .init = aer915_init,
- .event = aer915_event,
- .recv = aer915_recv,
- .send = aer915_send
+static void aer915_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+ k->init = aer915_init;
+ k->event = aer915_event;
+ k->recv = aer915_recv;
+ k->send = aer915_send;
+ dc->vmsd = &vmstate_aer915_state;
+}
+
+static TypeInfo aer915_info = {
+ .name = "aer915",
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(AER915State),
+ .class_init = aer915_class_init,
};
static void z2_init(ram_addr_t ram_size,
@@ -326,8 +344,8 @@ static void z2_init(ram_addr_t ram_size,
NULL,
qdev_get_gpio_in(cpu->gpio, Z2_GPIO_SD_DETECT));
- ssi_register_slave(&zipit_lcd_info);
- i2c_register_slave(&aer915_info);
+ type_register_static(&zipit_lcd_info);
+ type_register_static(&aer915_info);
z2_lcd = ssi_create_slave(cpu->ssp[1], "zipit-lcd");
bus = pxa2xx_i2c_bus(cpu->i2c[0]);
i2c_create_slave(bus, "aer915", 0x55);
diff --git a/hw/zaurus.c b/hw/zaurus.c
index c4bcd29825..055df9b4e2 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -221,20 +221,31 @@ static const VMStateDescription vmstate_scoop_regs = {
},
};
-static SysBusDeviceInfo scoop_sysbus_info = {
- .init = scoop_init,
- .qdev.name = "scoop",
- .qdev.desc = "Scoop2 Sharp custom ASIC",
- .qdev.size = sizeof(ScoopInfo),
- .qdev.vmsd = &vmstate_scoop_regs,
- .qdev.props = (Property[]) {
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property scoop_sysbus_properties[] = {
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = scoop_init;
+ dc->desc = "Scoop2 Sharp custom ASIC";
+ dc->vmsd = &vmstate_scoop_regs;
+ dc->props = scoop_sysbus_properties;
+}
+
+static TypeInfo scoop_sysbus_info = {
+ .name = "scoop",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ScoopInfo),
+ .class_init = scoop_sysbus_class_init,
};
static void scoop_register(void)
{
- sysbus_register_withprop(&scoop_sysbus_info);
+ type_register_static(&scoop_sysbus_info);
}
device_init(scoop_register);