]> git.proxmox.com Git - qemu.git/commitdiff
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Thu, 16 Feb 2012 00:41:28 +0000 (18:41 -0600)
committerAnthony Liguori <aliguori@us.ibm.com>
Thu, 16 Feb 2012 00:41:28 +0000 (18:41 -0600)
* qemu-kvm/uq/master:
  apic: Fix legacy vmstate loading for KVM
  kvm: Implement kvm_irqchip_in_kernel like kvm_enabled
  kvm: Allow to set shadow MMU size

289 files changed:
Makefile
Makefile.hw
Makefile.objs
Makefile.target
block.c
block.h
block/iscsi.c
block/qcow2.c
block/qcow2.h
block/qed.c
block/qed.h
block/sheepdog.c
block/vpc.c
block_int.h
compiler.h
configure
cutils.c
fsdev/file-op-9p.h
fsdev/virtfs-proxy-helper.c
hw/9pfs/cofile.c
hw/9pfs/virtio-9p-device.c
hw/9pfs/virtio-9p-handle.c
hw/9pfs/virtio-9p-local.c
hw/9pfs/virtio-9p.c
hw/a9mpcore.c
hw/ac97.c
hw/acpi_piix4.c
hw/ads7846.c
hw/alpha_typhoon.c
hw/apb_pci.c
hw/apic.c
hw/apic_common.c
hw/applesmc.c
hw/arm11mpcore.c
hw/arm_l2x0.c
hw/arm_mptimer.c
hw/arm_sysctl.c
hw/arm_timer.c
hw/armv7m.c
hw/armv7m_nvic.c
hw/bitbang_i2c.c
hw/bonito.c
hw/ccid-card-emulated.c
hw/ccid-card-passthru.c
hw/cirrus_vga.c
hw/cs4231.c
hw/cs4231a.c
hw/debugcon.c
hw/dec_pci.c
hw/ds1225y.c
hw/ds1338.c
hw/e1000.c
hw/eccmemctl.c
hw/eepro100.c
hw/empty_slot.c
hw/es1370.c
hw/escc.c
hw/esp.c
hw/etraxfs_eth.c
hw/etraxfs_pic.c
hw/etraxfs_ser.c
hw/etraxfs_timer.c
hw/fdc.c
hw/framebuffer.c
hw/fw_cfg.c
hw/g364fb.c
hw/grackle_pci.c
hw/grlib_apbuart.c
hw/grlib_gptimer.c
hw/grlib_irqmp.c
hw/gt64xxx.c
hw/gus.c
hw/hda-audio.c
hw/highbank.c
hw/hpet.c
hw/i2c.c
hw/i82374.c
hw/i82378.c
hw/i8254.c
hw/i8259.c
hw/i8259_common.c
hw/ide/ahci.c
hw/ide/cmd646.c
hw/ide/ich.c
hw/ide/isa.c
hw/ide/piix.c
hw/ide/qdev.c
hw/ide/via.c
hw/integratorcp.c
hw/intel-hda.c
hw/ioapic.c
hw/ioapic_common.c
hw/ioh3420.c
hw/isa-bus.c
hw/ivshmem.c
hw/kvm/apic.c
hw/kvm/clock.c
hw/kvm/i8259.c
hw/kvm/ioapic.c
hw/lan9118.c
hw/lance.c
hw/lm32_juart.c
hw/lm32_pic.c
hw/lm32_sys.c
hw/lm32_timer.c
hw/lm32_uart.c
hw/lm832x.c
hw/lsi53c895a.c
hw/m48t59.c
hw/macio.c
hw/marvell_88w8618_audio.c
hw/max111x.c
hw/max7310.c
hw/mc146818rtc.c
hw/milkymist-ac97.c
hw/milkymist-hpdmc.c
hw/milkymist-memcard.c
hw/milkymist-minimac2.c
hw/milkymist-pfpu.c
hw/milkymist-softusb.c
hw/milkymist-sysctl.c
hw/milkymist-tmu2.c
hw/milkymist-uart.c
hw/milkymist-vgafb.c
hw/mips_malta.c
hw/mipsnet.c
hw/mpc8544_guts.c
hw/mst_fpga.c
hw/musicpal.c
hw/nand.c
hw/ne2000-isa.c
hw/ne2000.c
hw/omap_gpio.c
hw/omap_intc.c
hw/onenand.c
hw/opencores_eth.c
hw/parallel.c
hw/pc.c
hw/pci.c
hw/pckbd.c
hw/pcnet-pci.c
hw/pflash_cfi02.c
hw/piix4.c
hw/piix_pci.c
hw/pl011.c
hw/pl022.c
hw/pl031.c
hw/pl041.c
hw/pl050.c
hw/pl061.c
hw/pl080.c
hw/pl110.c
hw/pl181.c
hw/pl190.c
hw/ppc4xx_pci.c
hw/ppce500_pci.c
hw/ppce500_spin.c
hw/prep_pci.c
hw/pxa2xx.c
hw/pxa2xx_dma.c
hw/pxa2xx_gpio.c
hw/pxa2xx_pic.c
hw/pxa2xx_timer.c
hw/qdev-addr.c
hw/qdev-monitor.c
hw/qdev-properties.c
hw/qdev.c
hw/qdev.h
hw/qxl.c
hw/realview.c
hw/realview_gic.c
hw/rtl8139.c
hw/s390-virtio-bus.c
hw/sb16.c
hw/sbi.c
hw/scsi-bus.c
hw/scsi-disk.c
hw/scsi-generic.c
hw/serial.c
hw/sga.c
hw/sh_pci.c
hw/slavio_intctl.c
hw/slavio_misc.c
hw/slavio_timer.c
hw/sm501.c
hw/smbus.c
hw/smbus_eeprom.c
hw/smc91c111.c
hw/spapr_hcall.c
hw/spapr_llan.c
hw/spapr_pci.c
hw/spapr_rtas.c
hw/spapr_vio.c
hw/spapr_vscsi.c
hw/spapr_vty.c
hw/sparc32_dma.c
hw/spitz.c
hw/ssd0303.c
hw/ssd0323.c
hw/ssi-sd.c
hw/ssi.c
hw/stellaris.c
hw/stellaris_enet.c
hw/strongarm.c
hw/sun4c_intctl.c
hw/sun4m.c
hw/sun4m_iommu.c
hw/sun4u.c
hw/sysbus.c
hw/tcx.c
hw/tmp105.c
hw/tosa.c
hw/tusb6010.c
hw/twl92230.c
hw/unin_pci.c
hw/usb-audio.c
hw/usb-bt.c
hw/usb-bus.c
hw/usb-ccid.c
hw/usb-ehci.c
hw/usb-hid.c
hw/usb-hub.c
hw/usb-msd.c
hw/usb-musb.c
hw/usb-net.c
hw/usb-ohci.c
hw/usb-serial.c
hw/usb-uhci.c
hw/usb-wacom.c
hw/usb-xhci.c
hw/usb.c
hw/usb.h
hw/versatile_pci.c
hw/versatilepb.c
hw/vexpress.c
hw/vga-isa.c
hw/vga-pci.c
hw/vga.c
hw/virtio-console.c
hw/virtio-pci.c
hw/virtio-serial-bus.c
hw/vmmouse.c
hw/vmport.c
hw/vmware_vga.c
hw/vt82c686.c
hw/wdt_i6300esb.c
hw/wdt_ib700.c
hw/wm8750.c
hw/xen_platform.c
hw/xgmac.c
hw/xilinx_axidma.c
hw/xilinx_axienet.c
hw/xilinx_ethlite.c
hw/xilinx_intc.c
hw/xilinx_timer.c
hw/xilinx_uartlite.c
hw/xio3130_downstream.c
hw/xio3130_upstream.c
hw/zaurus.c
include/qemu/object.h
include/qemu/qom-qobject.h [new file with mode: 0644]
libcacard/Makefile
memory.c
module.h
qemu-common.h
qemu-config.c
qemu-doc.texi
qemu-img.c
qemu-io.c
qemu-options.hx
qemu-thread-win32.c
qerror.c
qerror.h
qmp.c
qom/Makefile
qom/container.c
qom/object.c
qom/qom-qobject.c [new file with mode: 0644]
slirp/ip_icmp.c
slirp/misc.c
target-ppc/helper.c
trace-events
ui/spice-core.c
ui/vnc.c
ui/vnc.h
usb-bsd.c
usb-linux.c
usb-redir.c
vl.c

index 47acf3dc36b29b912c3bef7d4a2d02350d593ba7..e66e885d1bdc7669aca770e8025f0e2f2e54e3aa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -114,8 +114,6 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 
 QEMU_CFLAGS+=$(CURL_CFLAGS)
 
-QEMU_CFLAGS+=$(GLIB_CFLAGS)
-
 QEMU_CFLAGS += -I$(SRC_PATH)/include
 
 ui/cocoa.o: ui/cocoa.m
index 7b8d068c94270f119ab4e0d7f7518a4742c5d491..33f1ab01838d7f3f0eefc778d9b8a3a716582248 100644 (file)
@@ -10,7 +10,6 @@ include $(SRC_PATH)/rules.mak
 $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
 
 QEMU_CFLAGS+=-I..
-QEMU_CFLAGS += $(GLIB_CFLAGS)
 QEMU_CFLAGS += -I$(SRC_PATH)/include
 
 include $(SRC_PATH)/Makefile.objs
index ec35320ff5c49f714d638597562ff78e94fae6c6..391e524525de467c86065afbd315c998db891783 100644 (file)
@@ -323,8 +323,6 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
 
 hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
-$(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
-
 
 ######################################################################
 # libdis
index 68481a3a6c98007cadcae294fcdec3de8adacf73..29fde6e982ffa1e10fdfffb0ad8b2cddb97c7aff 100644 (file)
@@ -29,10 +29,17 @@ ifdef CONFIG_USER_ONLY
 QEMU_PROG=qemu-$(TARGET_ARCH2)
 else
 # system emulator name
+ifneq (,$(findstring -mwindows,$(LIBS)))
+# Terminate program name with a 'w' because the linker builds a windows executable.
+QEMU_PROGW=qemu-system-$(TARGET_ARCH2)w$(EXESUF)
+endif # windows executable
 QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF)
 endif
 
 PROGS=$(QEMU_PROG)
+ifdef QEMU_PROGW
+PROGS+=$(QEMU_PROGW)
+endif
 STPFILES=
 
 ifndef CONFIG_HAIKU
@@ -208,7 +215,6 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
 QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
-QEMU_CFLAGS += $(GLIB_CFLAGS)
 
 # xen support
 obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
@@ -407,9 +413,16 @@ endif # CONFIG_LINUX_USER
 
 obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
 
+ifdef QEMU_PROGW
+# The linker builds a windows executable. Make also a console executable.
+$(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+       $(call LINK,$^)
+$(QEMU_PROG): $(QEMU_PROGW)
+       $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"  GEN   $(TARGET_DIR)$(QEMU_PROG)")
+else
 $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
        $(call LINK,$^)
-
+endif
 
 gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
        $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"  GEN   $(TARGET_DIR)$@")
diff --git a/block.c b/block.c
index 3621d11de0ab8b012e9e0b2dd229cc0ded5c38aa..ae297bb8471346db4c4e539ea13f5f519380aa36 100644 (file)
--- a/block.c
+++ b/block.c
@@ -50,6 +50,7 @@
 
 typedef enum {
     BDRV_REQ_COPY_ON_READ = 0x1,
+    BDRV_REQ_ZERO_WRITE   = 0x2,
 } BdrvRequestFlags;
 
 static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
@@ -69,7 +70,8 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
     BdrvRequestFlags flags);
 static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
-    int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
+    int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
+    BdrvRequestFlags flags);
 static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                                int64_t sector_num,
                                                QEMUIOVector *qiov,
@@ -1300,7 +1302,7 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque)
                                      rwco->nb_sectors, rwco->qiov, 0);
     } else {
         rwco->ret = bdrv_co_do_writev(rwco->bs, rwco->sector_num,
-                                      rwco->nb_sectors, rwco->qiov);
+                                      rwco->nb_sectors, rwco->qiov, 0);
     }
 }
 
@@ -1515,6 +1517,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
      */
     void *bounce_buffer;
 
+    BlockDriver *drv = bs->drv;
     struct iovec iov;
     QEMUIOVector bounce_qiov;
     int64_t cluster_sector_num;
@@ -1535,14 +1538,21 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
     iov.iov_base = bounce_buffer = qemu_blockalign(bs, iov.iov_len);
     qemu_iovec_init_external(&bounce_qiov, &iov, 1);
 
-    ret = bs->drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,
-                                 &bounce_qiov);
+    ret = drv->bdrv_co_readv(bs, cluster_sector_num, cluster_nb_sectors,
+                             &bounce_qiov);
     if (ret < 0) {
         goto err;
     }
 
-    ret = bs->drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors,
+    if (drv->bdrv_co_write_zeroes &&
+        buffer_is_zero(bounce_buffer, iov.iov_len)) {
+        ret = drv->bdrv_co_write_zeroes(bs, cluster_sector_num,
+                                        cluster_nb_sectors);
+    } else {
+        ret = drv->bdrv_co_writev(bs, cluster_sector_num, cluster_nb_sectors,
                                   &bounce_qiov);
+    }
+
     if (ret < 0) {
         /* It might be okay to ignore write errors for guest requests.  If this
          * is a deliberate copy-on-read then we don't want to ignore the error.
@@ -1639,11 +1649,37 @@ int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,
                             BDRV_REQ_COPY_ON_READ);
 }
 
+static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
+    int64_t sector_num, int nb_sectors)
+{
+    BlockDriver *drv = bs->drv;
+    QEMUIOVector qiov;
+    struct iovec iov;
+    int ret;
+
+    /* First try the efficient write zeroes operation */
+    if (drv->bdrv_co_write_zeroes) {
+        return drv->bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
+    }
+
+    /* Fall back to bounce buffer if write zeroes is unsupported */
+    iov.iov_len  = nb_sectors * BDRV_SECTOR_SIZE;
+    iov.iov_base = qemu_blockalign(bs, iov.iov_len);
+    memset(iov.iov_base, 0, iov.iov_len);
+    qemu_iovec_init_external(&qiov, &iov, 1);
+
+    ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, &qiov);
+
+    qemu_vfree(iov.iov_base);
+    return ret;
+}
+
 /*
  * Handle a write request in coroutine context
  */
 static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
-    int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
+    int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
+    BdrvRequestFlags flags)
 {
     BlockDriver *drv = bs->drv;
     BdrvTrackedRequest req;
@@ -1670,7 +1706,11 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
 
     tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
 
-    ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
+    if (flags & BDRV_REQ_ZERO_WRITE) {
+        ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors);
+    } else {
+        ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
+    }
 
     if (bs->dirty_bitmap) {
         set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
@@ -1690,7 +1730,16 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
 {
     trace_bdrv_co_writev(bs, sector_num, nb_sectors);
 
-    return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov);
+    return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov, 0);
+}
+
+int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
+                                      int64_t sector_num, int nb_sectors)
+{
+    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
+
+    return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
+                             BDRV_REQ_ZERO_WRITE);
 }
 
 /**
@@ -3192,7 +3241,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
             acb->req.nb_sectors, acb->req.qiov, 0);
     } else {
         acb->req.error = bdrv_co_do_writev(bs, acb->req.sector,
-            acb->req.nb_sectors, acb->req.qiov);
+            acb->req.nb_sectors, acb->req.qiov, 0);
     }
 
     acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
diff --git a/block.h b/block.h
index cae289b2fbf7a217bb693db075e7a5872b404c2f..60ea7308c6c95a1c8b68d0e1d21c53a6d05a3992 100644 (file)
--- a/block.h
+++ b/block.h
@@ -146,6 +146,14 @@ int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
 int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
     int nb_sectors, QEMUIOVector *qiov);
+/*
+ * Efficiently zero a region of the disk image.  Note that this is a regular
+ * I/O request like read or write and should have a reasonable size.  This
+ * function is not suitable for zeroing the entire image in a single request
+ * because it may allocate memory for the entire region.
+ */
+int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors);
 int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num,
     int nb_sectors, int *pnum);
 BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
index 938c5680715af9303e3b22ad0ce5a6f5f2e04c63..bd3ca11b2e1315f3f7566655349627006cbdc473 100644 (file)
@@ -455,6 +455,109 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
     }
 }
 
+static int parse_chap(struct iscsi_context *iscsi, const char *target)
+{
+    QemuOptsList *list;
+    QemuOpts *opts;
+    const char *user = NULL;
+    const char *password = NULL;
+
+    list = qemu_find_opts("iscsi");
+    if (!list) {
+        return 0;
+    }
+
+    opts = qemu_opts_find(list, target);
+    if (opts == NULL) {
+        opts = QTAILQ_FIRST(&list->head);
+        if (!opts) {
+            return 0;
+        }
+    }
+
+    user = qemu_opt_get(opts, "user");
+    if (!user) {
+        return 0;
+    }
+
+    password = qemu_opt_get(opts, "password");
+    if (!password) {
+        error_report("CHAP username specified but no password was given");
+        return -1;
+    }
+
+    if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
+        error_report("Failed to set initiator username and password");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void parse_header_digest(struct iscsi_context *iscsi, const char *target)
+{
+    QemuOptsList *list;
+    QemuOpts *opts;
+    const char *digest = NULL;
+
+    list = qemu_find_opts("iscsi");
+    if (!list) {
+        return;
+    }
+
+    opts = qemu_opts_find(list, target);
+    if (opts == NULL) {
+        opts = QTAILQ_FIRST(&list->head);
+        if (!opts) {
+            return;
+        }
+    }
+
+    digest = qemu_opt_get(opts, "header-digest");
+    if (!digest) {
+        return;
+    }
+
+    if (!strcmp(digest, "CRC32C")) {
+        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
+    } else if (!strcmp(digest, "NONE")) {
+        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
+    } else if (!strcmp(digest, "CRC32C-NONE")) {
+        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
+    } else if (!strcmp(digest, "NONE-CRC32C")) {
+        iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
+    } else {
+        error_report("Invalid header-digest setting : %s", digest);
+    }
+}
+
+static char *parse_initiator_name(const char *target)
+{
+    QemuOptsList *list;
+    QemuOpts *opts;
+    const char *name = NULL;
+
+    list = qemu_find_opts("iscsi");
+    if (!list) {
+        return g_strdup("iqn.2008-11.org.linux-kvm");
+    }
+
+    opts = qemu_opts_find(list, target);
+    if (opts == NULL) {
+        opts = QTAILQ_FIRST(&list->head);
+        if (!opts) {
+            return g_strdup("iqn.2008-11.org.linux-kvm");
+        }
+    }
+
+    name = qemu_opt_get(opts, "initiator-name");
+    if (!name) {
+        return g_strdup("iqn.2008-11.org.linux-kvm");
+    }
+
+    return g_strdup(name);
+}
+
 /*
  * We support iscsi url's on the form
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
@@ -465,6 +568,7 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     struct iscsi_context *iscsi = NULL;
     struct iscsi_url *iscsi_url = NULL;
     struct IscsiTask task;
+    char *initiator_name = NULL;
     int ret;
 
     if ((BDRV_SECTOR_SIZE % 512) != 0) {
@@ -474,16 +578,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
         return -EINVAL;
     }
 
-    memset(iscsilun, 0, sizeof(IscsiLun));
-
-    /* Should really append the KVM name after the ':' here */
-    iscsi = iscsi_create_context("iqn.2008-11.org.linux-kvm:");
-    if (iscsi == NULL) {
-        error_report("iSCSI: Failed to create iSCSI context.");
-        ret = -ENOMEM;
-        goto failed;
-    }
-
     iscsi_url = iscsi_parse_full_url(iscsi, filename);
     if (iscsi_url == NULL) {
         error_report("Failed to parse URL : %s %s", filename,
@@ -492,6 +586,17 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
         goto failed;
     }
 
+    memset(iscsilun, 0, sizeof(IscsiLun));
+
+    initiator_name = parse_initiator_name(iscsi_url->target);
+
+    iscsi = iscsi_create_context(initiator_name);
+    if (iscsi == NULL) {
+        error_report("iSCSI: Failed to create iSCSI context.");
+        ret = -ENOMEM;
+        goto failed;
+    }
+
     if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
         error_report("iSCSI: Failed to set target name.");
         ret = -EINVAL;
@@ -507,6 +612,14 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
             goto failed;
         }
     }
+
+    /* check if we got CHAP username/password via the options */
+    if (parse_chap(iscsi, iscsi_url->target) != 0) {
+        error_report("iSCSI: Failed to set CHAP user/password");
+        ret = -EINVAL;
+        goto failed;
+    }
+
     if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
         error_report("iSCSI: Failed to set session type to normal.");
         ret = -EINVAL;
@@ -515,6 +628,9 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
 
     iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
 
+    /* check if we got HEADER_DIGEST via the options */
+    parse_header_digest(iscsi, iscsi_url->target);
+
     task.iscsilun = iscsilun;
     task.status = 0;
     task.complete = 0;
@@ -548,6 +664,9 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     return 0;
 
 failed:
+    if (initiator_name != NULL) {
+        g_free(initiator_name);
+    }
     if (iscsi_url != NULL) {
         iscsi_destroy_url(iscsi_url);
     }
index aa32e8d01a325bfebe6e3d2b8c9bc794b431fa80..3692b4523b43a049dd40a451c990ba84c182eb55 100644 (file)
@@ -77,8 +77,10 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
 static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                                  uint64_t end_offset)
 {
+    BDRVQcowState *s = bs->opaque;
     QCowExtension ext;
     uint64_t offset;
+    int ret;
 
 #ifdef DEBUG_EXT
     printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);
@@ -129,8 +131,22 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
             break;
 
         default:
-            /* unknown magic -- just skip it */
-            offset = ((offset + ext.len + 7) & ~7);
+            /* unknown magic - save it in case we need to rewrite the header */
+            {
+                Qcow2UnknownHeaderExtension *uext;
+
+                uext = g_malloc0(sizeof(*uext)  + ext.len);
+                uext->magic = ext.magic;
+                uext->len = ext.len;
+                QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);
+
+                ret = bdrv_pread(bs->file, offset , uext->data, uext->len);
+                if (ret < 0) {
+                    return ret;
+                }
+
+                offset = ((offset + ext.len + 7) & ~7);
+            }
             break;
         }
     }
@@ -138,6 +154,16 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
     return 0;
 }
 
+static void cleanup_unknown_header_ext(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+    Qcow2UnknownHeaderExtension *uext, *next;
+
+    QLIST_FOREACH_SAFE(uext, &s->unknown_header_ext, next, next) {
+        QLIST_REMOVE(uext, next);
+        g_free(uext);
+    }
+}
 
 static int qcow2_open(BlockDriverState *bs, int flags)
 {
@@ -291,6 +317,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     return ret;
 
  fail:
+    cleanup_unknown_header_ext(bs);
     qcow2_free_snapshots(bs);
     qcow2_refcount_close(bs);
     g_free(s->l1_table);
@@ -632,6 +659,7 @@ static void qcow2_close(BlockDriverState *bs)
     qcow2_cache_destroy(bs, s->l2_table_cache);
     qcow2_cache_destroy(bs, s->refcount_block_cache);
 
+    cleanup_unknown_header_ext(bs);
     g_free(s->cluster_cache);
     qemu_vfree(s->cluster_data);
     qcow2_refcount_close(bs);
@@ -669,103 +697,149 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
     }
 }
 
+static size_t header_ext_add(char *buf, uint32_t magic, const void *s,
+    size_t len, size_t buflen)
+{
+    QCowExtension *ext_backing_fmt = (QCowExtension*) buf;
+    size_t ext_len = sizeof(QCowExtension) + ((len + 7) & ~7);
+
+    if (buflen < ext_len) {
+        return -ENOSPC;
+    }
+
+    *ext_backing_fmt = (QCowExtension) {
+        .magic  = cpu_to_be32(magic),
+        .len    = cpu_to_be32(len),
+    };
+    memcpy(buf + sizeof(QCowExtension), s, len);
+
+    return ext_len;
+}
+
 /*
- * Updates the variable length parts of the qcow2 header, i.e. the backing file
- * name and all extensions. qcow2 was not designed to allow such changes, so if
- * we run out of space (we can only use the first cluster) this function may
- * fail.
+ * Updates the qcow2 header, including the variable length parts of it, i.e.
+ * the backing file name and all extensions. qcow2 was not designed to allow
+ * such changes, so if we run out of space (we can only use the first cluster)
+ * this function may fail.
  *
  * Returns 0 on success, -errno in error cases.
  */
-static int qcow2_update_ext_header(BlockDriverState *bs,
-    const char *backing_file, const char *backing_fmt)
+int qcow2_update_header(BlockDriverState *bs)
 {
-    size_t backing_file_len = 0;
-    size_t backing_fmt_len = 0;
     BDRVQcowState *s = bs->opaque;
-    QCowExtension ext_backing_fmt = {0, 0};
+    QCowHeader *header;
+    char *buf;
+    size_t buflen = s->cluster_size;
     int ret;
+    uint64_t total_size;
+    uint32_t refcount_table_clusters;
+    Qcow2UnknownHeaderExtension *uext;
 
-    /* Backing file format doesn't make sense without a backing file */
-    if (backing_fmt && !backing_file) {
-        return -EINVAL;
-    }
+    buf = qemu_blockalign(bs, buflen);
+    memset(buf, 0, s->cluster_size);
 
-    /* Prepare the backing file format extension if needed */
-    if (backing_fmt) {
-        ext_backing_fmt.len = cpu_to_be32(strlen(backing_fmt));
-        ext_backing_fmt.magic = cpu_to_be32(QCOW2_EXT_MAGIC_BACKING_FORMAT);
-        backing_fmt_len = ((sizeof(ext_backing_fmt)
-            + strlen(backing_fmt) + 7) & ~7);
-    }
+    /* Header structure */
+    header = (QCowHeader*) buf;
 
-    /* Check if we can fit the new header into the first cluster */
-    if (backing_file) {
-        backing_file_len = strlen(backing_file);
-    }
-
-    size_t header_size = sizeof(QCowHeader) + backing_file_len
-        + backing_fmt_len;
-
-    if (header_size > s->cluster_size) {
-        return -ENOSPC;
+    if (buflen < sizeof(*header)) {
+        ret = -ENOSPC;
+        goto fail;
     }
 
-    /* Rewrite backing file name and qcow2 extensions */
-    size_t ext_size = header_size - sizeof(QCowHeader);
-    uint8_t buf[ext_size];
-    size_t offset = 0;
-    size_t backing_file_offset = 0;
+    total_size = bs->total_sectors * BDRV_SECTOR_SIZE;
+    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
+
+    *header = (QCowHeader) {
+        .magic                  = cpu_to_be32(QCOW_MAGIC),
+        .version                = cpu_to_be32(QCOW_VERSION),
+        .backing_file_offset    = 0,
+        .backing_file_size      = 0,
+        .cluster_bits           = cpu_to_be32(s->cluster_bits),
+        .size                   = cpu_to_be64(total_size),
+        .crypt_method           = cpu_to_be32(s->crypt_method_header),
+        .l1_size                = cpu_to_be32(s->l1_size),
+        .l1_table_offset        = cpu_to_be64(s->l1_table_offset),
+        .refcount_table_offset  = cpu_to_be64(s->refcount_table_offset),
+        .refcount_table_clusters = cpu_to_be32(refcount_table_clusters),
+        .nb_snapshots           = cpu_to_be32(s->nb_snapshots),
+        .snapshots_offset       = cpu_to_be64(s->snapshots_offset),
+    };
 
-    if (backing_file) {
-        if (backing_fmt) {
-            int padding = backing_fmt_len -
-                (sizeof(ext_backing_fmt) + strlen(backing_fmt));
+    buf += sizeof(*header);
+    buflen -= sizeof(*header);
 
-            memcpy(buf + offset, &ext_backing_fmt, sizeof(ext_backing_fmt));
-            offset += sizeof(ext_backing_fmt);
+    /* Backing file format header extension */
+    if (*bs->backing_format) {
+        ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT,
+                             bs->backing_format, strlen(bs->backing_format),
+                             buflen);
+        if (ret < 0) {
+            goto fail;
+        }
 
-            memcpy(buf + offset, backing_fmt, strlen(backing_fmt));
-            offset += strlen(backing_fmt);
+        buf += ret;
+        buflen -= ret;
+    }
 
-            memset(buf + offset, 0, padding);
-            offset += padding;
+    /* Keep unknown header extensions */
+    QLIST_FOREACH(uext, &s->unknown_header_ext, next) {
+        ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen);
+        if (ret < 0) {
+            goto fail;
         }
 
-        memcpy(buf + offset, backing_file, backing_file_len);
-        backing_file_offset = sizeof(QCowHeader) + offset;
+        buf += ret;
+        buflen -= ret;
     }
 
-    ret = bdrv_pwrite_sync(bs->file, sizeof(QCowHeader), buf, ext_size);
+    /* End of header extensions */
+    ret = header_ext_add(buf, QCOW2_EXT_MAGIC_END, NULL, 0, buflen);
     if (ret < 0) {
         goto fail;
     }
 
-    /* Update header fields */
-    uint64_t be_backing_file_offset = cpu_to_be64(backing_file_offset);
-    uint32_t be_backing_file_size = cpu_to_be32(backing_file_len);
+    buf += ret;
+    buflen -= ret;
 
-    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, backing_file_offset),
-        &be_backing_file_offset, sizeof(uint64_t));
-    if (ret < 0) {
-        goto fail;
+    /* Backing file name */
+    if (*bs->backing_file) {
+        size_t backing_file_len = strlen(bs->backing_file);
+
+        if (buflen < backing_file_len) {
+            ret = -ENOSPC;
+            goto fail;
+        }
+
+        strncpy(buf, bs->backing_file, buflen);
+
+        header->backing_file_offset = cpu_to_be64(buf - ((char*) header));
+        header->backing_file_size   = cpu_to_be32(backing_file_len);
     }
 
-    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, backing_file_size),
-        &be_backing_file_size, sizeof(uint32_t));
+    /* Write the new header */
+    ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size);
     if (ret < 0) {
         goto fail;
     }
 
     ret = 0;
 fail:
+    qemu_vfree(header);
     return ret;
 }
 
 static int qcow2_change_backing_file(BlockDriverState *bs,
     const char *backing_file, const char *backing_fmt)
 {
-    return qcow2_update_ext_header(bs, backing_file, backing_fmt);
+    /* Backing file format doesn't make sense without a backing file */
+    if (backing_fmt && !backing_file) {
+        return -EINVAL;
+    }
+
+    pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
+    pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
+
+    return qcow2_update_header(bs);
 }
 
 static int preallocate(BlockDriverState *bs)
index 99e45361f507f268d12edcfd29f0ac98984b7550..fc358381756a93dbeb951800330f7f41d46b8b28 100644 (file)
@@ -87,6 +87,13 @@ typedef struct QCowSnapshot {
 struct Qcow2Cache;
 typedef struct Qcow2Cache Qcow2Cache;
 
+typedef struct Qcow2UnknownHeaderExtension {
+    uint32_t magic;
+    uint32_t len;
+    QLIST_ENTRY(Qcow2UnknownHeaderExtension) next;
+    uint8_t data[];
+} Qcow2UnknownHeaderExtension;
+
 typedef struct BDRVQcowState {
     int cluster_bits;
     int cluster_size;
@@ -127,6 +134,7 @@ typedef struct BDRVQcowState {
     QCowSnapshot *snapshots;
 
     int flags;
+    QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext;
 } BDRVQcowState;
 
 /* XXX: use std qcow open function ? */
@@ -178,6 +186,7 @@ static inline int64_t align_offset(int64_t offset, int n)
 /* qcow2.c functions */
 int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
                   int64_t sector_num, int nb_sectors);
+int qcow2_update_header(BlockDriverState *bs);
 
 /* qcow2-refcount.c functions */
 int qcow2_refcount_init(BlockDriverState *bs);
index 8da3ebe9d459b8ac409da6ee0b01ff8fb15fb127..a041d31e661a652a79c1c02c096cd563a4b6efb0 100644 (file)
@@ -875,6 +875,12 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
     qemu_iovec_destroy(&acb->cur_qiov);
     qed_unref_l2_cache_entry(acb->request.l2_table);
 
+    /* Free the buffer we may have allocated for zero writes */
+    if (acb->flags & QED_AIOCB_ZERO) {
+        qemu_vfree(acb->qiov->iov[0].iov_base);
+        acb->qiov->iov[0].iov_base = NULL;
+    }
+
     /* Arrange for a bh to invoke the completion function */
     acb->bh_ret = ret;
     acb->bh = qemu_bh_new(qed_aio_complete_bh, acb);
@@ -941,9 +947,8 @@ static void qed_aio_write_l1_update(void *opaque, int ret)
 /**
  * Update L2 table with new cluster offsets and write them out
  */
-static void qed_aio_write_l2_update(void *opaque, int ret)
+static void qed_aio_write_l2_update(QEDAIOCB *acb, int ret, uint64_t offset)
 {
-    QEDAIOCB *acb = opaque;
     BDRVQEDState *s = acb_to_s(acb);
     bool need_alloc = acb->find_cluster_ret == QED_CLUSTER_L1;
     int index;
@@ -959,7 +964,7 @@ static void qed_aio_write_l2_update(void *opaque, int ret)
 
     index = qed_l2_index(s, acb->cur_pos);
     qed_update_l2_table(s, acb->request.l2_table->table, index, acb->cur_nclusters,
-                         acb->cur_cluster);
+                         offset);
 
     if (need_alloc) {
         /* Write out the whole new L2 table */
@@ -976,6 +981,12 @@ err:
     qed_aio_complete(acb, ret);
 }
 
+static void qed_aio_write_l2_update_cb(void *opaque, int ret)
+{
+    QEDAIOCB *acb = opaque;
+    qed_aio_write_l2_update(acb, ret, acb->cur_cluster);
+}
+
 /**
  * Flush new data clusters before updating the L2 table
  *
@@ -990,7 +1001,7 @@ static void qed_aio_write_flush_before_l2_update(void *opaque, int ret)
     QEDAIOCB *acb = opaque;
     BDRVQEDState *s = acb_to_s(acb);
 
-    if (!bdrv_aio_flush(s->bs->file, qed_aio_write_l2_update, opaque)) {
+    if (!bdrv_aio_flush(s->bs->file, qed_aio_write_l2_update_cb, opaque)) {
         qed_aio_complete(acb, -EIO);
     }
 }
@@ -1019,7 +1030,7 @@ static void qed_aio_write_main(void *opaque, int ret)
         if (s->bs->backing_hd) {
             next_fn = qed_aio_write_flush_before_l2_update;
         } else {
-            next_fn = qed_aio_write_l2_update;
+            next_fn = qed_aio_write_l2_update_cb;
         }
     }
 
@@ -1081,6 +1092,18 @@ static bool qed_should_set_need_check(BDRVQEDState *s)
     return !(s->header.features & QED_F_NEED_CHECK);
 }
 
+static void qed_aio_write_zero_cluster(void *opaque, int ret)
+{
+    QEDAIOCB *acb = opaque;
+
+    if (ret) {
+        qed_aio_complete(acb, ret);
+        return;
+    }
+
+    qed_aio_write_l2_update(acb, 0, 1);
+}
+
 /**
  * Write new data cluster
  *
@@ -1092,6 +1115,7 @@ static bool qed_should_set_need_check(BDRVQEDState *s)
 static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
 {
     BDRVQEDState *s = acb_to_s(acb);
+    BlockDriverCompletionFunc *cb;
 
     /* Cancel timer when the first allocating request comes in */
     if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
@@ -1109,14 +1133,26 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
 
     acb->cur_nclusters = qed_bytes_to_clusters(s,
             qed_offset_into_cluster(s, acb->cur_pos) + len);
-    acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters);
     qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
 
+    if (acb->flags & QED_AIOCB_ZERO) {
+        /* Skip ahead if the clusters are already zero */
+        if (acb->find_cluster_ret == QED_CLUSTER_ZERO) {
+            qed_aio_next_io(acb, 0);
+            return;
+        }
+
+        cb = qed_aio_write_zero_cluster;
+    } else {
+        cb = qed_aio_write_prefill;
+        acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters);
+    }
+
     if (qed_should_set_need_check(s)) {
         s->header.features |= QED_F_NEED_CHECK;
-        qed_write_header(s, qed_aio_write_prefill, acb);
+        qed_write_header(s, cb, acb);
     } else {
-        qed_aio_write_prefill(acb, 0);
+        cb(acb, 0);
     }
 }
 
@@ -1131,6 +1167,16 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
  */
 static void qed_aio_write_inplace(QEDAIOCB *acb, uint64_t offset, size_t len)
 {
+    /* Allocate buffer for zero writes */
+    if (acb->flags & QED_AIOCB_ZERO) {
+        struct iovec *iov = acb->qiov->iov;
+
+        if (!iov->iov_base) {
+            iov->iov_base = qemu_blockalign(acb->common.bs, iov->iov_len);
+            memset(iov->iov_base, 0, iov->iov_len);
+        }
+    }
+
     /* Calculate the I/O vector */
     acb->cur_cluster = offset;
     qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
@@ -1233,8 +1279,8 @@ static void qed_aio_next_io(void *opaque, int ret)
 {
     QEDAIOCB *acb = opaque;
     BDRVQEDState *s = acb_to_s(acb);
-    QEDFindClusterFunc *io_fn =
-        acb->is_write ? qed_aio_write_data : qed_aio_read_data;
+    QEDFindClusterFunc *io_fn = (acb->flags & QED_AIOCB_WRITE) ?
+                                qed_aio_write_data : qed_aio_read_data;
 
     trace_qed_aio_next_io(s, acb, ret, acb->cur_pos + acb->cur_qiov.size);
 
@@ -1264,14 +1310,14 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
                                        int64_t sector_num,
                                        QEMUIOVector *qiov, int nb_sectors,
                                        BlockDriverCompletionFunc *cb,
-                                       void *opaque, bool is_write)
+                                       void *opaque, int flags)
 {
     QEDAIOCB *acb = qemu_aio_get(&qed_aio_pool, bs, cb, opaque);
 
     trace_qed_aio_setup(bs->opaque, acb, sector_num, nb_sectors,
-                         opaque, is_write);
+                        opaque, flags);
 
-    acb->is_write = is_write;
+    acb->flags = flags;
     acb->finished = NULL;
     acb->qiov = qiov;
     acb->qiov_offset = 0;
@@ -1291,7 +1337,7 @@ static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs,
                                             BlockDriverCompletionFunc *cb,
                                             void *opaque)
 {
-    return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, false);
+    return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
 }
 
 static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
@@ -1300,7 +1346,8 @@ static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
                                              BlockDriverCompletionFunc *cb,
                                              void *opaque)
 {
-    return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, true);
+    return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb,
+                         opaque, QED_AIOCB_WRITE);
 }
 
 static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs,
@@ -1310,6 +1357,53 @@ static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs,
     return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
+typedef struct {
+    Coroutine *co;
+    int ret;
+    bool done;
+} QEDWriteZeroesCB;
+
+static void coroutine_fn qed_co_write_zeroes_cb(void *opaque, int ret)
+{
+    QEDWriteZeroesCB *cb = opaque;
+
+    cb->done = true;
+    cb->ret = ret;
+    if (cb->co) {
+        qemu_coroutine_enter(cb->co, NULL);
+    }
+}
+
+static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
+                                                 int64_t sector_num,
+                                                 int nb_sectors)
+{
+    BlockDriverAIOCB *blockacb;
+    QEDWriteZeroesCB cb = { .done = false };
+    QEMUIOVector qiov;
+    struct iovec iov;
+
+    /* Zero writes start without an I/O buffer.  If a buffer becomes necessary
+     * then it will be allocated during request processing.
+     */
+    iov.iov_base = NULL,
+    iov.iov_len  = nb_sectors * BDRV_SECTOR_SIZE,
+
+    qemu_iovec_init_external(&qiov, &iov, 1);
+    blockacb = qed_aio_setup(bs, sector_num, &qiov, nb_sectors,
+                             qed_co_write_zeroes_cb, &cb,
+                             QED_AIOCB_WRITE | QED_AIOCB_ZERO);
+    if (!blockacb) {
+        return -EIO;
+    }
+    if (!cb.done) {
+        cb.co = qemu_coroutine_self();
+        qemu_coroutine_yield();
+    }
+    assert(cb.done);
+    return cb.ret;
+}
+
 static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
 {
     BDRVQEDState *s = bs->opaque;
@@ -1469,6 +1563,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_aio_readv           = bdrv_qed_aio_readv,
     .bdrv_aio_writev          = bdrv_qed_aio_writev,
     .bdrv_aio_flush           = bdrv_qed_aio_flush,
+    .bdrv_co_write_zeroes     = bdrv_qed_co_write_zeroes,
     .bdrv_truncate            = bdrv_qed_truncate,
     .bdrv_getlength           = bdrv_qed_getlength,
     .bdrv_get_info            = bdrv_qed_get_info,
index 62cbd3b8996162525756ba9280e652d13c191d68..62624a1f34d48fbf3d0cd45046c910ef35afc3fa 100644 (file)
@@ -123,12 +123,17 @@ typedef struct QEDRequest {
     CachedL2Table *l2_table;
 } QEDRequest;
 
+enum {
+    QED_AIOCB_WRITE = 0x0001,       /* read or write? */
+    QED_AIOCB_ZERO  = 0x0002,       /* zero write, used with QED_AIOCB_WRITE */
+};
+
 typedef struct QEDAIOCB {
     BlockDriverAIOCB common;
     QEMUBH *bh;
     int bh_ret;                     /* final return status for completion bh */
     QSIMPLEQ_ENTRY(QEDAIOCB) next;  /* next request */
-    bool is_write;                  /* false - read, true - write */
+    int flags;                      /* QED_AIOCB_* bits ORed together */
     bool *finished;                 /* signal for cancel completion */
     uint64_t end_pos;               /* request end on block device, in bytes */
 
index 9416400165efae87ce4800aeba2b18da56917939..00276f6f4601f886c6b5c4e11cff8fe2f837445c 100644 (file)
@@ -629,6 +629,9 @@ static void coroutine_fn aio_read_response(void *opaque)
 
     switch (acb->aiocb_type) {
     case AIOCB_WRITE_UDATA:
+        /* this coroutine context is no longer suitable for co_recv
+         * because we may send data to update vdi objects */
+        s->co_recv = NULL;
         if (!is_data_obj(aio_req->oid)) {
             break;
         }
index 89a5ee26686a08252765de544a8aac4078a4e8f5..6b4816f563e190a258934fe59c7c197360609278 100644 (file)
@@ -161,13 +161,27 @@ static int vpc_open(BlockDriverState *bs, int flags)
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
     int err = -1;
+    int disk_type = VHD_DYNAMIC;
 
     if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
         goto fail;
 
     footer = (struct vhd_footer*) s->footer_buf;
-    if (strncmp(footer->creator, "conectix", 8))
-        goto fail;
+    if (strncmp(footer->creator, "conectix", 8)) {
+        int64_t offset = bdrv_getlength(bs->file);
+        if (offset < HEADER_SIZE) {
+            goto fail;
+        }
+        /* If a fixed disk, the footer is found only at the end of the file */
+        if (bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, HEADER_SIZE)
+                != HEADER_SIZE) {
+            goto fail;
+        }
+        if (strncmp(footer->creator, "conectix", 8)) {
+            goto fail;
+        }
+        disk_type = VHD_FIXED;
+    }
 
     checksum = be32_to_cpu(footer->checksum);
     footer->checksum = 0;
@@ -186,49 +200,54 @@ static int vpc_open(BlockDriverState *bs, int flags)
         goto fail;
     }
 
-    if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
-            != HEADER_SIZE)
-        goto fail;
-
-    dyndisk_header = (struct vhd_dyndisk_header*) buf;
+    if (disk_type == VHD_DYNAMIC) {
+        if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
+                HEADER_SIZE) != HEADER_SIZE) {
+            goto fail;
+        }
 
-    if (strncmp(dyndisk_header->magic, "cxsparse", 8))
-        goto fail;
+        dyndisk_header = (struct vhd_dyndisk_header *) buf;
 
+        if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
+            goto fail;
+        }
 
-    s->block_size = be32_to_cpu(dyndisk_header->block_size);
-    s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
+        s->block_size = be32_to_cpu(dyndisk_header->block_size);
+        s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
 
-    s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
-    s->pagetable = g_malloc(s->max_table_entries * 4);
+        s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
+        s->pagetable = g_malloc(s->max_table_entries * 4);
 
-    s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
-    if (bdrv_pread(bs->file, s->bat_offset, s->pagetable,
-            s->max_table_entries * 4) != s->max_table_entries * 4)
-           goto fail;
+        s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
+        if (bdrv_pread(bs->file, s->bat_offset, s->pagetable,
+                s->max_table_entries * 4) != s->max_table_entries * 4) {
+            goto fail;
+        }
 
-    s->free_data_block_offset =
-        (s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
+        s->free_data_block_offset =
+            (s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
 
-    for (i = 0; i < s->max_table_entries; i++) {
-        be32_to_cpus(&s->pagetable[i]);
-        if (s->pagetable[i] != 0xFFFFFFFF) {
-            int64_t next = (512 * (int64_t) s->pagetable[i]) +
-                s->bitmap_size + s->block_size;
+        for (i = 0; i < s->max_table_entries; i++) {
+            be32_to_cpus(&s->pagetable[i]);
+            if (s->pagetable[i] != 0xFFFFFFFF) {
+                int64_t next = (512 * (int64_t) s->pagetable[i]) +
+                    s->bitmap_size + s->block_size;
 
-            if (next> s->free_data_block_offset)
-                s->free_data_block_offset = next;
+                if (next > s->free_data_block_offset) {
+                    s->free_data_block_offset = next;
+                }
+            }
         }
-    }
 
-    s->last_bitmap_offset = (int64_t) -1;
+        s->last_bitmap_offset = (int64_t) -1;
 
 #ifdef CACHE
-    s->pageentry_u8 = g_malloc(512);
-    s->pageentry_u32 = s->pageentry_u8;
-    s->pageentry_u16 = s->pageentry_u8;
-    s->last_pagetable = -1;
+        s->pageentry_u8 = g_malloc(512);
+        s->pageentry_u32 = s->pageentry_u8;
+        s->pageentry_u16 = s->pageentry_u8;
+        s->last_pagetable = -1;
 #endif
+    }
 
     qemu_co_mutex_init(&s->lock);
 
@@ -395,7 +414,11 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
     int ret;
     int64_t offset;
     int64_t sectors, sectors_per_block;
+    struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
 
+    if (cpu_to_be32(footer->type) == VHD_FIXED) {
+        return bdrv_read(bs->file, sector_num, buf, nb_sectors);
+    }
     while (nb_sectors > 0) {
         offset = get_sector_offset(bs, sector_num, 0);
 
@@ -440,7 +463,11 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
     int64_t offset;
     int64_t sectors, sectors_per_block;
     int ret;
+    struct vhd_footer *footer =  (struct vhd_footer *) s->footer_buf;
 
+    if (cpu_to_be32(footer->type) == VHD_FIXED) {
+        return bdrv_write(bs->file, sector_num, buf, nb_sectors);
+    }
     while (nb_sectors > 0) {
         offset = get_sector_offset(bs, sector_num, 1);
 
@@ -533,70 +560,14 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
     return 0;
 }
 
-static int vpc_create(const char *filename, QEMUOptionParameter *options)
+static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors)
 {
-    uint8_t buf[1024];
-    struct vhd_footer* footer = (struct vhd_footer*) buf;
     struct vhd_dyndisk_header* dyndisk_header =
         (struct vhd_dyndisk_header*) buf;
-    int fd, i;
-    uint16_t cyls = 0;
-    uint8_t heads = 0;
-    uint8_t secs_per_cyl = 0;
     size_t block_size, num_bat_entries;
-    int64_t total_sectors = 0;
+    int i;
     int ret = -EIO;
 
-    // Read out options
-    total_sectors = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n /
-                    BDRV_SECTOR_SIZE;
-
-    // Create the file
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
-    if (fd < 0)
-        return -EIO;
-
-    /* Calculate matching total_size and geometry. Increase the number of
-       sectors requested until we get enough (or fail). */
-    for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
-        if (calculate_geometry(total_sectors + i,
-                               &cyls, &heads, &secs_per_cyl)) {
-            ret = -EFBIG;
-            goto fail;
-        }
-    }
-    total_sectors = (int64_t) cyls * heads * secs_per_cyl;
-
-    // Prepare the Hard Disk Footer
-    memset(buf, 0, 1024);
-
-    memcpy(footer->creator, "conectix", 8);
-    // TODO Check if "qemu" creator_app is ok for VPC
-    memcpy(footer->creator_app, "qemu", 4);
-    memcpy(footer->creator_os, "Wi2k", 4);
-
-    footer->features = be32_to_cpu(0x02);
-    footer->version = be32_to_cpu(0x00010000);
-    footer->data_offset = be64_to_cpu(HEADER_SIZE);
-    footer->timestamp = be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE);
-
-    // Version of Virtual PC 2007
-    footer->major = be16_to_cpu(0x0005);
-    footer->minor =be16_to_cpu(0x0003);
-
-    footer->orig_size = be64_to_cpu(total_sectors * 512);
-    footer->size = be64_to_cpu(total_sectors * 512);
-
-    footer->cyls = be16_to_cpu(cyls);
-    footer->heads = heads;
-    footer->secs_per_cyl = secs_per_cyl;
-
-    footer->type = be32_to_cpu(VHD_DYNAMIC);
-
-    // TODO uuid is missing
-
-    footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE));
-
     // Write the footer (twice: at the beginning and at the end)
     block_size = 0x200000;
     num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512);
@@ -624,7 +595,6 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
         }
     }
 
-
     // Prepare the Dynamic Disk Header
     memset(buf, 0, 1024);
 
@@ -652,6 +622,129 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     }
     ret = 0;
 
+ fail:
+    return ret;
+}
+
+static int create_fixed_disk(int fd, uint8_t *buf, int64_t total_size)
+{
+    int ret = -EIO;
+
+    /* Add footer to total size */
+    total_size += 512;
+    if (ftruncate(fd, total_size) != 0) {
+        ret = -errno;
+        goto fail;
+    }
+    if (lseek(fd, -512, SEEK_END) < 0) {
+        goto fail;
+    }
+    if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) {
+        goto fail;
+    }
+
+    ret = 0;
+
+ fail:
+    return ret;
+}
+
+static int vpc_create(const char *filename, QEMUOptionParameter *options)
+{
+    uint8_t buf[1024];
+    struct vhd_footer *footer = (struct vhd_footer *) buf;
+    QEMUOptionParameter *disk_type_param;
+    int fd, i;
+    uint16_t cyls = 0;
+    uint8_t heads = 0;
+    uint8_t secs_per_cyl = 0;
+    int64_t total_sectors;
+    int64_t total_size;
+    int disk_type;
+    int ret = -EIO;
+
+    /* Read out options */
+    total_size = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n;
+
+    disk_type_param = get_option_parameter(options, BLOCK_OPT_SUBFMT);
+    if (disk_type_param && disk_type_param->value.s) {
+        if (!strcmp(disk_type_param->value.s, "dynamic")) {
+            disk_type = VHD_DYNAMIC;
+        } else if (!strcmp(disk_type_param->value.s, "fixed")) {
+            disk_type = VHD_FIXED;
+        } else {
+            return -EINVAL;
+        }
+    } else {
+        disk_type = VHD_DYNAMIC;
+    }
+
+    /* Create the file */
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+    if (fd < 0) {
+        return -EIO;
+    }
+
+    /*
+     * Calculate matching total_size and geometry. Increase the number of
+     * sectors requested until we get enough (or fail). This ensures that
+     * qemu-img convert doesn't truncate images, but rather rounds up.
+     */
+    total_sectors = total_size / BDRV_SECTOR_SIZE;
+    for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
+        if (calculate_geometry(total_sectors + i, &cyls, &heads,
+                               &secs_per_cyl))
+        {
+            ret = -EFBIG;
+            goto fail;
+        }
+    }
+
+    total_sectors = (int64_t) cyls * heads * secs_per_cyl;
+
+    /* Prepare the Hard Disk Footer */
+    memset(buf, 0, 1024);
+
+    memcpy(footer->creator, "conectix", 8);
+    /* TODO Check if "qemu" creator_app is ok for VPC */
+    memcpy(footer->creator_app, "qemu", 4);
+    memcpy(footer->creator_os, "Wi2k", 4);
+
+    footer->features = be32_to_cpu(0x02);
+    footer->version = be32_to_cpu(0x00010000);
+    if (disk_type == VHD_DYNAMIC) {
+        footer->data_offset = be64_to_cpu(HEADER_SIZE);
+    } else {
+        footer->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL);
+    }
+    footer->timestamp = be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE);
+
+    /* Version of Virtual PC 2007 */
+    footer->major = be16_to_cpu(0x0005);
+    footer->minor = be16_to_cpu(0x0003);
+    if (disk_type == VHD_DYNAMIC) {
+        footer->orig_size = be64_to_cpu(total_sectors * 512);
+        footer->size = be64_to_cpu(total_sectors * 512);
+    } else {
+        footer->orig_size = be64_to_cpu(total_size);
+        footer->size = be64_to_cpu(total_size);
+    }
+    footer->cyls = be16_to_cpu(cyls);
+    footer->heads = heads;
+    footer->secs_per_cyl = secs_per_cyl;
+
+    footer->type = be32_to_cpu(disk_type);
+
+    /* TODO uuid is missing */
+
+    footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE));
+
+    if (disk_type == VHD_DYNAMIC) {
+        ret = create_dynamic_disk(fd, buf, total_sectors);
+    } else {
+        ret = create_fixed_disk(fd, buf, total_size);
+    }
+
  fail:
     close(fd);
     return ret;
@@ -675,6 +768,13 @@ static QEMUOptionParameter vpc_create_options[] = {
         .type = OPT_SIZE,
         .help = "Virtual disk size"
     },
+    {
+        .name = BLOCK_OPT_SUBFMT,
+        .type = OPT_STRING,
+        .help =
+            "Type of virtual hard disk format. Supported formats are "
+            "{dynamic (default) | fixed} "
+    },
     { NULL }
 };
 
index 7be2988ca7098f3ca16bf24ff69dfa957690fb7a..7946cf66a1d6375e83bc7ad37e08406c561a71b8 100644 (file)
@@ -131,6 +131,14 @@ struct BlockDriver {
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
     int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
+    /*
+     * Efficiently zero a region of the disk image.  Typically an image format
+     * would use a compact metadata representation to implement this.  This
+     * function pointer may be NULL and .bdrv_co_writev() will be called
+     * instead.
+     */
+    int coroutine_fn (*bdrv_co_write_zeroes)(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors);
     int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors);
     int coroutine_fn (*bdrv_co_is_allocated)(BlockDriverState *bs,
index a1c0794947766226733de71de1051aff42d79805..736e77075ae47d9707946f982478e78d764b0fff 100644 (file)
 # define QEMU_PACKED __attribute__((packed))
 #endif
 
+#define cat(x,y) x ## y
+#define cat2(x,y) cat(x,y)
 #define QEMU_BUILD_BUG_ON(x) \
-    typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1];
+    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
 
 #if defined __GNUC__
 # if !QEMU_GNUC_PREREQ(4, 4)
index 763db24cd0dc67ce6dfb0669060cfb32509e0803..68f9ee6acbc51cff700be1e3d0cf192c9df92f05 100755 (executable)
--- a/configure
+++ b/configure
@@ -2584,7 +2584,7 @@ fi
 
 # check for usbredirparser for usb network redirection support
 if test "$usb_redir" != "no" ; then
-    if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
+    if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
         usb_redir="yes"
         usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
         usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
index a6ffd4644562462b38faa7c9ed79e4a5dc361c99..af308cd7b9f1c0f20d043c204ef6c2db392ae898 100644 (file)
--- a/cutils.c
+++ b/cutils.c
@@ -303,6 +303,41 @@ void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
     }
 }
 
+/*
+ * Checks if a buffer is all zeroes
+ *
+ * Attention! The len must be a multiple of 4 * sizeof(long) due to
+ * restriction of optimizations in this function.
+ */
+bool buffer_is_zero(const void *buf, size_t len)
+{
+    /*
+     * Use long as the biggest available internal data type that fits into the
+     * CPU register and unroll the loop to smooth out the effect of memory
+     * latency.
+     */
+
+    size_t i;
+    long d0, d1, d2, d3;
+    const long * const data = buf;
+
+    assert(len % (4 * sizeof(long)) == 0);
+    len /= sizeof(long);
+
+    for (i = 0; i < len; i += 4) {
+        d0 = data[i + 0];
+        d1 = data[i + 1];
+        d2 = data[i + 2];
+        d3 = data[i + 3];
+
+        if (d0 || d1 || d2 || d3) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 #ifndef _WIN32
 /* Sets a specific flag */
 int fcntl_setfl(int fd, int flag)
index 1e96c8bed93c9942b63d98914ab6ee5ca84aa693..956fda091968b34326246209109b4b05697fcf31 100644 (file)
@@ -56,11 +56,15 @@ typedef struct extended_ops {
  * On failure ignore the error.
  */
 #define V9FS_SM_NONE                0x00000010
-#define V9FS_RDONLY                 0x00000020
-#define V9FS_PROXY_SOCK_FD          0x00000040
-#define V9FS_PROXY_SOCK_NAME        0x00000080
+/*
+ * uid/gid part of .virtfs_meatadata namespace
+ */
+#define V9FS_SM_MAPPED_FILE         0x00000020
+#define V9FS_RDONLY                 0x00000040
+#define V9FS_PROXY_SOCK_FD          0x00000080
+#define V9FS_PROXY_SOCK_NAME        0x00000100
 
-#define V9FS_SEC_MASK               0x0000001C
+#define V9FS_SEC_MASK               0x0000003C
 
 
 typedef struct FileOperations FileOperations;
index 4a507d860e167ea42dbd995ee0fe73ab86cf82a9..f9a8270ee96610db897e875180d06d5f624ef3f8 100644 (file)
@@ -1036,7 +1036,13 @@ int main(int argc, char **argv)
         return -1;
     }
 
-    if (*sock_name && (own_u == -1 || own_g == -1)) {
+    if (sock_name && sock != -1) {
+        fprintf(stderr, "both named socket and socket descriptor specified\n");
+        usage(argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    if (sock_name && (own_u == -1 || own_g == -1)) {
         fprintf(stderr, "owner uid:gid not specified, ");
         fprintf(stderr,
                 "owner uid:gid specifies who can access the socket file\n");
@@ -1064,7 +1070,7 @@ int main(int argc, char **argv)
     }
 
     do_log(LOG_INFO, "Started\n");
-    if (*sock_name) {
+    if (sock_name) {
         sock = proxy_socket(sock_name, own_u, own_g);
         if (sock < 0) {
             goto error;
index b15838c1e6a206ca21b3224e7e18b87f997ad0d9..9345aaeb2efbe0b3cd88a5f58f5707c64419245f 100644 (file)
@@ -76,6 +76,20 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
                 err = -errno;
             }
         });
+    /*
+     * Some FS driver (local:mapped-file) can't support fetching attributes
+     * using file descriptor. Use Path name in that case.
+     */
+    if (err == -EOPNOTSUPP) {
+        err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
+        if (err == -ENOENT) {
+            /*
+             * fstat on an unlinked file. Work with partial results
+             * returned from s->ops->fstat
+             */
+            err = 0;
+        }
+    }
     return err;
 }
 
index 3f15540c5f30fc864967330fc416332af3085629..b8220abae796f3ee2892f9ae3497324fc387b6cf 100644 (file)
@@ -91,15 +91,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
         s->ctx.fs_root = NULL;
     }
     s->ctx.exops.get_st_gen = NULL;
-
-    if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
-        s->ctx.xops = passthrough_xattr_ops;
-    } else if (fse->export_flags & V9FS_SM_MAPPED) {
-        s->ctx.xops = mapped_xattr_ops;
-    } else if (fse->export_flags & V9FS_SM_NONE) {
-        s->ctx.xops = none_xattr_ops;
-    }
-
     len = strlen(conf->tag);
     if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
@@ -193,10 +184,10 @@ static TypeInfo virtio_9p_info = {
     .class_init    = virtio_9p_class_init,
 };
 
-static void virtio_9p_register_devices(void)
+static void virtio_9p_register_types(void)
 {
     type_register_static(&virtio_9p_info);
     virtio_9p_set_fd_limit();
 }
 
-device_init(virtio_9p_register_devices)
+type_init(virtio_9p_register_types)
index cb012c0510ace40de7153d7feb87f0e981a0c200..f96d17a9749a6f672741ff4dcb98da81d1dcc3ce 100644 (file)
@@ -63,11 +63,11 @@ static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
     if (fd < 0) {
         return fd;
     }
-    ret = fchmod(fd, credp->fc_mode & 07777);
+    ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
     if (ret < 0) {
         goto err_out;
     }
-    ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
+    ret = fchmod(fd, credp->fc_mode & 07777);
 err_out:
     close(fd);
     return ret;
index 3ae6ef2e395336cb768c8ea5941e191114f2cd35..33a41d2e18b60aab8c87cab8834c03a442fc5ca7 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include "qemu-xattr.h"
+#include <libgen.h>
 #include <linux/fs.h>
 #ifdef CONFIG_LINUX_MAGIC_H
 #include <linux/magic.h>
 #define BTRFS_SUPER_MAGIC 0x9123683E
 #endif
 
+#define VIRTFS_META_DIR ".virtfs_metadata"
+
+static const char *local_mapped_attr_path(FsContext *ctx,
+                                          const char *path, char *buffer)
+{
+    char *dir_name;
+    char *tmp_path = strdup(path);
+    char *base_name = basename(tmp_path);
+
+    /* NULL terminate the directory */
+    dir_name = tmp_path;
+    *(base_name - 1) = '\0';
+
+    snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
+             ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
+    free(tmp_path);
+    return buffer;
+}
+
+#define ATTR_MAX 100
+static void local_mapped_file_attr(FsContext *ctx, const char *path,
+                                   struct stat *stbuf)
+{
+    FILE *fp;
+    char buf[ATTR_MAX];
+    char attr_path[PATH_MAX];
+
+    local_mapped_attr_path(ctx, path, attr_path);
+    fp = fopen(attr_path, "r");
+    if (!fp) {
+        return;
+    }
+    memset(buf, 0, ATTR_MAX);
+    while (fgets(buf, ATTR_MAX, fp)) {
+        if (!strncmp(buf, "virtfs.uid", 10)) {
+            stbuf->st_uid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.gid", 10)) {
+            stbuf->st_gid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.mode", 11)) {
+            stbuf->st_mode = atoi(buf+12);
+        } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+            stbuf->st_rdev = atoi(buf+12);
+        }
+        memset(buf, 0, ATTR_MAX);
+    }
+    fclose(fp);
+}
+
 static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
 {
     int err;
@@ -71,10 +120,103 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
                         sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        local_mapped_file_attr(fs_ctx, path, stbuf);
     }
     return err;
 }
 
+static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
+{
+    int err;
+    char attr_dir[PATH_MAX];
+    char *tmp_path = strdup(path);
+
+    snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
+             ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
+
+    err = mkdir(attr_dir, 0700);
+    if (err < 0 && errno == EEXIST) {
+        err = 0;
+    }
+    free(tmp_path);
+    return err;
+}
+
+static int local_set_mapped_file_attr(FsContext *ctx,
+                                      const char *path, FsCred *credp)
+{
+    FILE *fp;
+    int ret = 0;
+    char buf[ATTR_MAX];
+    char attr_path[PATH_MAX];
+    int uid = -1, gid = -1, mode = -1, rdev = -1;
+
+    fp = fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
+    if (!fp) {
+        goto create_map_file;
+    }
+    memset(buf, 0, ATTR_MAX);
+    while (fgets(buf, ATTR_MAX, fp)) {
+        if (!strncmp(buf, "virtfs.uid", 10)) {
+            uid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.gid", 10)) {
+            gid = atoi(buf+11);
+        } else if (!strncmp(buf, "virtfs.mode", 11)) {
+            mode = atoi(buf+12);
+        } else if (!strncmp(buf, "virtfs.rdev", 11)) {
+            rdev = atoi(buf+12);
+        }
+        memset(buf, 0, ATTR_MAX);
+    }
+    fclose(fp);
+    goto update_map_file;
+
+create_map_file:
+    ret = local_create_mapped_attr_dir(ctx, path);
+    if (ret < 0) {
+        goto err_out;
+    }
+
+update_map_file:
+    fp = fopen(attr_path, "w");
+    if (!fp) {
+        ret = -1;
+        goto err_out;
+    }
+
+    if (credp->fc_uid != -1) {
+        uid = credp->fc_uid;
+    }
+    if (credp->fc_gid != -1) {
+        gid = credp->fc_gid;
+    }
+    if (credp->fc_mode != -1) {
+        mode = credp->fc_mode;
+    }
+    if (credp->fc_rdev != -1) {
+        rdev = credp->fc_rdev;
+    }
+
+
+    if (uid != -1) {
+        fprintf(fp, "virtfs.uid=%d\n", uid);
+    }
+    if (gid != -1) {
+        fprintf(fp, "virtfs.gid=%d\n", gid);
+    }
+    if (mode != -1) {
+        fprintf(fp, "virtfs.mode=%d\n", mode);
+    }
+    if (rdev != -1) {
+        fprintf(fp, "virtfs.rdev=%d\n", rdev);
+    }
+    fclose(fp);
+
+err_out:
+    return ret;
+}
+
 static int local_set_xattr(const char *path, FsCred *credp)
 {
     int err;
@@ -115,9 +257,6 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
 {
     char buffer[PATH_MAX];
 
-    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
-        return -1;
-    }
     if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
                 credp->fc_gid) < 0) {
         /*
@@ -128,6 +267,10 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
             return -1;
         }
     }
+
+    if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
+        return -1;
+    }
     return 0;
 }
 
@@ -138,7 +281,8 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
     char buffer[PATH_MAX];
     char *path = fs_path->data;
 
-    if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+    if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
+        (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
         int fd;
         fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
         if (fd == -1) {
@@ -203,7 +347,18 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
                            struct dirent *entry,
                            struct dirent **result)
 {
-    return readdir_r(fs->dir, entry, result);
+    int ret;
+
+again:
+    ret = readdir_r(fs->dir, entry, result);
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        if (!ret && *result != NULL &&
+            !strcmp(entry->d_name, VIRTFS_META_DIR)) {
+            /* skp the meta data directory */
+            goto again;
+        }
+    }
+    return ret;
 }
 
 static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
@@ -264,6 +419,8 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 
     if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        return local_set_mapped_file_attr(fs_ctx, path, credp);
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
@@ -296,6 +453,18 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+
+        err = mknod(rpath(fs_ctx, path, buffer),
+                    SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        if (err == -1) {
+            goto out;
+        }
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
@@ -344,6 +513,17 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+        if (err == -1) {
+            goto out;
+        }
+        credp->fc_mode = credp->fc_mode|S_IFDIR;
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
@@ -404,6 +584,9 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
                       &tmp_dev, sizeof(dev_t)) > 0) {
                 stbuf->st_rdev = tmp_dev;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        errno = EOPNOTSUPP;
+        return -1;
     }
     return err;
 }
@@ -436,6 +619,19 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+        if (fd == -1) {
+            err = fd;
+            goto out;
+        }
+        credp->fc_mode = credp->fc_mode|S_IFREG;
+        /* Set client credentials in .virtfs_metadata directory files */
+        err = local_set_mapped_file_attr(fs_ctx, path, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
@@ -506,6 +702,35 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
             serrno = errno;
             goto err_end;
         }
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        int fd;
+        ssize_t oldpath_size, write_size;
+        fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
+                  SM_LOCAL_MODE_BITS);
+        if (fd == -1) {
+            err = fd;
+            goto out;
+        }
+        /* Write the oldpath (target) to the file. */
+        oldpath_size = strlen(oldpath);
+        do {
+            write_size = write(fd, (void *)oldpath, oldpath_size);
+        } while (write_size == -1 && errno == EINTR);
+
+        if (write_size != oldpath_size) {
+            serrno = errno;
+            close(fd);
+            err = -1;
+            goto err_end;
+        }
+        close(fd);
+        /* Set cleint credentials in symlink's xattr */
+        credp->fc_mode = credp->fc_mode|S_IFLNK;
+        err = local_set_mapped_file_attr(fs_ctx, newpath, credp);
+        if (err == -1) {
+            serrno = errno;
+            goto err_end;
+        }
     } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
                (fs_ctx->export_flags & V9FS_SM_NONE)) {
         err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
@@ -548,6 +773,21 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
 
     ret = link(rpath(ctx, oldpath->data, buffer),
                rpath(ctx, newpath.data, buffer1));
+
+    /* now link the virtfs_metadata files */
+    if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
+        /* Link the .virtfs_metadata files. Create the metada directory */
+        ret = local_create_mapped_attr_dir(ctx, newpath.data);
+        if (ret < 0) {
+            goto err_out;
+        }
+        ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
+                   local_mapped_attr_path(ctx, newpath.data, buffer1));
+        if (ret < 0 && errno != ENOENT) {
+            goto err_out;
+        }
+    }
+err_out:
     v9fs_string_free(&newpath);
     return ret;
 }
@@ -563,8 +803,21 @@ static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 static int local_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
+    int err;
     char buffer[PATH_MAX], buffer1[PATH_MAX];
 
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        err = local_create_mapped_attr_dir(ctx, newpath);
+        if (err < 0) {
+            return err;
+        }
+        /* rename the .virtfs_metadata files */
+        err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
+                     local_mapped_attr_path(ctx, newpath, buffer1));
+        if (err < 0 && errno != ENOENT) {
+            return err;
+        }
+    }
     return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
 }
 
@@ -580,6 +833,8 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
                       credp->fc_uid, credp->fc_gid);
     } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
         return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+    } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        return local_set_mapped_file_attr(fs_ctx, path, credp);
     }
     return -1;
 }
@@ -595,8 +850,46 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
 
 static int local_remove(FsContext *ctx, const char *path)
 {
+    int err;
+    struct stat stbuf;
     char buffer[PATH_MAX];
+
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        err =  lstat(rpath(ctx, path, buffer), &stbuf);
+        if (err) {
+            goto err_out;
+        }
+        /*
+         * If directory remove .virtfs_metadata contained in the
+         * directory
+         */
+        if (S_ISDIR(stbuf.st_mode)) {
+            sprintf(buffer, "%s/%s/%s", ctx->fs_root, path, VIRTFS_META_DIR);
+            err = remove(buffer);
+            if (err < 0 && errno != ENOENT) {
+                /*
+                 * We didn't had the .virtfs_metadata file. May be file created
+                 * in non-mapped mode ?. Ignore ENOENT.
+                 */
+                goto err_out;
+            }
+        }
+        /*
+         * Now remove the name from parent directory
+         * .virtfs_metadata directory
+         */
+        err = remove(local_mapped_attr_path(ctx, path, buffer));;
+        if (err < 0 && errno != ENOENT) {
+            /*
+             * We didn't had the .virtfs_metadata file. May be file created
+             * in non-mapped mode ?. Ignore ENOENT.
+             */
+            goto err_out;
+        }
+    }
     return remove(rpath(ctx, path, buffer));
+err_out:
+    return err;
 }
 
 static int local_fsync(FsContext *ctx, int fid_type,
@@ -696,12 +989,45 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
     int ret;
     V9fsString fullname;
     char buffer[PATH_MAX];
+
     v9fs_string_init(&fullname);
 
     v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+    if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        if (flags == AT_REMOVEDIR) {
+            /*
+             * If directory remove .virtfs_metadata contained in the
+             * directory
+             */
+            sprintf(buffer, "%s/%s/%s", ctx->fs_root,
+                    fullname.data, VIRTFS_META_DIR);
+            ret = remove(buffer);
+            if (ret < 0 && errno != ENOENT) {
+                /*
+                 * We didn't had the .virtfs_metadata file. May be file created
+                 * in non-mapped mode ?. Ignore ENOENT.
+                 */
+                goto err_out;
+            }
+        }
+        /*
+         * Now remove the name from parent directory
+         * .virtfs_metadata directory.
+         */
+        ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
+        if (ret < 0 && errno != ENOENT) {
+            /*
+             * We didn't had the .virtfs_metadata file. May be file created
+             * in non-mapped mode ?. Ignore ENOENT.
+             */
+            goto err_out;
+        }
+    }
+    /* Remove the name finally */
     ret = remove(rpath(ctx, fullname.data, buffer));
     v9fs_string_free(&fullname);
 
+err_out:
     return ret;
 }
 
@@ -736,6 +1062,19 @@ static int local_init(FsContext *ctx)
     int err = 0;
     struct statfs stbuf;
 
+    if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
+        ctx->xops = passthrough_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_MAPPED) {
+        ctx->xops = mapped_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_NONE) {
+        ctx->xops = none_xattr_ops;
+    } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+        /*
+         * xattr operation for mapped-file and passthrough
+         * remain same.
+         */
+        ctx->xops = passthrough_xattr_ops;
+    }
     ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
 #ifdef FS_IOC_GETVERSION
     /*
@@ -770,13 +1109,17 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
 
     if (!strcmp(sec_model, "passthrough")) {
         fse->export_flags |= V9FS_SM_PASSTHROUGH;
-    } else if (!strcmp(sec_model, "mapped")) {
+    } else if (!strcmp(sec_model, "mapped") ||
+               !strcmp(sec_model, "mapped-xattr")) {
         fse->export_flags |= V9FS_SM_MAPPED;
     } else if (!strcmp(sec_model, "none")) {
         fse->export_flags |= V9FS_SM_NONE;
+    } else if (!strcmp(sec_model, "mapped-file")) {
+        fse->export_flags |= V9FS_SM_MAPPED_FILE;
     } else {
         fprintf(stderr, "Invalid security model %s specified, valid options are"
-                "\n\t [passthrough|mapped|none]\n", sec_model);
+                "\n\t [passthrough|mapped-xattr|mapped-file|none]\n",
+                sec_model);
         return -1;
     }
 
index e6ba6ba30bb26196388d586d4b8ae2628fb8d922..a72ffc3390ae4953927d240f93c652f13e123efb 100644 (file)
@@ -986,7 +986,7 @@ static void v9fs_attach(void *opaque)
     s->root_fid = fid;
     /* disable migration */
     error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
-              s->ctx.fs_root, s->tag);
+              s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
     migrate_add_blocker(s->migration_blocker);
 out:
     put_fid(pdu, fidp);
@@ -1391,7 +1391,6 @@ static void v9fs_open(void *opaque)
                 err = -EROFS;
                 goto out;
             }
-            flags |= O_NOATIME;
         }
         err = v9fs_co_open(pdu, fidp, flags);
         if (err < 0) {
index 19de12b4b48a2b793e5a5eb55f5c1c2a32743c40..03b128ce5bf2948d4ed45adb607840cc9c1f8a72 100644 (file)
@@ -238,9 +238,9 @@ static TypeInfo a9mp_priv_info = {
     .class_init    = a9mp_priv_class_init,
 };
 
-static void a9mp_register_devices(void)
+static void a9mp_register_types(void)
 {
     type_register_static(&a9mp_priv_info);
 }
 
-device_init(a9mp_register_devices)
+type_init(a9mp_register_types)
index 7bf91714873feef5a6afd3e3956572b05962087d..c0fd0197a028eecbbda04b64e27736f4056ec4e9 100644 (file)
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1372,9 +1372,9 @@ static TypeInfo ac97_info = {
     .class_init    = ac97_class_init,
 };
 
-static void ac97_register (void)
+static void ac97_register_types (void)
 {
     type_register_static (&ac97_info);
 }
-device_init (ac97_register);
 
+type_init (ac97_register_types)
index 21484aec42060f638cc9e13f221af9e9f6f0b841..d959f4907bea152d61da615490186c9c2c2ff8a0 100644 (file)
@@ -426,12 +426,12 @@ static TypeInfo piix4_pm_info = {
     .class_init    = piix4_pm_class_init,
 };
 
-static void piix4_pm_register(void)
+static void piix4_pm_register_types(void)
 {
     type_register_static(&piix4_pm_info);
 }
 
-device_init(piix4_pm_register);
+type_init(piix4_pm_register_types)
 
 static uint32_t gpe_readb(void *opaque, uint32_t addr)
 {
index 3cfdecbe5cb65ab6b2691b33967abf1954a930f5..41c7f101c4c35d53f73dadb66276c4f07376ad5b 100644 (file)
@@ -168,9 +168,9 @@ static TypeInfo ads7846_info = {
     .class_init    = ads7846_class_init,
 };
 
-static void ads7846_register_devices(void)
+static void ads7846_register_types(void)
 {
     type_register_static(&ads7846_info);
 }
 
-device_init(ads7846_register_devices)
+type_init(ads7846_register_types)
index 736c28a3a9a78e4c4aebf280c728c4b57a2e61c0..b539416589f2269cd1ea9d7821f999169e9a8d43 100644 (file)
@@ -824,8 +824,9 @@ static TypeInfo typhoon_pcihost_info = {
     .class_init    = typhoon_pcihost_class_init,
 };
 
-static void typhoon_register(void)
+static void typhoon_register_types(void)
 {
     type_register_static(&typhoon_pcihost_info);
 }
-device_init(typhoon_register);
+
+type_init(typhoon_register_types)
index c7aaa72d077922cbbf5107717c7f7e174389b8a3..1d25da8da9194e075728aa7f7e6f1fabe3e4381f 100644 (file)
@@ -493,11 +493,11 @@ static TypeInfo pbm_pci_bridge_info = {
     .class_init    = pbm_pci_bridge_class_init,
 };
 
-static void pbm_register_devices(void)
+static void pbm_register_types(void)
 {
     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)
+type_init(pbm_register_types)
index 086c544bf3141c7302ff37ec00319f958769d9cb..ff9d24e9140a557366ce52d1930c5a22872ca3c4 100644 (file)
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -781,9 +781,9 @@ static TypeInfo apic_info = {
     .class_init    = apic_class_init,
 };
 
-static void apic_register_devices(void)
+static void apic_register_types(void)
 {
     type_register_static(&apic_info);
 }
 
-device_init(apic_register_devices)
+type_init(apic_register_types)
index 8373d79c41f350e23d8f27a401b03c4008c09efe..c91f7d53918a6def783cd6cd8e5728823762118d 100644 (file)
@@ -318,9 +318,9 @@ static TypeInfo apic_common_type = {
     .abstract = true,
 };
 
-static void register_devices(void)
+static void register_types(void)
 {
     type_register_static(&apic_common_type);
 }
 
-device_init(register_devices);
+type_init(register_types)
index b06487f70d6491d24c5171be1a052b7a462eb982..8bedaad3108fb13ec2099d6240e791b4ccd81ecf 100644 (file)
@@ -243,9 +243,9 @@ static TypeInfo applesmc_isa_info = {
     .class_init    = qdev_applesmc_class_init,
 };
 
-static void applesmc_register_devices(void)
+static void applesmc_register_types(void)
 {
     type_register_static(&applesmc_isa_info);
 }
 
-device_init(applesmc_register_devices)
+type_init(applesmc_register_types)
index 3c0839c4b477964d79946d69ba40731a83433ad1..102348bb7089d86b25af28550dc9d13d82499fd4 100644 (file)
@@ -252,10 +252,10 @@ static TypeInfo mpcore_priv_info = {
     .class_init    = mpcore_priv_class_init,
 };
 
-static void arm11mpcore_register_devices(void)
+static void arm11mpcore_register_types(void)
 {
     type_register_static(&mpcore_rirq_info);
     type_register_static(&mpcore_priv_info);
 }
 
-device_init(arm11mpcore_register_devices)
+type_init(arm11mpcore_register_types)
index ba26abc6f484ec39c051843c1fcc532db40436fe..09f290c85fe89e7b055b32a01418707cf3a14a4a 100644 (file)
@@ -184,9 +184,9 @@ static TypeInfo l2x0_info = {
     .class_init = l2x0_class_init,
 };
 
-static void l2x0_register_device(void)
+static void l2x0_register_types(void)
 {
     type_register_static(&l2x0_info);
 }
 
-device_init(l2x0_register_device)
+type_init(l2x0_register_types)
index 5a02365b6f09047f50bf2005b4617e7811abbee7..361e887decb39ebedf23d7687083373a09e3c038 100644 (file)
@@ -335,9 +335,9 @@ static TypeInfo arm_mptimer_info = {
     .class_init    = arm_mptimer_class_init,
 };
 
-static void arm_mptimer_register_devices(void)
+static void arm_mptimer_register_types(void)
 {
     type_register_static(&arm_mptimer_info);
 }
 
-device_init(arm_mptimer_register_devices)
+type_init(arm_mptimer_register_types)
index 9d257994c0ce165fe450b621d796d4f9b8f6b612..149c6394e600c341963b1f301fd62ed95898b2d2 100644 (file)
@@ -425,9 +425,9 @@ static TypeInfo arm_sysctl_info = {
     .class_init    = arm_sysctl_class_init,
 };
 
-static void arm_sysctl_register_devices(void)
+static void arm_sysctl_register_types(void)
 {
     type_register_static(&arm_sysctl_info);
 }
 
-device_init(arm_sysctl_register_devices)
+type_init(arm_sysctl_register_types)
index 1019d41b3e7749827a4029fe88f9f2ee4fc51705..e3ecce29f0f3b85167c0edfa44a176888f64678a 100644 (file)
@@ -383,10 +383,10 @@ static TypeInfo sp804_info = {
     .class_init    = sp804_class_init,
 };
 
-static void arm_timer_register_devices(void)
+static void arm_timer_register_types(void)
 {
     type_register_static(&icp_pit_info);
     type_register_static(&sp804_info);
 }
 
-device_init(arm_timer_register_devices)
+type_init(arm_timer_register_types)
index de3d7e08284f55b013e09e426e1efe6eb43b3a35..6b805798e6dcbe8471c3e847b1f65176f4f6d571 100644 (file)
@@ -266,9 +266,9 @@ static TypeInfo bitband_info = {
     .class_init    = bitband_class_init,
 };
 
-static void armv7m_register_devices(void)
+static void armv7m_register_types(void)
 {
     type_register_static(&bitband_info);
 }
 
-device_init(armv7m_register_devices)
+type_init(armv7m_register_types)
index 1ed0abc3e7f743745ac346d7006ca4fe53f6d709..3210129c3f0a120ef11596fd29aa6138ae02c760 100644 (file)
@@ -417,9 +417,9 @@ static TypeInfo armv7m_nvic_info = {
     .class_init    = armv7m_nvic_class_init,
 };
 
-static void armv7m_nvic_register_devices(void)
+static void armv7m_nvic_register_types(void)
 {
     type_register_static(&armv7m_nvic_info);
 }
 
-device_init(armv7m_nvic_register_devices)
+type_init(armv7m_nvic_register_types)
index c9c11823af553625422022bd5bc54ae713b30412..44ed7f4d6182c0fd8cc77c67ec01f3f90eecf624 100644 (file)
@@ -237,9 +237,9 @@ static TypeInfo gpio_i2c_info = {
     .class_init    = gpio_i2c_class_init,
 };
 
-static void bitbang_i2c_register(void)
+static void bitbang_i2c_register_types(void)
 {
     type_register_static(&gpio_i2c_info);
 }
 
-device_init(bitbang_i2c_register)
+type_init(bitbang_i2c_register_types)
index 7350a4f9ec623bfd0cede608e3c3fc0c1dbac09f..77786f8883efc3253d9baeab6841313aca79ff9d 100644 (file)
@@ -804,9 +804,10 @@ static TypeInfo bonito_pcihost_info = {
     .class_init    = bonito_pcihost_class_init,
 };
 
-static void bonito_register(void)
+static void bonito_register_types(void)
 {
     type_register_static(&bonito_pcihost_info);
     type_register_static(&bonito_info);
 }
-device_init(bonito_register);
+
+type_init(bonito_register_types)
index 9510ed4d944e6e7ff6e4010ca8c3bf69aee4769a..f4a6da4283a3a27eaff154be7ad6ca75dee900d5 100644 (file)
@@ -594,9 +594,9 @@ static TypeInfo emulated_card_info = {
     .class_init    = emulated_class_initfn,
 };
 
-static void ccid_card_emulated_register_devices(void)
+static void ccid_card_emulated_register_types(void)
 {
     type_register_static(&emulated_card_info);
 }
 
-device_init(ccid_card_emulated_register_devices)
+type_init(ccid_card_emulated_register_types)
index a7006ca0357ac03e7017f481f735c32c1320ea7d..bd6c77777da4207e109ff9ff0802b25987ce61d6 100644 (file)
@@ -343,9 +343,9 @@ static TypeInfo passthru_card_info = {
     .class_init    = passthru_class_initfn,
 };
 
-static void ccid_card_passthru_register_devices(void)
+static void ccid_card_passthru_register_types(void)
 {
     type_register_static(&passthru_card_info);
 }
 
-device_init(ccid_card_passthru_register_devices)
+type_init(ccid_card_passthru_register_types)
index a8e8ab76606499a6adc3c60bd87418a3d2d788b8..4edcb947743b9b8728980b94b1b5a1d585d3695c 100644 (file)
@@ -2923,12 +2923,6 @@ static TypeInfo isa_cirrus_vga_info = {
     .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
@@ -2996,8 +2990,10 @@ static TypeInfo cirrus_vga_info = {
     .class_init    = cirrus_vga_class_init,
 };
 
-static void cirrus_vga_register(void)
+static void cirrus_vga_register_types(void)
 {
+    type_register_static(&isa_cirrus_vga_info);
     type_register_static(&cirrus_vga_info);
 }
-device_init(cirrus_vga_register);
+
+type_init(cirrus_vga_register_types)
index c0badbff5ccacd385637b05b2251d78c32d4fea8..cfec1d9cd158402b35cf116f6b43236ed3e703f4 100644 (file)
@@ -173,9 +173,9 @@ static TypeInfo cs4231_info = {
     .class_init    = cs4231_class_init,
 };
 
-static void cs4231_register_devices(void)
+static void cs4231_register_types(void)
 {
     type_register_static(&cs4231_info);
 }
 
-device_init(cs4231_register_devices)
+type_init(cs4231_register_types)
index ad04ad667c8df36e683762dfa1449f729ea6fc1e..e07b9d62371f6f7019598d0fc7f6bc1fd357393c 100644 (file)
@@ -689,8 +689,9 @@ static TypeInfo cs4231a_info = {
     .class_init    = cs4231a_class_initfn,
 };
 
-static void cs4231a_register (void)
+static void cs4231a_register_types (void)
 {
     type_register_static (&cs4231a_info);
 }
-device_init (cs4231a_register)
+
+type_init (cs4231a_register_types)
index 3903b2605d1309d915648d06c022d0602c5b189e..14ab326be360a7a35f84497bc829f0adeb86ea20 100644 (file)
@@ -109,9 +109,9 @@ static TypeInfo debugcon_isa_info = {
     .class_init    = debugcon_isa_class_initfn,
 };
 
-static void debugcon_register_devices(void)
+static void debugcon_register_types(void)
 {
     type_register_static(&debugcon_isa_info);
 }
 
-device_init(debugcon_register_devices)
+type_init(debugcon_register_types)
index a40fbcf3e57e3293056417fb381582e653b982ca..37337bf4b637d89aee865393d9c95fbf01447a33 100644 (file)
@@ -140,11 +140,11 @@ static TypeInfo pci_dec_21154_device_info = {
     .class_init    = pci_dec_21154_device_class_init,
 };
 
-static void dec_register_devices(void)
+static void dec_register_types(void)
 {
     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)
+type_init(dec_register_types)
index 539bcebae03734fec2f30445d731b184d87b3abb..2cd355bd0a225b9b584becc1a021a4d4b3c4f9ad 100644 (file)
@@ -157,9 +157,9 @@ static TypeInfo nvram_sysbus_info = {
     .class_init    = nvram_sysbus_class_init,
 };
 
-static void nvram_register(void)
+static void nvram_register_types(void)
 {
     type_register_static(&nvram_sysbus_info);
 }
 
-device_init(nvram_register)
+type_init(nvram_register_types)
index b137e133790e41e1a25fbdcc8f1e383665f336db..6397f0aa6f94a86c0768182fa932fc8361ab7b63 100644 (file)
@@ -135,9 +135,9 @@ static TypeInfo ds1338_info = {
     .class_init    = ds1338_class_init,
 };
 
-static void ds1338_register_devices(void)
+static void ds1338_register_types(void)
 {
     type_register_static(&ds1338_info);
 }
 
-device_init(ds1338_register_devices)
+type_init(ds1338_register_types)
index 751f79d5ff9c806f7d38b473a00dc39f6d048cf3..7babc0b06eafd2e0f934f909cdf28bc9f3e3cdbf 100644 (file)
@@ -1227,9 +1227,9 @@ static TypeInfo e1000_info = {
     .class_init    = e1000_class_init,
 };
 
-static void e1000_register_devices(void)
+static void e1000_register_types(void)
 {
     type_register_static(&e1000_info);
 }
 
-device_init(e1000_register_devices)
+type_init(e1000_register_types)
index 1cf2090c1f784d5ca63a70d095228bca1a4a8a89..fe1cd9000757f7f17b2cb86401adfd727dc1dba1 100644 (file)
@@ -332,9 +332,9 @@ static TypeInfo ecc_info = {
 };
 
 
-static void ecc_register_devices(void)
+static void ecc_register_types(void)
 {
     type_register_static(&ecc_info);
 }
 
-device_init(ecc_register_devices)
+type_init(ecc_register_types)
index 843610c933c209745a4a918a891e733d60997228..e3ba71974ed6fbbf9116593cc592e10b10b26ecb 100644 (file)
@@ -2089,7 +2089,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data)
     k->subsystem_id = info->subsystem_id;
 }
 
-static void eepro100_register_devices(void)
+static void eepro100_register_types(void)
 {
     size_t i;
     for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
@@ -2105,4 +2105,4 @@ static void eepro100_register_devices(void)
     }
 }
 
-device_init(eepro100_register_devices)
+type_init(eepro100_register_types)
index 1bc181555f59b8e813dae34a15987aad187097df..099c85e58338bad9bdbf7496c7e8ba1ca6bac1df 100644 (file)
@@ -90,9 +90,9 @@ static TypeInfo empty_slot_info = {
     .class_init    = empty_slot_class_init,
 };
 
-static void empty_slot_register_devices(void)
+static void empty_slot_register_types(void)
 {
     type_register_static(&empty_slot_info);
 }
 
-device_init(empty_slot_register_devices);
+type_init(empty_slot_register_types)
index e377c48e4997127f367552c252e00632fc5d172f..f19cef31a6ca0c622c205c653dbb2560c9ae99be 100644 (file)
@@ -1054,9 +1054,10 @@ static TypeInfo es1370_info = {
     .class_init    = es1370_class_init,
 };
 
-static void es1370_register (void)
+static void es1370_register_types (void)
 {
     type_register_static (&es1370_info);
 }
-device_init (es1370_register);
+
+type_init (es1370_register_types)
 
index 9fe282f7b815d870054f2c6f54aff306d5be7423..4d8a8e88867e613f90cd03583104c44a76d7f2d0 100644 (file)
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -931,9 +931,9 @@ static TypeInfo escc_info = {
     .class_init    = escc_class_init,
 };
 
-static void escc_register_devices(void)
+static void escc_register_types(void)
 {
     type_register_static(&escc_info);
 }
 
-device_init(escc_register_devices)
+type_init(escc_register_types)
index 2f44386233dec7799da7bb567830607db298630f..2dda8e358e52f047556a7b47ad3c9ae56e105672 100644 (file)
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -775,9 +775,9 @@ static TypeInfo esp_info = {
     .class_init    = esp_class_init,
 };
 
-static void esp_register_devices(void)
+static void esp_register_types(void)
 {
     type_register_static(&esp_info);
 }
 
-device_init(esp_register_devices)
+type_init(esp_register_types)
index aefd5778ab03c89b4278882e57a420877150160e..16a0637a4a9aed1ff3bb9277ca59ed5f805cf04b 100644 (file)
@@ -637,9 +637,9 @@ static TypeInfo etraxfs_eth_info = {
     .class_init    = etraxfs_eth_class_init,
 };
 
-static void etraxfs_eth_register(void)
+static void etraxfs_eth_register_types(void)
 {
     type_register_static(&etraxfs_eth_info);
 }
 
-device_init(etraxfs_eth_register)
+type_init(etraxfs_eth_register_types)
index 33541fcc61711e9cfde1d0d594f09603ecc0f5f4..dc27f88ac9509cf70abdfa43e1276e587922ae91 100644 (file)
@@ -172,9 +172,9 @@ static TypeInfo etraxfs_pic_info = {
     .class_init    = etraxfs_pic_class_init,
 };
 
-static void etraxfs_pic_register(void)
+static void etraxfs_pic_register_types(void)
 {
     type_register_static(&etraxfs_pic_info);
 }
 
-device_init(etraxfs_pic_register)
+type_init(etraxfs_pic_register_types)
index 567cb8cc2d0cb124cfbe1145256868b10485538a..cecd8195843763a9985519ac982b0e969bfd8bd3 100644 (file)
@@ -240,9 +240,9 @@ static TypeInfo etraxfs_ser_info = {
     .class_init    = etraxfs_ser_class_init,
 };
 
-static void etraxfs_serial_register(void)
+static void etraxfs_serial_register_types(void)
 {
     type_register_static(&etraxfs_ser_info);
 }
 
-device_init(etraxfs_serial_register)
+type_init(etraxfs_serial_register_types)
index b71c5ee9d5e997a3af9c1fec2ef1af44bade8198..9076a49884e8626b9efb463ffa2e8fef730ac302 100644 (file)
@@ -343,9 +343,9 @@ static TypeInfo etraxfs_timer_info = {
     .class_init    = etraxfs_timer_class_init,
 };
 
-static void etraxfs_timer_register(void)
+static void etraxfs_timer_register_types(void)
 {
     type_register_static(&etraxfs_timer_info);
 }
 
-device_init(etraxfs_timer_register)
+type_init(etraxfs_timer_register_types)
index f575a2c9f579456f8d255bbd0cecc6dbf271eeab..38fad587cbaec42e4d96edd5cc6cefbb72d5e146 100644 (file)
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -2043,11 +2043,11 @@ static TypeInfo sun4m_fdc_info = {
     .class_init    = sun4m_fdc_class_init,
 };
 
-static void fdc_register_devices(void)
+static void fdc_register_types(void)
 {
     type_register_static(&isa_fdc_info);
     type_register_static(&sysbus_fdc_info);
     type_register_static(&sun4m_fdc_info);
 }
 
-device_init(fdc_register_devices)
+type_init(fdc_register_types)
index ea122fb2668bac20b38694bad88105cff901185f..f4747cd646629ced9ed8822e6eaa6850b6003e88 100644 (file)
@@ -87,7 +87,7 @@ void framebuffer_update_display(
     dest += i * dest_row_pitch;
 
     for (; i < rows; i++) {
-        dirty = memory_region_get_dirty(mem, addr, addr + src_width,
+        dirty = memory_region_get_dirty(mem, addr, src_width,
                                              DIRTY_MEMORY_VGA);
         if (dirty || invalidate) {
             fn(opaque, dest, src, cols, dest_col_pitch);
index 6b2f7d19863ab29aa04899eeabbbc248c42571a4..7b3b5769a261eec57934e896e1caa73b9d26567a 100644 (file)
@@ -556,9 +556,9 @@ static TypeInfo fw_cfg_info = {
     .class_init    = fw_cfg_class_init,
 };
 
-static void fw_cfg_register_devices(void)
+static void fw_cfg_register_types(void)
 {
     type_register_static(&fw_cfg_info);
 }
 
-device_init(fw_cfg_register_devices)
+type_init(fw_cfg_register_types)
index 66d0044c0627924723847078b738a3f3c402f5b7..9c63bddc59a07d19282c494cd5131e110b52a4f0 100644 (file)
@@ -574,9 +574,9 @@ static TypeInfo g364fb_sysbus_info = {
     .class_init    = g364fb_sysbus_class_init,
 };
 
-static void g364fb_register(void)
+static void g364fb_register_types(void)
 {
     type_register_static(&g364fb_sysbus_info);
 }
 
-device_init(g364fb_register);
+type_init(g364fb_register_types)
index 8122baf482685e4ff1e21a06165781d8469bfe01..81ff3a339adcf35d4d2e7da3804dfdb32d6ceec7 100644 (file)
@@ -157,10 +157,10 @@ static TypeInfo grackle_pci_host_info = {
     .class_init    = pci_grackle_class_init,
 };
 
-static void grackle_register_devices(void)
+static void grackle_register_types(void)
 {
     type_register_static(&grackle_pci_info);
     type_register_static(&grackle_pci_host_info);
 }
 
-device_init(grackle_register_devices)
+type_init(grackle_register_types)
index 89de2d85ae956f38b89a1bfcfda24a8b9b80563c..73fc9894db336ea15f8e00d195adcb3e61671274 100644 (file)
@@ -263,9 +263,9 @@ static TypeInfo grlib_gptimer_info = {
     .class_init    = grlib_gptimer_class_init,
 };
 
-static void grlib_gptimer_register(void)
+static void grlib_gptimer_register_types(void)
 {
     type_register_static(&grlib_gptimer_info);
 }
 
-device_init(grlib_gptimer_register)
+type_init(grlib_gptimer_register_types)
index fb0b236746a76ed20acaefb5439d70ba2db514f4..41770a9e6c7a71abec183c869048dff85a53f8e5 100644 (file)
@@ -396,9 +396,9 @@ static TypeInfo grlib_gptimer_info = {
     .class_init    = grlib_gptimer_class_init,
 };
 
-static void grlib_gptimer_register(void)
+static void grlib_gptimer_register_types(void)
 {
     type_register_static(&grlib_gptimer_info);
 }
 
-device_init(grlib_gptimer_register)
+type_init(grlib_gptimer_register_types)
index 1e5ad826f51c4ec15198378aaaa32fd574666090..0f6e65cf204d591248b7c57a7a3eb6b73f43051d 100644 (file)
@@ -377,9 +377,9 @@ static TypeInfo grlib_irqmp_info = {
     .class_init    = grlib_irqmp_class_init,
 };
 
-static void grlib_irqmp_register(void)
+static void grlib_irqmp_register_types(void)
 {
     type_register_static(&grlib_irqmp_info);
 }
 
-device_init(grlib_irqmp_register)
+type_init(grlib_irqmp_register_types)
index e8cd59c3a45ede9bc59fcac045fbfa5f1aaa1c24..a2d0e5a2c3f028a197411bd26d58f1d1d7b78e7a 100644 (file)
@@ -1168,10 +1168,10 @@ static TypeInfo gt64120_info = {
     .class_init    = gt64120_class_init,
 };
 
-static void gt64120_pci_register_devices(void)
+static void gt64120_pci_register_types(void)
 {
     type_register_static(&gt64120_info);
     type_register_static(&gt64120_pci_info);
 }
 
-device_init(gt64120_pci_register_devices)
+type_init(gt64120_pci_register_types)
index 20547075ec91e5ea32bd351de05cb782cffea9bf..840d098d6ae406452501428a7d7a345f92aafd56 100644 (file)
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -324,8 +324,9 @@ static TypeInfo gus_info = {
     .class_init    = gus_class_initfn,
 };
 
-static void gus_register (void)
+static void gus_register_types (void)
 {
     type_register_static (&gus_info);
 }
-device_init (gus_register)
+
+type_init (gus_register_types)
index 152f8e6f139081c041a589143dc640026302bdc5..8995519573d1ec85cceb446037bb9181647e5793 100644 (file)
@@ -948,9 +948,10 @@ static TypeInfo hda_audio_duplex_info = {
     .class_init    = hda_audio_duplex_class_init,
 };
 
-static void hda_audio_register(void)
+static void hda_audio_register_types(void)
 {
     type_register_static(&hda_audio_output_info);
     type_register_static(&hda_audio_duplex_info);
 }
-device_init(hda_audio_register);
+
+type_init(hda_audio_register_types)
index 684178ee3e53fcf5cf45fc42e2a39387c9329c05..b28b4640aa4f8c4e1d5ab8338bfa0a9478cdb968 100644 (file)
@@ -177,12 +177,12 @@ static TypeInfo highbank_regs_info = {
     .class_init    = highbank_regs_class_init,
 };
 
-static void highbank_regs_register_device(void)
+static void highbank_regs_register_types(void)
 {
     type_register_static(&highbank_regs_info);
 }
 
-device_init(highbank_regs_register_device)
+type_init(highbank_regs_register_types)
 
 static struct arm_boot_info highbank_binfo;
 
index b6ace4e69692b3e74e417e2d9fe9821e67b2f061..ba36e103d09d9076ad43fd2c7a3f6cc0e84b89c2 100644 (file)
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -720,9 +720,9 @@ static TypeInfo hpet_device_info = {
     .class_init    = hpet_device_class_init,
 };
 
-static void hpet_register_device(void)
+static void hpet_register_types(void)
 {
     type_register_static(&hpet_device_info);
 }
 
-device_init(hpet_register_device)
+type_init(hpet_register_types)
index 8ae4aaae1da4414c1ed6f893a76972c3ab5b94c5..23dfccba149925bcd9de4f38185b4451240a4652 100644 (file)
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -230,9 +230,9 @@ static TypeInfo i2c_slave_type_info = {
     .class_init = i2c_slave_class_init,
 };
 
-static void i2c_slave_register_devices(void)
+static void i2c_slave_register_types(void)
 {
     type_register_static(&i2c_slave_type_info);
 }
 
-device_init(i2c_slave_register_devices);
+type_init(i2c_slave_register_types)
index 220e8cccb6c8785001a7dd5683c34d67fead9b83..67298a39f5e46c24b3c95d65209f53ba04323dfb 100644 (file)
@@ -157,9 +157,9 @@ static TypeInfo i82374_isa_info = {
     .class_init = i82374_class_init,
 };
 
-static void i82374_register_devices(void)
+static void i82374_register_types(void)
 {
     type_register_static(&i82374_isa_info);
 }
 
-device_init(i82374_register_devices)
+type_init(i82374_register_types)
index 9c3efe8b95fc47b50f23054f690d520d94258610..3929c041b753c8b62ab9b2fbe319f44380c4c094 100644 (file)
@@ -267,9 +267,9 @@ static TypeInfo pci_i82378_info = {
     .class_init = pci_i82378_class_init,
 };
 
-static void i82378_register_devices(void)
+static void i82378_register_types(void)
 {
     type_register_static(&pci_i82378_info);
 }
 
-device_init(i82378_register_devices)
+type_init(i82378_register_types)
index 522fed88097c3042e27bc6d660fcfeee0c8e6bea..481fc7b2523ff8df628b7c724724de46a2c9a876 100644 (file)
@@ -559,8 +559,9 @@ static TypeInfo pit_info = {
     .class_init    = pit_class_initfn,
 };
 
-static void pit_register(void)
+static void pit_register_types(void)
 {
     type_register_static(&pit_info);
 }
-device_init(pit_register)
+
+type_init(pit_register_types)
index 7ae53805d71bca73ef25bb801c12a1918821cd23..1a4b1ab0dd20b484693c4389fa51c7f5f7091fc8 100644 (file)
@@ -488,9 +488,9 @@ static TypeInfo i8259_info = {
     .class_init = i8259_class_init,
 };
 
-static void pic_register(void)
+static void pic_register_types(void)
 {
     type_register_static(&i8259_info);
 }
 
-device_init(pic_register)
+type_init(pic_register_types)
index 9f150bc6d087860fb25b74c073e311aba3f062e5..775fda453c3573d83a151346710b13ca1a39617a 100644 (file)
@@ -153,9 +153,9 @@ static TypeInfo pic_common_type = {
     .abstract = true,
 };
 
-static void register_devices(void)
+static void register_types(void)
 {
     type_register_static(&pic_common_type);
 }
 
-device_init(register_devices);
+type_init(register_types);
index c87a6ca515b710402ea7b52736fc3b7be1a70856..b515f417b169bea698212333433178248af87921 100644 (file)
@@ -146,6 +146,7 @@ static void ahci_check_irq(AHCIState *s)
 
     DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus);
 
+    s->control_regs.irqstatus = 0;
     for (i = 0; i < s->ports; i++) {
         AHCIPortRegs *pr = &s->dev[i].port_regs;
         if (pr->irq_stat & pr->irq_mask) {
@@ -216,6 +217,7 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
             break;
         case PORT_IRQ_STAT:
             pr->irq_stat &= ~val;
+            ahci_check_irq(s);
             break;
         case PORT_IRQ_MASK:
             pr->irq_mask = val & 0xfdc000ff;
@@ -560,6 +562,11 @@ static void ahci_reset_port(AHCIState *s, int port)
             ncq_tfs->aiocb = NULL;
         }
 
+        /* Maybe we just finished the request thanks to bdrv_aio_cancel() */
+        if (!ncq_tfs->used) {
+            continue;
+        }
+
         qemu_sglist_destroy(&ncq_tfs->sglist);
         ncq_tfs->used = 0;
     }
@@ -1261,9 +1268,9 @@ static TypeInfo sysbus_ahci_info = {
     .class_init    = sysbus_ahci_class_init,
 };
 
-static void sysbus_ahci_register(void)
+static void sysbus_ahci_register_types(void)
 {
     type_register_static(&sysbus_ahci_info);
 }
 
-device_init(sysbus_ahci_register);
+type_init(sysbus_ahci_register_types)
index a119500f4051727061c259c10ed90638840e38be..743ec024067e2f149b6e683e7d01e57245b9f02d 100644 (file)
@@ -351,8 +351,9 @@ static TypeInfo cmd646_ide_info = {
     .class_init    = cmd646_ide_class_init,
 };
 
-static void cmd646_ide_register(void)
+static void cmd646_ide_register_types(void)
 {
     type_register_static(&cmd646_ide_info);
 }
-device_init(cmd646_ide_register);
+
+type_init(cmd646_ide_register_types)
index 5cdaa990ea17cf781fcb51beed67cecbac2d3d84..560ae376187f843e29fa4f554f19367c89b43859 100644 (file)
@@ -168,8 +168,9 @@ static TypeInfo ich_ahci_info = {
     .class_init    = ich_ahci_class_init,
 };
 
-static void ich_ahci_register(void)
+static void ich_ahci_register_types(void)
 {
     type_register_static(&ich_ahci_info);
 }
-device_init(ich_ahci_register);
+
+type_init(ich_ahci_register_types)
index a0bcb43ebacb8a849c44dce4f9981639573a9315..8ab2718eeaebf837b1a24a6b784b8a8fb7d27398 100644 (file)
@@ -118,9 +118,9 @@ static TypeInfo isa_ide_info = {
     .class_init    = isa_ide_class_initfn,
 };
 
-static void isa_ide_register_devices(void)
+static void isa_ide_register_types(void)
 {
     type_register_static(&isa_ide_info);
 }
 
-device_init(isa_ide_register_devices)
+type_init(isa_ide_register_types)
index bf4465bb4906733c24db6c30618725f312e3da00..aee60aa390af4fe1878f4529c918b57c71190f5d 100644 (file)
@@ -299,10 +299,11 @@ static TypeInfo piix4_ide_info = {
     .class_init    = piix4_ide_class_init,
 };
 
-static void piix_ide_register(void)
+static void piix_ide_register_types(void)
 {
     type_register_static(&piix3_ide_info);
     type_register_static(&piix3_ide_xen_info);
     type_register_static(&piix4_ide_info);
 }
-device_init(piix_ide_register);
+
+type_init(piix_ide_register_types)
index 1640616906f684ba53ec96f63cf1ff8596ce78c0..f6a48961c54dfcb867f8b7e4cf633aba558b4878 100644 (file)
@@ -257,11 +257,12 @@ static TypeInfo ide_device_type_info = {
     .class_init = ide_device_class_init,
 };
 
-static void ide_dev_register(void)
+static void ide_register_types(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);
+
+type_init(ide_register_types)
index b4ca6f27b38f086cf7bc3fb86f5f020503e013de..2886bc6dfb4725ec0d4a7dff95607f11adeaa246 100644 (file)
@@ -234,8 +234,9 @@ static TypeInfo via_ide_info = {
     .class_init    = via_ide_class_init,
 };
 
-static void via_ide_register(void)
+static void via_ide_register_types(void)
 {
     type_register_static(&via_ide_info);
 }
-device_init(via_ide_register);
+
+type_init(via_ide_register_types)
index 6dbd64990868bbd2dc21686228c79f06bf2ae4de..294d7da7fc8442c5fdc0cf9da37733f038769f67 100644 (file)
@@ -553,10 +553,10 @@ static TypeInfo icp_pic_info = {
     .class_init    = icp_pic_class_init,
 };
 
-static void integratorcp_register_devices(void)
+static void integratorcp_register_types(void)
 {
     type_register_static(&icp_pic_info);
     type_register_static(&core_info);
 }
 
-device_init(integratorcp_register_devices)
+type_init(integratorcp_register_types)
index 83c42d58b60c832b824a040ae1689b932b044c9e..bb11af286a81135d3c0384f5072411fa6dacd5b5 100644 (file)
@@ -1287,12 +1287,13 @@ static TypeInfo hda_codec_device_type_info = {
     .class_init = hda_codec_device_class_init,
 };
 
-static void intel_hda_register(void)
+static void intel_hda_register_types(void)
 {
     type_register_static(&intel_hda_info);
     type_register_static(&hda_codec_device_type_info);
 }
-device_init(intel_hda_register);
+
+type_init(intel_hda_register_types)
 
 /*
  * create intel hda controller with codec attached to it,
index 79549f8ed1ef5db8ad9e820472ae037d74237dc6..3fee0114d9118671ada957c6b5c1e792a57e082a 100644 (file)
@@ -251,9 +251,9 @@ static TypeInfo ioapic_info = {
     .class_init    = ioapic_class_init,
 };
 
-static void ioapic_register_devices(void)
+static void ioapic_register_types(void)
 {
     type_register_static(&ioapic_info);
 }
 
-device_init(ioapic_register_devices)
+type_init(ioapic_register_types)
index f932700d129965065fadbaf8a9902eb3dcb81bc5..653eef2ce1a239602a13f5168e9582f40d4304ee 100644 (file)
@@ -112,10 +112,9 @@ static TypeInfo ioapic_common_type = {
     .abstract = true,
 };
 
-static void register_devices(void)
+static void register_types(void)
 {
     type_register_static(&ioapic_common_type);
 }
 
-device_init(register_devices);
-
+type_init(register_types)
index 1c60123d433dc67d41f1f20dcb87c26b62624692..1632d31c191001e68fbb1d86a4d18fb6b1575635 100644 (file)
@@ -237,12 +237,12 @@ static TypeInfo ioh3420_info = {
     .class_init    = ioh3420_class_init,
 };
 
-static void ioh3420_register(void)
+static void ioh3420_register_types(void)
 {
     type_register_static(&ioh3420_info);
 }
 
-device_init(ioh3420_register);
+type_init(ioh3420_register_types)
 
 /*
  * Local variables:
index d03f82824ca6cd12ee5761a9ad4474724dcf673f..5a43f03a7c342bf21ccc0585126bb94ded5d1237 100644 (file)
@@ -210,7 +210,7 @@ static TypeInfo isa_device_type_info = {
     .class_init = isa_device_class_init,
 };
 
-static void isabus_register_devices(void)
+static void isabus_register_types(void)
 {
     type_register_static(&isabus_bridge_info);
     type_register_static(&isa_device_type_info);
@@ -235,4 +235,4 @@ MemoryRegion *isa_address_space(ISADevice *dev)
     return get_system_memory();
 }
 
-device_init(isabus_register_devices)
+type_init(isabus_register_types)
index 6f017d474c03f7041a858da17c193671affcbee9..64e1cd968e710f22bdf872ce99f36fc85571f13f 100644 (file)
@@ -798,9 +798,9 @@ static TypeInfo ivshmem_info = {
     .class_init    = ivshmem_class_init,
 };
 
-static void ivshmem_register_devices(void)
+static void ivshmem_register_types(void)
 {
     type_register_static(&ivshmem_info);
 }
 
-device_init(ivshmem_register_devices)
+type_init(ivshmem_register_types)
index dfc2ab3b03b9a4d714e6633281f4443f721a9355..5bb0a4b9fda7c5ebd5a110deee05b2c6acbf2389 100644 (file)
@@ -139,9 +139,9 @@ static TypeInfo kvm_apic_info = {
     .class_init = kvm_apic_class_init,
 };
 
-static void kvm_apic_register_device(void)
+static void kvm_apic_register_types(void)
 {
     type_register_static(&kvm_apic_info);
 }
 
-device_init(kvm_apic_register_device)
+type_init(kvm_apic_register_types)
index d5a53869b3fe7ac97e23e7405ef8a158bb5f277f..2157340326f21b8a12f2552b690e324e05446833 100644 (file)
@@ -119,11 +119,11 @@ void kvmclock_create(void)
     }
 }
 
-static void kvmclock_register_device(void)
+static void kvmclock_register_types(void)
 {
     if (kvm_enabled()) {
     type_register_static(&kvmclock_info);
     }
 }
 
-device_init(kvmclock_register_device);
+type_init(kvmclock_register_types)
index 14bd4275188c63d50526050964b7e3ac93a1049b..eb98889329b8f9c9d5b6a90f49e0a5a7b03ab656 100644 (file)
@@ -130,9 +130,9 @@ static TypeInfo kvm_i8259_info = {
     .class_init = kvm_i8259_class_init,
 };
 
-static void kvm_pic_register(void)
+static void kvm_pic_register_types(void)
 {
     type_register_static(&kvm_i8259_info);
 }
 
-device_init(kvm_pic_register)
+type_init(kvm_pic_register_types)
index b316933a9661a81eaf475bc48262b6215378030d..3ae317540347b35d0275d96b8d3f2f9b49259e2b 100644 (file)
@@ -117,9 +117,9 @@ static TypeInfo kvm_ioapic_info = {
     .class_init = kvm_ioapic_class_init,
 };
 
-static void kvm_ioapic_register_device(void)
+static void kvm_ioapic_register_types(void)
 {
     type_register_static(&kvm_ioapic_info);
 }
 
-device_init(kvm_ioapic_register_device)
+type_init(kvm_ioapic_register_types)
index 78777c73362f8ea8efabc9e72d4a79a3ace47083..aeb0c395294b01877eb9d4be620e052af19e2b02 100644 (file)
@@ -1261,7 +1261,7 @@ static TypeInfo lan9118_info = {
     .class_init    = lan9118_class_init,
 };
 
-static void lan9118_register_devices(void)
+static void lan9118_register_types(void)
 {
     type_register_static(&lan9118_info);
 }
@@ -1282,4 +1282,4 @@ void lan9118_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     sysbus_connect_irq(s, 0, irq);
 }
 
-device_init(lan9118_register_devices)
+type_init(lan9118_register_types)
index 519720bd9c37f2c345e87e1a6a322aac4af1c1b8..ce3d46c17bca8aaa4c9a7de4d6b851de8e73d98b 100644 (file)
@@ -162,8 +162,9 @@ static TypeInfo lance_info = {
     .class_init    = lance_class_init,
 };
 
-static void lance_register_devices(void)
+static void lance_register_types(void)
 {
     type_register_static(&lance_info);
 }
-device_init(lance_register_devices)
+
+type_init(lance_register_types)
index 38dd28230d523fd07a90ec8323dd67acf559d405..f07ed3977f5b8d67f2105e17493df7e1e4a1fd8d 100644 (file)
@@ -151,9 +151,9 @@ static TypeInfo lm32_juart_info = {
     .class_init    = lm32_juart_class_init,
 };
 
-static void lm32_juart_register(void)
+static void lm32_juart_register_types(void)
 {
     type_register_static(&lm32_juart_info);
 }
 
-device_init(lm32_juart_register)
+type_init(lm32_juart_register_types)
index 7be6d0d68ed34eb003b6e123c2956cd606842f28..32f65db7f13ad868a48311e7afef6103b6933cc2 100644 (file)
@@ -191,9 +191,9 @@ static TypeInfo lm32_pic_info = {
     .class_init    = lm32_pic_class_init,
 };
 
-static void lm32_pic_register(void)
+static void lm32_pic_register_types(void)
 {
     type_register_static(&lm32_pic_info);
 }
 
-device_init(lm32_pic_register)
+type_init(lm32_pic_register_types)
index ba6f4acbaa9d1a7ccd03d1fd66c81fe47b089221..bbe03c41d568d9f15423d9b59933dcb399b837e1 100644 (file)
@@ -164,9 +164,9 @@ static TypeInfo lm32_sys_info = {
     .class_init    = lm32_sys_class_init,
 };
 
-static void lm32_sys_register(void)
+static void lm32_sys_register_types(void)
 {
     type_register_static(&lm32_sys_info);
 }
 
-device_init(lm32_sys_register)
+type_init(lm32_sys_register_types)
index 3cb4e0a4f3cd330b8773776fdd69b0643e0978c1..e9450a0ce178d6156aaf4ad875cf8a1f84467e14 100644 (file)
@@ -222,9 +222,9 @@ static TypeInfo lm32_timer_info = {
     .class_init    = lm32_timer_class_init,
 };
 
-static void lm32_timer_register(void)
+static void lm32_timer_register_types(void)
 {
     type_register_static(&lm32_timer_info);
 }
 
-device_init(lm32_timer_register)
+type_init(lm32_timer_register_types)
index 630ccb713130bb5a5377d519bccf4da9ed4b0e07..57066e28c66c9bae1669257af6172925bf64ca8e 100644 (file)
@@ -288,9 +288,9 @@ static TypeInfo lm32_uart_info = {
     .class_init    = lm32_uart_class_init,
 };
 
-static void lm32_uart_register(void)
+static void lm32_uart_register_types(void)
 {
     type_register_static(&lm32_uart_info);
 }
 
-device_init(lm32_uart_register)
+type_init(lm32_uart_register_types)
index 895d306635150497e3be58cdb26378b61333b36c..8e09f9bcc9643a64cfdd614b764d96e2f0329c9b 100644 (file)
@@ -513,9 +513,9 @@ static TypeInfo lm8323_info = {
     .class_init    = lm8323_class_init,
 };
 
-static void lm832x_register_devices(void)
+static void lm832x_register_types(void)
 {
     type_register_static(&lm8323_info);
 }
 
-device_init(lm832x_register_devices)
+type_init(lm832x_register_types)
index 9a7ffe3f42391fffd5cb0addb7a8a73a1d75dc14..0acd1d06df3b0aaa338dfffaf15c190fdc40e86a 100644 (file)
@@ -2142,9 +2142,9 @@ static TypeInfo lsi_info = {
     .class_init    = lsi_class_init,
 };
 
-static void lsi53c895a_register_devices(void)
+static void lsi53c895a_register_types(void)
 {
     type_register_static(&lsi_info);
 }
 
-device_init(lsi53c895a_register_devices);
+type_init(lsi53c895a_register_types)
index c35867d0a10afa8d29d8e93cc425a4b86b8050ac..60bbb00946e2a25453268bffbf2080299b763670 100644 (file)
@@ -768,10 +768,10 @@ static TypeInfo m48t59_info = {
     .class_init    = m48t59_class_init,
 };
 
-static void m48t59_register_devices(void)
+static void m48t59_register_types(void)
 {
     type_register_static(&m48t59_info);
     type_register_static(&m48t59_isa_info);
 }
 
-device_init(m48t59_register_devices)
+type_init(m48t59_register_types)
index 3d648e934baf7b841abab837d77b5b8dfc127691..eb15b890b19a4de527beeca341ac2b0a01ab6e0e 100644 (file)
@@ -97,12 +97,12 @@ static TypeInfo macio_info = {
     .class_init    = macio_class_init,
 };
 
-static void macio_register(void)
+static void macio_register_types(void)
 {
     type_register_static(&macio_info);
 }
 
-device_init(macio_register);
+type_init(macio_register_types)
 
 void macio_init (PCIBus *bus, int device_id, int is_oldworld,
                  MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
index b628f1718d51ff9e844c845d8d47575df7078e12..f6f1937442bf8348ff1c7bcac483f1529550c5b5 100644 (file)
@@ -295,9 +295,9 @@ static TypeInfo mv88w8618_audio_info = {
     .class_init    = mv88w8618_audio_class_init,
 };
 
-static void mv88w8618_register_devices(void)
+static void mv88w8618_register_types(void)
 {
     type_register_static(&mv88w8618_audio_info);
 }
 
-device_init(mv88w8618_register_devices)
+type_init(mv88w8618_register_types)
index 9d61aa98db71e7a386795dcd84baacb66396af5e..706d89f4fd3151951a0c5bcaf756b6dcf6895358 100644 (file)
@@ -183,10 +183,10 @@ static TypeInfo max1111_info = {
     .class_init    = max1111_class_init,
 };
 
-static void max111x_register_devices(void)
+static void max111x_register_types(void)
 {
     type_register_static(&max1110_info);
     type_register_static(&max1111_info);
 }
 
-device_init(max111x_register_devices)
+type_init(max111x_register_types)
index 3a6bb961ef484677f9e05834adcf88dde5e3faf8..1ed18ba8764b88e5d4fedb5becbb39bb62c73e2f 100644 (file)
@@ -205,9 +205,9 @@ static TypeInfo max7310_info = {
     .class_init    = max7310_class_init,
 };
 
-static void max7310_register_devices(void)
+static void max7310_register_types(void)
 {
     type_register_static(&max7310_info);
 }
 
-device_init(max7310_register_devices)
+type_init(max7310_register_types)
index 4a43225707a268a03545724e3d04cb0989d98566..6c1ad38f725e0af722b0923504c034986788ab6d 100644 (file)
@@ -733,8 +733,9 @@ static TypeInfo mc146818rtc_info = {
     .class_init    = rtc_class_initfn,
 };
 
-static void mc146818rtc_register(void)
+static void mc146818rtc_register_types(void)
 {
     type_register_static(&mc146818rtc_info);
 }
-device_init(mc146818rtc_register)
+
+type_init(mc146818rtc_register_types)
index 0881643a4c9e12c8b683c74ea25dbb753edfd7fe..4414f397340a05889aaad8279e25868571f8f590 100644 (file)
@@ -336,9 +336,9 @@ static TypeInfo milkymist_ac97_info = {
     .class_init    = milkymist_ac97_class_init,
 };
 
-static void milkymist_ac97_register(void)
+static void milkymist_ac97_register_types(void)
 {
     type_register_static(&milkymist_ac97_info);
 }
 
-device_init(milkymist_ac97_register)
+type_init(milkymist_ac97_register_types)
index b5122afd57bfafe7082b871f55b0cc6b66d9a70e..2da0293683a2eb1fa993fb24fbe96d1a67904e10 100644 (file)
@@ -162,9 +162,9 @@ static TypeInfo milkymist_hpdmc_info = {
     .class_init    = milkymist_hpdmc_class_init,
 };
 
-static void milkymist_hpdmc_register(void)
+static void milkymist_hpdmc_register_types(void)
 {
     type_register_static(&milkymist_hpdmc_info);
 }
 
-device_init(milkymist_hpdmc_register)
+type_init(milkymist_hpdmc_register_types)
index 3c1c68a2e7868f044ac564435574240728e29b01..3515c3cd9a4423a14adcbeeb209d293dbf6cc5b4 100644 (file)
@@ -295,9 +295,9 @@ static TypeInfo milkymist_memcard_info = {
     .class_init    = milkymist_memcard_class_init,
 };
 
-static void milkymist_memcard_register(void)
+static void milkymist_memcard_register_types(void)
 {
     type_register_static(&milkymist_memcard_info);
 }
 
-device_init(milkymist_memcard_register)
+type_init(milkymist_memcard_register_types)
index b9b553fc955c29fced3a39b1a9e867a4e949e1fb..70bf336adde8f9fd7d70fabc17f3cb775b1f007b 100644 (file)
@@ -542,9 +542,9 @@ static TypeInfo milkymist_minimac2_info = {
     .class_init    = milkymist_minimac2_class_init,
 };
 
-static void milkymist_minimac2_register(void)
+static void milkymist_minimac2_register_types(void)
 {
     type_register_static(&milkymist_minimac2_info);
 }
 
-device_init(milkymist_minimac2_register)
+type_init(milkymist_minimac2_register_types)
index 1b73a4686b04d0a3c58297481697ec05ce3a6562..0f9ff4a13d4aac827cc4c450e164e0d07a663d1d 100644 (file)
@@ -536,9 +536,9 @@ static TypeInfo milkymist_pfpu_info = {
     .class_init    = milkymist_pfpu_class_init,
 };
 
-static void milkymist_pfpu_register(void)
+static void milkymist_pfpu_register_types(void)
 {
     type_register_static(&milkymist_pfpu_info);
 }
 
-device_init(milkymist_pfpu_register)
+type_init(milkymist_pfpu_register_types)
index 5d496cbdb04da2b673e40c2646a9e06eab279653..ecc2be92251f8d0306da7b1781f08f3563ec0c2b 100644 (file)
@@ -323,9 +323,9 @@ static TypeInfo milkymist_softusb_info = {
     .class_init    = milkymist_softusb_class_init,
 };
 
-static void milkymist_softusb_register(void)
+static void milkymist_softusb_register_types(void)
 {
     type_register_static(&milkymist_softusb_info);
 }
 
-device_init(milkymist_softusb_register)
+type_init(milkymist_softusb_register_types)
index 18171f6165ceabbce575bc100f8b989bd5922f5b..a88548e0aa543b50e27fc13ceabf0bf238e88007 100644 (file)
@@ -322,9 +322,9 @@ static TypeInfo milkymist_sysctl_info = {
     .class_init    = milkymist_sysctl_class_init,
 };
 
-static void milkymist_sysctl_register(void)
+static void milkymist_sysctl_register_types(void)
 {
     type_register_static(&milkymist_sysctl_info);
 }
 
-device_init(milkymist_sysctl_register)
+type_init(milkymist_sysctl_register_types)
index 474eae0a4aa252ec98079648746ff9a99b59e506..210ceede2a969cfd6830dad83239f616150e2178 100644 (file)
@@ -482,9 +482,9 @@ static TypeInfo milkymist_tmu2_info = {
     .class_init    = milkymist_tmu2_class_init,
 };
 
-static void milkymist_tmu2_register(void)
+static void milkymist_tmu2_register_types(void)
 {
     type_register_static(&milkymist_tmu2_info);
 }
 
-device_init(milkymist_tmu2_register)
+type_init(milkymist_tmu2_register_types)
index f9a229cf685637b83be6c7fbead6d6798c45cf55..291fe3c57beb8625ccb960de5c99b536d1168555 100644 (file)
@@ -235,9 +235,9 @@ static TypeInfo milkymist_uart_info = {
     .class_init    = milkymist_uart_class_init,
 };
 
-static void milkymist_uart_register(void)
+static void milkymist_uart_register_types(void)
 {
     type_register_static(&milkymist_uart_info);
 }
 
-device_init(milkymist_uart_register)
+type_init(milkymist_uart_register_types)
index 92ad02f9e21edebdb123651408a33af55f3ea454..69afd72d8aa5536c78eb58f9ce33c090087f9532 100644 (file)
@@ -323,9 +323,9 @@ static TypeInfo milkymist_vgafb_info = {
     .class_init    = milkymist_vgafb_class_init,
 };
 
-static void milkymist_vgafb_register(void)
+static void milkymist_vgafb_register_types(void)
 {
     type_register_static(&milkymist_vgafb_info);
 }
 
-device_init(milkymist_vgafb_register)
+type_init(milkymist_vgafb_register_types)
index d232630e661889f8a9f96f8ab8a26ad88db94a01..ffecefdededdec80b2e9569114a38a9ae8427099 100644 (file)
@@ -1029,7 +1029,7 @@ static QEMUMachine mips_malta_machine = {
     .is_default = 1,
 };
 
-static void mips_malta_device_init(void)
+static void mips_malta_register_types(void)
 {
     type_register_static(&mips_malta_device);
 }
@@ -1039,5 +1039,5 @@ static void mips_malta_machine_init(void)
     qemu_register_machine(&mips_malta_machine);
 }
 
-device_init(mips_malta_device_init);
+type_init(mips_malta_register_types)
 machine_init(mips_malta_machine_init);
index a0e6c9fa1e4925d627ab6200fd09b82548aa250c..50d92f8f54bb02cd6e162531726a7710c0745c4f 100644 (file)
@@ -276,9 +276,9 @@ static TypeInfo mipsnet_info = {
     .class_init    = mipsnet_class_init,
 };
 
-static void mipsnet_register_devices(void)
+static void mipsnet_register_types(void)
 {
     type_register_static(&mipsnet_info);
 }
 
-device_init(mipsnet_register_devices)
+type_init(mipsnet_register_types)
index 28cd60d89c895717554f1af8901c1c6174b8dce3..aeb2de7ccc667ae7993d3908453c56287fa17ac9 100644 (file)
@@ -135,8 +135,9 @@ static TypeInfo mpc8544_guts_info = {
     .class_init    = mpc8544_guts_class_init,
 };
 
-static void mpc8544_guts_register(void)
+static void mpc8544_guts_register_types(void)
 {
     type_register_static(&mpc8544_guts_info);
 }
-device_init(mpc8544_guts_register);
+
+type_init(mpc8544_guts_register_types)
index 1729db01a4084f70778a0a4eabc7f1b3d42a735a..024192d135aef64aa8c9f299f36dc72771f9d63b 100644 (file)
@@ -255,8 +255,9 @@ static TypeInfo mst_fpga_info = {
     .class_init    = mst_fpga_class_init,
 };
 
-static void mst_fpga_register(void)
+static void mst_fpga_register_types(void)
 {
     type_register_static(&mst_fpga_info);
 }
-device_init(mst_fpga_register);
+
+type_init(mst_fpga_register_types)
index ac909248d4460bcc882689c124891d3ec86b9f45..187a1aef5e6eeecefd9ed4bf4628b0f73283f4ab 100644 (file)
@@ -1681,7 +1681,7 @@ static TypeInfo mv88w8618_wlan_info = {
     .class_init    = mv88w8618_wlan_class_init,
 };
 
-static void musicpal_register_devices(void)
+static void musicpal_register_types(void)
 {
     type_register_static(&mv88w8618_pic_info);
     type_register_static(&mv88w8618_pit_info);
@@ -1693,4 +1693,4 @@ static void musicpal_register_devices(void)
     type_register_static(&musicpal_key_info);
 }
 
-device_init(musicpal_register_devices)
+type_init(musicpal_register_types)
index 5d947b1cedfd096913b21d0b6fa3cc4a96dc6e5f..e9501ae038c35aa0b4b84d1be45ee324f0b60e93 100644 (file)
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -442,7 +442,7 @@ static TypeInfo nand_info = {
     .class_init    = nand_class_init,
 };
 
-static void nand_create_device(void)
+static void nand_register_types(void)
 {
     type_register_static(&nand_info);
 }
@@ -635,7 +635,7 @@ DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
     return dev;
 }
 
-device_init(nand_create_device)
+type_init(nand_register_types)
 
 #else
 
index 13522821526acff216d688834f8491b79eaec476..a4a783ab89b3a813e18ab2d4b13f21c0defa3495 100644 (file)
@@ -104,9 +104,9 @@ static TypeInfo ne2000_isa_info = {
     .class_init    = isa_ne2000_class_initfn,
 };
 
-static void ne2000_isa_register_devices(void)
+static void ne2000_isa_register_types(void)
 {
     type_register_static(&ne2000_isa_info);
 }
 
-device_init(ne2000_isa_register_devices)
+type_init(ne2000_isa_register_types)
index 080811ec4de98658964a62c594a80f95e3bb0eac..bb84fd1f9365834fe22c0bbda19aa8323da7e1c3 100644 (file)
@@ -812,9 +812,9 @@ static TypeInfo ne2000_info = {
     .class_init    = ne2000_class_init,
 };
 
-static void ne2000_register_devices(void)
+static void ne2000_register_types(void)
 {
     type_register_static(&ne2000_info);
 }
 
-device_init(ne2000_register_devices)
+type_init(ne2000_register_types)
index 9a9a8e183f60feaaca5f8494344c86c6b6e05de1..201ff77c36256cfd03c02579ea60876b47707e52 100644 (file)
@@ -783,10 +783,10 @@ static TypeInfo omap2_gpio_info = {
     .class_init    = omap2_gpio_class_init,
 };
 
-static void omap_gpio_register_device(void)
+static void omap_gpio_register_types(void)
 {
     type_register_static(&omap_gpio_info);
     type_register_static(&omap2_gpio_info);
 }
 
-device_init(omap_gpio_register_device)
+type_init(omap_gpio_register_types)
index 5aa98a8fdb6cfbb9feb38ee0b55235fac5ebd8af..5076e07ed50c44a7e6952d139a787b89688a566f 100644 (file)
@@ -640,10 +640,10 @@ static TypeInfo omap2_intc_info = {
     .class_init    = omap2_intc_class_init,
 };
 
-static void omap_intc_register_device(void)
+static void omap_intc_register_types(void)
 {
     type_register_static(&omap_intc_info);
     type_register_static(&omap2_intc_info);
 }
 
-device_init(omap_intc_register_device)
+type_init(omap_intc_register_types)
index 8744b04db3c34cfc68cfb6bddd03ec2ce427edbe..db6af682c42243e74f755ee5f70e8b4c8d0beb99 100644 (file)
@@ -828,7 +828,7 @@ static TypeInfo onenand_info = {
     .class_init    = onenand_class_init,
 };
 
-static void onenand_register_device(void)
+static void onenand_register_types(void)
 {
     type_register_static(&onenand_info);
 }
@@ -838,4 +838,4 @@ void *onenand_raw_otp(DeviceState *onenand_device)
     return FROM_SYSBUS(OneNANDState, sysbus_from_qdev(onenand_device))->otp;
 }
 
-device_init(onenand_register_device)
+type_init(onenand_register_types)
index 09f2757df3fcc7541c4c4623148f055b00b6e304..9b036cb103995e91c42920247aaf06d35cbdc000 100644 (file)
@@ -750,9 +750,9 @@ static TypeInfo open_eth_info = {
     .class_init    = open_eth_class_init,
 };
 
-static void open_eth_register_devices(void)
+static void open_eth_register_types(void)
 {
     type_register_static(&open_eth_info);
 }
 
-device_init(open_eth_register_devices)
+type_init(open_eth_register_types)
index 484d7279279783b0afa6f6e6172ef437814c54cf..219f38436ffa43bee30636a7a70338f057292171 100644 (file)
@@ -606,9 +606,9 @@ static TypeInfo parallel_isa_info = {
     .class_init    = parallel_isa_class_initfn,
 };
 
-static void parallel_register_devices(void)
+static void parallel_register_types(void)
 {
     type_register_static(&parallel_isa_info);
 }
 
-device_init(parallel_register_devices)
+type_init(parallel_register_types)
diff --git a/hw/pc.c b/hw/pc.c
index 3b35735ade66cfd68d7edc744d2c738cf3e1fc1e..ab94d724048cf8481d0e7cdc17c9bb52857c7801 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -514,11 +514,12 @@ static TypeInfo port92_info = {
     .class_init    = port92_class_initfn,
 };
 
-static void port92_register(void)
+static void port92_register_types(void)
 {
     type_register_static(&port92_info);
 }
-device_init(port92_register)
+
+type_init(port92_register_types)
 
 static void handle_a20_line_change(void *opaque, int irq, int level)
 {
index 5f4f80ed10080ea4a95b8eba36d708d66a9141fa..678a8c11173496b923a37ab8a9885b3101abee35 100644 (file)
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2003,9 +2003,9 @@ static TypeInfo pci_device_type_info = {
     .class_init = pci_device_class_init,
 };
 
-static void pci_register_devices(void)
+static void pci_register_types(void)
 {
     type_register_static(&pci_device_type_info);
 }
 
-device_init(pci_register_devices);
+type_init(pci_register_types)
index b4c53bed6c3fbb0cc544b5b85455efaea3d296f9..69857bade97481bf705d18cb172613fef1b825af 100644 (file)
@@ -513,8 +513,9 @@ static TypeInfo i8042_info = {
     .class_init    = i8042_class_initfn,
 };
 
-static void i8042_register(void)
+static void i8042_register_types(void)
 {
     type_register_static(&i8042_info);
 }
-device_init(i8042_register)
+
+type_init(i8042_register_types)
index 439f32caaeaa5273b908698404b63d55cd61b75e..368260959f5858303ce9a4e7b99df7a3ba411503 100644 (file)
@@ -376,9 +376,9 @@ static TypeInfo pcnet_info = {
     .class_init    = pcnet_class_init,
 };
 
-static void pci_pcnet_register_devices(void)
+static void pci_pcnet_register_types(void)
 {
     type_register_static(&pcnet_info);
 }
 
-device_init(pci_pcnet_register_devices)
+type_init(pci_pcnet_register_types)
index a9e88b9b3c837b80a7852db79272411ba99c2860..2ca0fd4560cfed08bd8f76d5c9b996832966ee12 100644 (file)
@@ -102,6 +102,7 @@ static void pflash_setup_mappings(pflash_t *pfl)
 static void pflash_register_memory(pflash_t *pfl, int rom_mode)
 {
     memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
+    pfl->rom_mode = rom_mode;
 }
 
 static void pflash_timer (void *opaque)
index 4e7a2370cd75e47fd0ba1089916eb7801abfbf89..ce4eb0d1ae3f2c2676535a86636402a9fb4d6b81 100644 (file)
@@ -124,8 +124,9 @@ static TypeInfo piix4_info = {
     .class_init    = piix4_class_init,
 };
 
-static void piix4_register(void)
+static void piix4_register_types(void)
 {
     type_register_static(&piix4_info);
 }
-device_init(piix4_register);
+
+type_init(piix4_register_types)
index 190642733f3fe9b164662538800b26d224839dbe..e0268fe053f8d0332aa0ecd90da07628ea572990 100644 (file)
@@ -589,11 +589,12 @@ static TypeInfo i440fx_pcihost_info = {
     .class_init    = i440fx_pcihost_class_init,
 };
 
-static void i440fx_register(void)
+static void i440fx_register_types(void)
 {
     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);
+
+type_init(i440fx_register_types)
index 752cbf9725bc37798f9f45fce1196070ac4ea566..8a5a8f554a58881511fc55159639567934e049fd 100644 (file)
@@ -316,10 +316,10 @@ static TypeInfo pl011_luminary_info = {
     .class_init    = pl011_luminary_class_init,
 };
 
-static void pl011_register_devices(void)
+static void pl011_register_types(void)
 {
     type_register_static(&pl011_arm_info);
     type_register_static(&pl011_luminary_info);
 }
 
-device_init(pl011_register_devices)
+type_init(pl011_register_types)
index 30bd3442bbcd5c9a22e3181be25efd6123c63cec..03bf63c4d2e6c2f156e2306589afa1bd6ad1ed2b 100644 (file)
@@ -299,9 +299,9 @@ static TypeInfo pl022_info = {
     .class_init    = pl022_class_init,
 };
 
-static void pl022_register_devices(void)
+static void pl022_register_types(void)
 {
     type_register_static(&pl022_info);
 }
 
-device_init(pl022_register_devices)
+type_init(pl022_register_types)
index 8416a609ef802cf0e71ef2e64706c24c07c17b99..05b5b11e1ad49df0be2bceb6bf5b622458b63f57 100644 (file)
@@ -230,9 +230,9 @@ static TypeInfo pl031_info = {
     .class_init    = pl031_class_init,
 };
 
-static void pl031_register_devices(void)
+static void pl031_register_types(void)
 {
     type_register_static(&pl031_info);
 }
 
-device_init(pl031_register_devices)
+type_init(pl031_register_types)
index 6d99c9cbbcd6d8ab73d50f775b04a7b239ca105c..b6723be0a95374b13bab01a1ef3700d2a26f8135 100644 (file)
@@ -638,9 +638,9 @@ static TypeInfo pl041_device_info = {
     .class_init    = pl041_device_class_init,
 };
 
-static void pl041_register_device(void)
+static void pl041_register_types(void)
 {
     type_register_static(&pl041_device_info);
 }
 
-device_init(pl041_register_device)
+type_init(pl041_register_types)
index b0094ac9b31ddaab2c913fa0f66613e1bad80fa5..b13924a160a387842af91ae8acba8dcabeb94f33 100644 (file)
@@ -189,10 +189,10 @@ static TypeInfo pl050_mouse_info = {
     .class_init    = pl050_mouse_class_init,
 };
 
-static void pl050_register_devices(void)
+static void pl050_register_types(void)
 {
     type_register_static(&pl050_kbd_info);
     type_register_static(&pl050_mouse_info);
 }
 
-device_init(pl050_register_devices)
+type_init(pl050_register_types)
index 3136c994231693c5604d4edadfd94563522fc11a..2aac7e8e9ee4529d072f2847115f42265afe6bc0 100644 (file)
@@ -325,10 +325,10 @@ static TypeInfo pl061_luminary_info = {
     .class_init    = pl061_luminary_class_init,
 };
 
-static void pl061_register_devices(void)
+static void pl061_register_types(void)
 {
     type_register_static(&pl061_info);
     type_register_static(&pl061_luminary_info);
 }
 
-device_init(pl061_register_devices)
+type_init(pl061_register_types)
index 4405d1823bee1689a0f588968f166b4a938b9400..b3cf651ab7ce512c5409d45e4cadbfd46f8e26d7 100644 (file)
@@ -409,10 +409,10 @@ static TypeInfo pl081_info = {
 
 /* 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)
+static void pl080_register_types(void)
 {
     type_register_static(&pl080_info);
     type_register_static(&pl081_info);
 }
 
-device_init(pl080_register_devices)
+type_init(pl080_register_types)
index 86e95a3ffdb6d57cf2d95a1912bd7b21ed6442c2..f94608cb62b222096f1f08edef27aa692276141d 100644 (file)
@@ -520,11 +520,11 @@ static TypeInfo pl111_info = {
     .class_init    = pl111_class_init,
 };
 
-static void pl110_register_devices(void)
+static void pl110_register_types(void)
 {
     type_register_static(&pl110_info);
     type_register_static(&pl110_versatile_info);
     type_register_static(&pl111_info);
 }
 
-device_init(pl110_register_devices)
+type_init(pl110_register_types)
index ae636e220ea9819cbcea6881406e394612433c54..7d91fbba1d0d22e394fd79e33a11c7870b278f80 100644 (file)
@@ -505,9 +505,9 @@ static TypeInfo pl181_info = {
     .class_init    = pl181_class_init,
 };
 
-static void pl181_register_devices(void)
+static void pl181_register_types(void)
 {
     type_register_static(&pl181_info);
 }
 
-device_init(pl181_register_devices)
+type_init(pl181_register_types)
index 956ab21c6acf0b7e67aea7bc04af3c72719d279d..cb50afb9f4c49dd16694dd3e35dd72cb7838c14e 100644 (file)
@@ -273,9 +273,9 @@ static TypeInfo pl190_info = {
     .class_init    = pl190_class_init,
 };
 
-static void pl190_register_devices(void)
+static void pl190_register_types(void)
 {
     type_register_static(&pl190_info);
 }
 
-device_init(pl190_register_devices)
+type_init(pl190_register_types)
index d11f120d321b1ecf902c7edef94632056e9f273b..203c3cdc47c433e866336a1c9afc1d7e5fc6a7b5 100644 (file)
@@ -400,9 +400,10 @@ static TypeInfo ppc4xx_pcihost_info = {
     .class_init    = ppc4xx_pcihost_class_init,
 };
 
-static void ppc4xx_pci_register(void)
+static void ppc4xx_pci_register_types(void)
 {
     type_register_static(&ppc4xx_pcihost_info);
     type_register_static(&ppc4xx_host_bridge_info);
 }
-device_init(ppc4xx_pci_register);
+
+type_init(ppc4xx_pci_register_types)
index d5bce71429584a0fb66b834b5f61517bfcea5124..0f60b2413452b684a971e0f1155c7879aafc27f1 100644 (file)
@@ -373,9 +373,10 @@ static TypeInfo e500_pcihost_info = {
     .class_init    = e500_pcihost_class_init,
 };
 
-static void e500_pci_register(void)
+static void e500_pci_register_types(void)
 {
     type_register_static(&e500_pcihost_info);
     type_register_static(&e500_host_bridge_info);
 }
-device_init(e500_pci_register);
+
+type_init(e500_pci_register_types)
index 9d648ec90a255502f852c4d9ef4cd45f00079294..6b8a189c0e0cb8f1c53aa61a1697b4392f8c1383 100644 (file)
@@ -217,8 +217,9 @@ static TypeInfo ppce500_spin_info = {
     .class_init    = ppce500_spin_class_init,
 };
 
-static void ppce500_spin_register(void)
+static void ppce500_spin_register_types(void)
 {
     type_register_static(&ppce500_spin_info);
 }
-device_init(ppce500_spin_register);
+
+type_init(ppce500_spin_register_types)
index 40b8bb0edd6ea49c128e9a7a039fe52517652b75..8b29da99485b3f8684c6d1a7f1cda9eb5570c075 100644 (file)
@@ -173,10 +173,10 @@ static TypeInfo raven_pcihost_info = {
     .class_init = raven_pcihost_class_init,
 };
 
-static void raven_register_devices(void)
+static void raven_register_types(void)
 {
     type_register_static(&raven_pcihost_info);
     type_register_static(&raven_info);
 }
 
-device_init(raven_register_devices)
+type_init(raven_register_types)
index 244c6145104926a3b4d847c116a016e49f31e729..1ab27012c1d014fd2042fcf5e37a659b311baa88 100644 (file)
@@ -2330,7 +2330,7 @@ static TypeInfo pxa2xx_ssp_info = {
     .class_init    = pxa2xx_ssp_class_init,
 };
 
-static void pxa2xx_register_devices(void)
+static void pxa2xx_register_types(void)
 {
     type_register_static(&pxa2xx_i2c_slave_info);
     type_register_static(&pxa2xx_ssp_info);
@@ -2338,4 +2338,4 @@ static void pxa2xx_register_devices(void)
     type_register_static(&pxa2xx_rtc_sysbus_info);
 }
 
-device_init(pxa2xx_register_devices)
+type_init(pxa2xx_register_types)
index 2d61565f1d9c8202ffc8dffce3d9a6acaaaa41ff..8ced0dd8ec09817c6f079a6edd66477e56ad66d8 100644 (file)
@@ -566,8 +566,9 @@ static TypeInfo pxa2xx_dma_info = {
     .class_init    = pxa2xx_dma_class_init,
 };
 
-static void pxa2xx_dma_register(void)
+static void pxa2xx_dma_register_types(void)
 {
     type_register_static(&pxa2xx_dma_info);
 }
-device_init(pxa2xx_dma_register);
+
+type_init(pxa2xx_dma_register_types)
index 67fd17c4ca92b3734ed166a9f1d56aa857d5e5e0..d5f57162edec9b29a9ebc45b0305b9a67d81a53b 100644 (file)
@@ -340,8 +340,9 @@ static TypeInfo pxa2xx_gpio_info = {
     .class_init    = pxa2xx_gpio_class_init,
 };
 
-static void pxa2xx_gpio_register(void)
+static void pxa2xx_gpio_register_types(void)
 {
     type_register_static(&pxa2xx_gpio_info);
 }
-device_init(pxa2xx_gpio_register);
+
+type_init(pxa2xx_gpio_register_types)
index ca85743aea95e3ac1830c99155deb98c9949b9ae..6b2bdb0df1f692c5a5f048a0d5f55d3acfd6dacf 100644 (file)
@@ -313,8 +313,9 @@ static TypeInfo pxa2xx_pic_info = {
     .class_init    = pxa2xx_pic_class_init,
 };
 
-static void pxa2xx_pic_register(void)
+static void pxa2xx_pic_register_types(void)
 {
     type_register_static(&pxa2xx_pic_info);
 }
-device_init(pxa2xx_pic_register);
+
+type_init(pxa2xx_pic_register_types)
index 90800751b10c293fedadd9c5bed5a9e47f69cecc..77b033b5412057f8d55be39850af113b10ef197c 100644 (file)
@@ -527,9 +527,10 @@ static TypeInfo pxa27x_timer_dev_info = {
     .class_init    = pxa27x_timer_dev_class_init,
 };
 
-static void pxa2xx_timer_register(void)
+static void pxa2xx_timer_register_types(void)
 {
     type_register_static(&pxa25x_timer_dev_info);
     type_register_static(&pxa27x_timer_dev_info);
-};
-device_init(pxa2xx_timer_register);
+}
+
+type_init(pxa2xx_timer_register_types)
index 5976dcdf47133a7558502f95f3051f1cd4e05704..0bb16c7eb3a09a157339eef8763edfc27e75e3de 100644 (file)
@@ -61,8 +61,6 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_taddr = {
     .name  = "taddr",
-    .type  = PROP_TYPE_TADDR,
-    .size  = sizeof(target_phys_addr_t),
     .parse = parse_taddr,
     .print = print_taddr,
     .get   = get_taddr,
@@ -71,5 +69,8 @@ PropertyInfo qdev_prop_taddr = {
 
 void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_TADDR);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert(!errp);
+
 }
index 135c2bf23705e421ad98dcd89515a7eb09a7169f..a310cc7b16be869738a0653ea004de139aa2ba5d 100644 (file)
@@ -457,6 +457,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     id = qemu_opts_id(opts);
     if (id) {
         qdev->id = id;
+    }
+    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;
+    }
+    if (qdev->id) {
         object_property_add_child(qdev_get_peripheral(), qdev->id,
                                   OBJECT(qdev), NULL);
     } else {
@@ -466,14 +476,6 @@ DeviceState *qdev_device_add(QemuOpts *opts)
                                   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;
 }
@@ -485,22 +487,26 @@ 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);
+    for (; props->name; props++) {
+        Error *err = NULL;
+        char *value;
+        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
+        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
+            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
+        } else {
+            value = object_property_get_str(OBJECT(dev), props->name, &err);
+        }
+        g_free(legacy_name);
+
+        if (err) {
+            error_free(err);
+            continue;
         }
-        props++;
+        qdev_printf("%s-prop: %s = %s\n", prefix, props->name,
+                    value && *value ? value : "<null>");
+        g_free(value);
     }
 }
 
index c4583a14d75bec32f00f6a05c7d71fa5854bd724..7b74dd5bebdcc21d483b49f785c041c3b6171b0e 100644 (file)
@@ -12,7 +12,7 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 
 static uint32_t qdev_get_prop_mask(Property *prop)
 {
-    assert(prop->info->type == PROP_TYPE_BIT);
+    assert(prop->info == &qdev_prop_bit);
     return 0x1 << prop->bitnr;
 }
 
@@ -26,17 +26,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
         *p &= ~mask;
 }
 
-static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
-{
-    if (props->info->type == PROP_TYPE_BIT) {
-        bool *defval = src;
-        bit_prop_set(dev, props, *defval);
-    } else {
-        char *dst = qdev_get_prop_ptr(dev, props);
-        memcpy(dst, src, props->info->size);
-    }
-}
-
 /* Bit */
 static int parse_bit(DeviceState *dev, Property *prop, const char *str)
 {
@@ -90,8 +79,6 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
 PropertyInfo qdev_prop_bit = {
     .name  = "boolean",
     .legacy_name  = "on/off",
-    .type  = PROP_TYPE_BIT,
-    .size  = sizeof(uint32_t),
     .parse = parse_bit,
     .print = print_bit,
     .get   = get_bit,
@@ -151,7 +138,7 @@ static void set_int8(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (value > prop->info->min && value <= prop->info->max) {
+    if (value >= prop->info->min && value <= prop->info->max) {
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
@@ -162,8 +149,6 @@ static void set_int8(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_uint8 = {
     .name  = "uint8",
-    .type  = PROP_TYPE_UINT8,
-    .size  = sizeof(uint8_t),
     .parse = parse_uint8,
     .print = print_uint8,
     .get   = get_int8,
@@ -196,8 +181,6 @@ static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
 PropertyInfo qdev_prop_hex8 = {
     .name  = "uint8",
     .legacy_name  = "hex8",
-    .type  = PROP_TYPE_UINT8,
-    .size  = sizeof(uint8_t),
     .parse = parse_hex8,
     .print = print_hex8,
     .get   = get_int8,
@@ -259,7 +242,7 @@ static void set_int16(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (value > prop->info->min && value <= prop->info->max) {
+    if (value >= prop->info->min && value <= prop->info->max) {
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
@@ -270,8 +253,6 @@ static void set_int16(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_uint16 = {
     .name  = "uint16",
-    .type  = PROP_TYPE_UINT16,
-    .size  = sizeof(uint16_t),
     .parse = parse_uint16,
     .print = print_uint16,
     .get   = get_int16,
@@ -333,7 +314,7 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (value > prop->info->min && value <= prop->info->max) {
+    if (value >= prop->info->min && value <= prop->info->max) {
         *ptr = value;
     } else {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
@@ -344,8 +325,6 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_uint32 = {
     .name  = "uint32",
-    .type  = PROP_TYPE_UINT32,
-    .size  = sizeof(uint32_t),
     .parse = parse_uint32,
     .print = print_uint32,
     .get   = get_int32,
@@ -375,8 +354,6 @@ static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
 
 PropertyInfo qdev_prop_int32 = {
     .name  = "int32",
-    .type  = PROP_TYPE_INT32,
-    .size  = sizeof(int32_t),
     .parse = parse_int32,
     .print = print_int32,
     .get   = get_int32,
@@ -409,8 +386,6 @@ static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
 PropertyInfo qdev_prop_hex32 = {
     .name  = "uint32",
     .legacy_name  = "hex32",
-    .type  = PROP_TYPE_UINT32,
-    .size  = sizeof(uint32_t),
     .parse = parse_hex32,
     .print = print_hex32,
     .get   = get_int32,
@@ -468,8 +443,6 @@ static void set_int64(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_uint64 = {
     .name  = "uint64",
-    .type  = PROP_TYPE_UINT64,
-    .size  = sizeof(uint64_t),
     .parse = parse_uint64,
     .print = print_uint64,
     .get   = get_int64,
@@ -500,8 +473,6 @@ static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
 PropertyInfo qdev_prop_hex64 = {
     .name  = "uint64",
     .legacy_name  = "hex64",
-    .type  = PROP_TYPE_UINT64,
-    .size  = sizeof(uint64_t),
     .parse = parse_hex64,
     .print = print_hex64,
     .get   = get_int64,
@@ -510,19 +481,10 @@ PropertyInfo qdev_prop_hex64 = {
 
 /* --- string --- */
 
-static int parse_string(DeviceState *dev, Property *prop, const char *str)
-{
-    char **ptr = qdev_get_prop_ptr(dev, prop);
-
-    if (*ptr)
-        g_free(*ptr);
-    *ptr = g_strdup(str);
-    return 0;
-}
-
-static void free_string(DeviceState *dev, Property *prop)
+static void release_string(Object *obj, const char *name, void *opaque)
 {
-    g_free(*(char **)qdev_get_prop_ptr(dev, prop));
+    Property *prop = opaque;
+    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
 }
 
 static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
@@ -579,20 +541,16 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_string = {
     .name  = "string",
-    .type  = PROP_TYPE_STRING,
-    .size  = sizeof(char*),
-    .parse = parse_string,
     .print = print_string,
-    .free  = free_string,
+    .release = release_string,
     .get   = get_string,
     .set   = set_string,
 };
 
 /* --- drive --- */
 
-static int parse_drive(DeviceState *dev, Property *prop, const char *str)
+static int parse_drive(DeviceState *dev, const char *str, void **ptr)
 {
-    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
     BlockDriverState *bs;
 
     bs = bdrv_find(str);
@@ -604,8 +562,10 @@ static int parse_drive(DeviceState *dev, Property *prop, const char *str)
     return 0;
 }
 
-static void free_drive(DeviceState *dev, Property *prop)
+static void release_drive(Object *obj, const char *name, void *opaque)
 {
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr) {
@@ -614,35 +574,30 @@ static void free_drive(DeviceState *dev, Property *prop)
     }
 }
 
-static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
+static const char *print_drive(void *ptr)
 {
-    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-    return snprintf(dest, len, "%s",
-                    *ptr ? bdrv_get_device_name(*ptr) : "<null>");
+    return bdrv_get_device_name(ptr);
 }
 
-static void get_generic(Object *obj, Visitor *v, void *opaque,
-                       const char *name, Error **errp)
+static void get_pointer(Object *obj, Visitor *v, Property *prop,
+                        const char *(*print)(void *ptr),
+                        const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
     void **ptr = qdev_get_prop_ptr(dev, prop);
-    char buffer[1024];
-    char *p = buffer;
+    char *p;
 
-    buffer[0] = 0;
-    if (*ptr) {
-        prop->info->print(dev, prop, buffer, sizeof(buffer));
-    }
+    p = (char *) (*ptr ? print(*ptr) : "");
     visit_type_str(v, &p, name, errp);
 }
 
-static void set_generic(Object *obj, Visitor *v, void *opaque,
+static void set_pointer(Object *obj, Visitor *v, Property *prop,
+                        int (*parse)(DeviceState *dev, const char *str, void **ptr),
                         const char *name, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
     Error *local_err = NULL;
+    void **ptr = qdev_get_prop_ptr(dev, prop);
     char *str;
     int ret;
 
@@ -658,44 +613,53 @@ static void set_generic(Object *obj, Visitor *v, void *opaque,
     }
     if (!*str) {
         g_free(str);
-        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+        *ptr = NULL;
         return;
     }
-    ret = prop->info->parse(dev, prop, str);
+    ret = parse(dev, str, ptr);
     error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
     g_free(str);
 }
 
+static void get_drive(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_drive, name, errp);
+}
+
+static void set_drive(Object *obj, Visitor *v, void *opaque,
+                      const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_drive, name, errp);
+}
+
 PropertyInfo qdev_prop_drive = {
     .name  = "drive",
-    .type  = PROP_TYPE_DRIVE,
-    .size  = sizeof(BlockDriverState *),
-    .parse = parse_drive,
-    .print = print_drive,
-    .get   = get_generic,
-    .set   = set_generic,
-    .free  = free_drive,
+    .get   = get_drive,
+    .set   = set_drive,
+    .release = release_drive,
 };
 
 /* --- character device --- */
 
-static int parse_chr(DeviceState *dev, Property *prop, const char *str)
+static int parse_chr(DeviceState *dev, const char *str, void **ptr)
 {
-    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-
-    *ptr = qemu_chr_find(str);
-    if (*ptr == NULL) {
+    CharDriverState *chr = qemu_chr_find(str);
+    if (chr == NULL) {
         return -ENOENT;
     }
-    if ((*ptr)->avail_connections < 1) {
+    if (chr->avail_connections < 1) {
         return -EEXIST;
     }
-    --(*ptr)->avail_connections;
+    *ptr = chr;
+    --chr->avail_connections;
     return 0;
 }
 
-static void free_chr(DeviceState *dev, Property *prop)
+static void release_chr(Object *obj, const char *name, void *opaque)
 {
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr) {
@@ -704,62 +668,71 @@ static void free_chr(DeviceState *dev, Property *prop)
 }
 
 
-static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
+static const char *print_chr(void *ptr)
 {
-    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    CharDriverState *chr = ptr;
 
-    if (*ptr && (*ptr)->label) {
-        return snprintf(dest, len, "%s", (*ptr)->label);
-    } else {
-        return snprintf(dest, len, "<null>");
-    }
+    return chr->label ? chr->label : "";
+}
+
+static void get_chr(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_chr, name, errp);
+}
+
+static void set_chr(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_chr, name, errp);
 }
 
 PropertyInfo qdev_prop_chr = {
     .name  = "chr",
-    .type  = PROP_TYPE_CHR,
-    .size  = sizeof(CharDriverState*),
-    .parse = parse_chr,
-    .print = print_chr,
-    .get   = get_generic,
-    .set   = set_generic,
-    .free  = free_chr,
+    .get   = get_chr,
+    .set   = set_chr,
+    .release = release_chr,
 };
 
 /* --- netdev device --- */
 
-static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
+static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
 {
-    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
+    VLANClientState *netdev = qemu_find_netdev(str);
 
-    *ptr = qemu_find_netdev(str);
-    if (*ptr == NULL)
+    if (netdev == NULL) {
         return -ENOENT;
-    if ((*ptr)->peer) {
+    }
+    if (netdev->peer) {
         return -EEXIST;
     }
+    *ptr = netdev;
     return 0;
 }
 
-static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
+static const char *print_netdev(void *ptr)
 {
-    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
+    VLANClientState *netdev = ptr;
 
-    if (*ptr && (*ptr)->name) {
-        return snprintf(dest, len, "%s", (*ptr)->name);
-    } else {
-        return snprintf(dest, len, "<null>");
-    }
+    return netdev->name ? netdev->name : "";
+}
+
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    get_pointer(obj, v, opaque, print_netdev, name, errp);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    set_pointer(obj, v, opaque, parse_netdev, name, errp);
 }
 
 PropertyInfo qdev_prop_netdev = {
     .name  = "netdev",
-    .type  = PROP_TYPE_NETDEV,
-    .size  = sizeof(VLANClientState*),
-    .parse = parse_netdev,
-    .print = print_netdev,
-    .get   = get_generic,
-    .set   = set_generic,
+    .get   = get_netdev,
+    .set   = set_netdev,
 };
 
 /* --- vlan --- */
@@ -835,8 +808,6 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
 
 PropertyInfo qdev_prop_vlan = {
     .name  = "vlan",
-    .type  = PROP_TYPE_VLAN,
-    .size  = sizeof(VLANClientState*),
     .parse = parse_vlan,
     .print = print_vlan,
     .get   = get_vlan,
@@ -848,8 +819,6 @@ PropertyInfo qdev_prop_vlan = {
 /* Not a proper property, just for dirty hacks.  TODO Remove it!  */
 PropertyInfo qdev_prop_ptr = {
     .name  = "ptr",
-    .type  = PROP_TYPE_PTR,
-    .size  = sizeof(void*),
 };
 
 /* --- mac address --- */
@@ -859,95 +828,114 @@ PropertyInfo qdev_prop_ptr = {
  *   01:02:03:04:05:06
  *   01-02-03-04-05-06
  */
-static int parse_mac(DeviceState *dev, Property *prop, const char *str)
+static void get_mac(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
+    char buffer[2 * 6 + 5 + 1];
+    char *p = buffer;
+
+    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
+             mac->a[0], mac->a[1], mac->a[2],
+             mac->a[3], mac->a[4], mac->a[5]);
+
+    visit_type_str(v, &p, name, errp);
+}
+
+static void set_mac(Object *obj, Visitor *v, void *opaque,
+                    const char *name, Error **errp)
 {
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
+    Error *local_err = NULL;
     int i, pos;
-    char *p;
+    char *str, *p;
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
 
     for (i = 0, pos = 0; i < 6; i++, pos += 3) {
         if (!qemu_isxdigit(str[pos]))
-            return -EINVAL;
+            goto inval;
         if (!qemu_isxdigit(str[pos+1]))
-            return -EINVAL;
+            goto inval;
         if (i == 5) {
             if (str[pos+2] != '\0')
-                return -EINVAL;
+                goto inval;
         } else {
             if (str[pos+2] != ':' && str[pos+2] != '-')
-                return -EINVAL;
+                goto inval;
         }
         mac->a[i] = strtol(str+pos, &p, 16);
     }
-    return 0;
-}
+    return;
 
-static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
-    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
-
-    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
-                    mac->a[0], mac->a[1], mac->a[2],
-                    mac->a[3], mac->a[4], mac->a[5]);
+inval:
+    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 }
 
 PropertyInfo qdev_prop_macaddr = {
     .name  = "macaddr",
-    .type  = PROP_TYPE_MACADDR,
-    .size  = sizeof(MACAddr),
-    .parse = parse_mac,
-    .print = print_mac,
-    .get   = get_generic,
-    .set   = set_generic,
+    .get   = get_mac,
+    .set   = set_mac,
 };
 
 
 /* --- 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 const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
+    [LOST_TICK_DISCARD] = "discard",
+    [LOST_TICK_DELAY] = "delay",
+    [LOST_TICK_MERGE] = "merge",
+    [LOST_TICK_SLEW] = "slew",
+    [LOST_TICK_MAX] = NULL,
 };
 
-static int parse_lost_tick_policy(DeviceState *dev, Property *prop,
-                                  const char *str)
+QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
+
+static void get_enum(Object *obj, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
 {
-    LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
-    int i;
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    int *ptr = qdev_get_prop_ptr(dev, prop);
 
-    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;
+    visit_type_enum(v, ptr, prop->info->enum_table,
+                    prop->info->name, prop->name, errp);
 }
 
-static int print_lost_tick_policy(DeviceState *dev, Property *prop, char *dest,
-                                  size_t len)
+static void set_enum(Object *obj, Visitor *v, void *opaque,
+                     const char *name, Error **errp)
 {
-    LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    int *ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (dev->state != DEV_STATE_CREATED) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
 
-    return snprintf(dest, len, "%s", lost_tick_policy_table[*ptr].name);
+    visit_type_enum(v, ptr, prop->info->enum_table,
+                    prop->info->name, prop->name, errp);
 }
 
 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,
+    .name  = "LostTickPolicy",
+    .enum_table  = lost_tick_policy_table,
+    .get   = get_enum,
+    .set   = set_enum,
 };
 
 /* --- pci address --- */
@@ -987,30 +975,18 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t
     }
 }
 
-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];
-    char *p = buffer;
-
-    buffer[0] = 0;
-    if (*ptr != -1) {
-        snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7);
-    }
-    visit_type_str(v, &p, name, errp);
-}
-
 PropertyInfo qdev_prop_pci_devfn = {
-    .name  = "pci-devfn",
-    .type  = PROP_TYPE_UINT32,
-    .size  = sizeof(uint32_t),
+    .name  = "int32",
+    .legacy_name  = "pci-devfn",
     .parse = parse_pci_devfn,
     .print = print_pci_devfn,
-    .get   = get_pci_devfn,
-    .set   = set_generic,
+    .get   = get_int32,
+    .set   = set_int32,
+    /* FIXME: this should be -1...255, but the address is stored
+     * into an uint32_t rather than int32_t.
+     */
+    .min   = 0,
+    .max   = 0xFFFFFFFFULL,
 };
 
 /* --- public helpers --- */
@@ -1073,24 +1049,18 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
 
 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
 {
-    Property *prop;
-    int ret;
+    char *legacy_name;
+    Error *err = NULL;
 
-    prop = qdev_prop_find(dev, name);
-    /*
-     * TODO Properties without a parse method are just for dirty
-     * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
-     * marked for removal.  The test !prop->info->parse should be
-     * removed along with it.
-     */
-    if (!prop || !prop->info->parse) {
-        qerror_report(QERR_PROPERTY_NOT_FOUND, object_get_typename(OBJECT(dev)), name);
-        return -1;
+    legacy_name = g_strdup_printf("legacy-%s", name);
+    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
+        object_property_set_str(OBJECT(dev), value, legacy_name, &err);
+    } else {
+        object_property_set_str(OBJECT(dev), value, name, &err);
     }
-    ret = prop->info->parse(dev, prop, value);
-    if (ret < 0) {
-        Error *err;
-        error_set_from_qdev_prop_error(&err, ret, dev, prop, value);
+    g_free(legacy_name);
+
+    if (err) {
         qerror_report_err(err);
         error_free(err);
         return -1;
@@ -1098,72 +1068,66 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
     return 0;
 }
 
-void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
-{
-    Property *prop;
-
-    prop = qdev_prop_find(dev, name);
-    if (!prop) {
-        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
-                __FUNCTION__, object_get_typename(OBJECT(dev)), name);
-        abort();
-    }
-    if (prop->info->type != type) {
-        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
-                __FUNCTION__, object_get_typename(OBJECT(dev)), name);
-        abort();
-    }
-    qdev_prop_cpy(dev, prop, src);
-}
-
 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
+    Error *errp = NULL;
+    object_property_set_bool(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
+    Error *errp = NULL;
+    object_property_set_str(OBJECT(dev), value, name, &errp);
+    assert_no_error(errp);
 }
 
 int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
 {
-    int res;
-
-    res = bdrv_attach_dev(value, dev);
-    if (res < 0) {
-        error_report("Can't attach drive %s to %s.%s: %s",
-                     bdrv_get_device_name(value),
-                     dev->id ? dev->id : object_get_typename(OBJECT(dev)),
-                     name, strerror(-res));
+    Error *errp = NULL;
+    const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
+    object_property_set_str(OBJECT(dev), bdrv_name,
+                            name, &errp);
+    if (errp) {
+        qerror_report_err(errp);
+        error_free(errp);
         return -1;
     }
-    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
     return 0;
 }
 
@@ -1175,44 +1139,81 @@ void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverS
 }
 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
+    Error *errp = NULL;
+    assert(!value || value->label);
+    object_property_set_str(OBJECT(dev),
+                            value ? value->label : "", name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
+    Error *errp = NULL;
+    assert(!value || value->name);
+    object_property_set_str(OBJECT(dev),
+                            value ? value->name : "", name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
+    Error *errp = NULL;
+    object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
 {
-    qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
+    Error *errp = NULL;
+    char str[2 * 6 + 5 + 1];
+    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
+             value[0], value[1], value[2], value[3], value[4], value[5]);
+
+    object_property_set_str(OBJECT(dev), str, name, &errp);
+    assert_no_error(errp);
 }
 
-void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
-                                  LostTickPolicy *value)
+void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
 {
-    qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
+    Property *prop;
+    Error *errp = NULL;
+
+    prop = qdev_prop_find(dev, name);
+    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
+                            name, &errp);
+    assert_no_error(errp);
 }
 
 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
 {
-    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
+    Property *prop;
+    void **ptr;
+
+    prop = qdev_prop_find(dev, name);
+    assert(prop && prop->info == &qdev_prop_ptr);
+    ptr = qdev_get_prop_ptr(dev, prop);
+    *ptr = value;
 }
 
 void qdev_prop_set_defaults(DeviceState *dev, Property *props)
 {
+    Object *obj = OBJECT(dev);
     if (!props)
         return;
-    while (props->name) {
-        if (props->defval) {
-            qdev_prop_cpy(dev, props, props->defval);
+    for (; props->name; props++) {
+        Error *errp = NULL;
+        if (props->qtype == QTYPE_NONE) {
+            continue;
         }
-        props++;
+        if (props->qtype == QTYPE_QBOOL) {
+            object_property_set_bool(obj, props->defval, props->name, &errp);
+        } else if (props->info->enum_table) {
+            object_property_set_str(obj, props->info->enum_table[props->defval],
+                                    props->name, &errp);
+        } else if (props->qtype == QTYPE_QINT) {
+            object_property_set_int(obj, props->defval, props->name, &errp);
+        }
+        assert_no_error(errp);
     }
 }
 
index e3b53b7f62e9b4952cd82f76492827bd67544ad8..f0eb3a7384a1026ebfae3b36a249b232c561e04e 100644 (file)
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -86,11 +86,11 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
     dev->parent_bus = bus;
     QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
 
-    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_prop_set_defaults(dev, dev->parent_bus->info->props);
 }
 
 /* Create a new device.  This only initializes the device state structure
@@ -550,21 +550,24 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
  * Do not use this is new code!  Properties added through this interface will
  * be given names and types in the "legacy" namespace.
  *
- * Legacy properties are always processed as strings.  The format of the string
- * depends on the property type.
+ * Legacy properties are string versions of other OOM properties.  The format
+ * of the string depends on the property type.
  */
 void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                               Error **errp)
 {
     gchar *name, *type;
 
+    if (!prop->info->print && !prop->info->parse) {
+        return;
+    }
     name = g_strdup_printf("legacy-%s", prop->name);
     type = g_strdup_printf("legacy<%s>",
                            prop->info->legacy_name ?: prop->info->name);
 
     object_property_add(OBJECT(dev), name, type,
-                        prop->info->print ? qdev_get_legacy_property : NULL,
-                        prop->info->parse ? qdev_set_legacy_property : NULL,
+                        prop->info->print ? qdev_get_legacy_property : prop->info->get,
+                        prop->info->parse ? qdev_set_legacy_property : prop->info->set,
                         NULL,
                         prop, errp);
 
@@ -581,9 +584,18 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop,
 void qdev_property_add_static(DeviceState *dev, Property *prop,
                               Error **errp)
 {
+    /*
+     * TODO qdev_prop_ptr does not have getters or setters.  It must
+     * go now that it can be replaced with links.  The test should be
+     * removed along with it: all static properties are read/write.
+     */
+    if (!prop->info->get && !prop->info->set) {
+        return;
+    }
+
     object_property_add(OBJECT(dev), prop->name, prop->info->name,
                         prop->info->get, prop->info->set,
-                        NULL,
+                        prop->info->release,
                         prop, errp);
 }
 
@@ -600,13 +612,13 @@ static void device_initfn(Object *obj)
     dev->instance_id_alias = -1;
     dev->state = DEV_STATE_CREATED;
 
-    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);
     }
 
     object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
+    qdev_prop_set_defaults(dev, qdev_get_props(dev));
 }
 
 /* Unlink device from bus and free the structure.  */
@@ -614,7 +626,6 @@ static void device_finalize(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
     BusState *bus;
-    Property *prop;
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
     if (dev->state == DEV_STATE_INITIALIZED) {
@@ -633,11 +644,6 @@ static void device_finalize(Object *obj)
         }
     }
     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);
-        }
-    }
 }
 
 void device_reset(DeviceState *dev)
@@ -659,9 +665,9 @@ static TypeInfo device_type_info = {
     .class_size = sizeof(DeviceClass),
 };
 
-static void init_qdev(void)
+static void qdev_register_types(void)
 {
     type_register_static(&device_type_info);
 }
 
-device_init(init_qdev);
+type_init(qdev_register_types)
index ab53273632914c25dbf3bf69b8c573ed9a0da276..9cc3f984b20855132595f9e0e9371a4d10db6502 100644 (file)
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -112,41 +112,22 @@ struct Property {
     const char   *name;
     PropertyInfo *info;
     int          offset;
-    int          bitnr;
-    void         *defval;
-};
-
-enum PropertyType {
-    PROP_TYPE_UNSPEC = 0,
-    PROP_TYPE_UINT8,
-    PROP_TYPE_UINT16,
-    PROP_TYPE_UINT32,
-    PROP_TYPE_INT32,
-    PROP_TYPE_UINT64,
-    PROP_TYPE_TADDR,
-    PROP_TYPE_MACADDR,
-    PROP_TYPE_LOSTTICKPOLICY,
-    PROP_TYPE_DRIVE,
-    PROP_TYPE_CHR,
-    PROP_TYPE_STRING,
-    PROP_TYPE_NETDEV,
-    PROP_TYPE_VLAN,
-    PROP_TYPE_PTR,
-    PROP_TYPE_BIT,
+    uint8_t      bitnr;
+    uint8_t      qtype;
+    int64_t      defval;
 };
 
 struct PropertyInfo {
     const char *name;
     const char *legacy_name;
-    size_t size;
-    enum PropertyType type;
+    const char **enum_table;
     int64_t min;
     int64_t max;
     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);
     ObjectPropertyAccessor *get;
     ObjectPropertyAccessor *set;
+    ObjectPropertyRelease *release;
 };
 
 typedef struct GlobalProperty {
@@ -254,7 +235,8 @@ extern PropertyInfo qdev_prop_pci_devfn;
         .info      = &(_prop),                                          \
         .offset    = offsetof(_state, _field)                           \
             + type_check(_type,typeof_field(_state, _field)),           \
-        .defval    = (_type[]) { _defval },                             \
+        .qtype     = QTYPE_QINT,                                        \
+        .defval    = (_type)_defval,                                    \
         }
 #define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) {  \
         .name      = (_name),                                    \
@@ -262,7 +244,8 @@ extern PropertyInfo qdev_prop_pci_devfn;
         .bitnr    = (_bit),                                      \
         .offset    = offsetof(_state, _field)                    \
             + type_check(uint32_t,typeof_field(_state, _field)), \
-        .defval    = (bool[]) { (_defval) },                     \
+        .qtype     = QTYPE_QBOOL,                                \
+        .defval    = (bool)_defval,                              \
         }
 
 #define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
@@ -309,7 +292,6 @@ extern PropertyInfo qdev_prop_pci_devfn;
 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop);
 int qdev_prop_exists(DeviceState *dev, const char *name);
 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
-void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type);
 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
@@ -323,8 +305,7 @@ 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);
+void qdev_prop_set_enum(DeviceState *dev, const char *name, int 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);
index bc03c1dc777f2c351310804f53d80d3701bc96cb..ac69125f27433073dee002eb3e6d67cad8b39ed8 100644 (file)
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1870,10 +1870,10 @@ static TypeInfo qxl_secondary_info = {
     .class_init    = qxl_secondary_class_init,
 };
 
-static void qxl_register(void)
+static void qxl_register_types(void)
 {
     type_register_static(&qxl_primary_info);
     type_register_static(&qxl_secondary_info);
 }
 
-device_init(qxl_register);
+type_init(qxl_register_types)
index 821e62756047f44dcea9f61e1299149a1304aea9..bcf982fac55803f313ae2ba42fb0641748371a93 100644 (file)
@@ -96,7 +96,7 @@ static TypeInfo realview_i2c_info = {
     .class_init    = realview_i2c_class_init,
 };
 
-static void realview_register_devices(void)
+static void realview_register_types(void)
 {
     type_register_static(&realview_i2c_info);
 }
@@ -217,8 +217,8 @@ static void realview_init(ram_addr_t ram_size,
     sys_id = is_pb ? 0x01780500 : 0xc1400400;
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_init_nofail(sysctl);
     qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
     if (is_mpcore) {
@@ -491,4 +491,4 @@ static void realview_machine_init(void)
 }
 
 machine_init(realview_machine_init);
-device_init(realview_register_devices)
+type_init(realview_register_types)
index 4121502c7be087ebbbeb56612936341078f5789e..071ef13c9e2dac2cf2d5ee1c37457306ccf213aa 100644 (file)
@@ -60,9 +60,9 @@ static TypeInfo realview_gic_info = {
     .class_init    = realview_gic_class_init,
 };
 
-static void realview_gic_register_devices(void)
+static void realview_gic_register_types(void)
 {
     type_register_static(&realview_gic_info);
 }
 
-device_init(realview_gic_register_devices)
+type_init(realview_gic_register_types)
index 1668390e1fecf3b6b2c9ff93d621c0b8636dc408..05b8e1e3d7dd5e04bf6b1fd53d9c7e776efac29e 100644 (file)
@@ -3523,9 +3523,9 @@ static TypeInfo rtl8139_info = {
     .class_init    = rtl8139_class_init,
 };
 
-static void rtl8139_register_devices(void)
+static void rtl8139_register_types(void)
 {
     type_register_static(&rtl8139_info);
 }
 
-device_init(rtl8139_register_devices)
+type_init(rtl8139_register_types)
index 49140f8a9e0390995ef3f1155e81a24839aa4bd2..9d480564d7e2020dddd3825d4fa20b04e077b961 100644 (file)
@@ -433,15 +433,6 @@ static TypeInfo virtio_s390_device_info = {
     .abstract = true,
 };
 
-static void s390_virtio_register(void)
-{
-    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);
-
 
 /***************** S390 Virtio Bus Bridge Device *******************/
 /* Only required to have the virtio bus as child in the system bus */
@@ -468,9 +459,13 @@ static TypeInfo s390_virtio_bridge_info = {
     .class_init    = s390_virtio_bridge_class_init,
 };
 
-static void s390_virtio_register_devices(void)
+static void s390_virtio_register_types(void)
 {
+    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);
     type_register_static(&s390_virtio_bridge_info);
 }
 
-device_init(s390_virtio_register_devices)
+type_init(s390_virtio_register_types)
index db8929b98ed51e821520ff3c3eb01a82e87e55ae..c81455d7f3266e3a681f8cfa9b7f8ef3ba6581f8 100644 (file)
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1417,8 +1417,9 @@ static TypeInfo sb16_info = {
     .class_init    = sb16_class_initfn,
 };
 
-static void sb16_register (void)
+static void sb16_register_types (void)
 {
     type_register_static (&sb16_info);
 }
-device_init (sb16_register)
+
+type_init (sb16_register_types)
index 847a4dde84843a2ddc797942bc98eaca798c7266..52982a9a3e1171d4978fc2a71c237e9c39cbb4d5 100644 (file)
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -148,9 +148,9 @@ static TypeInfo sbi_info = {
     .class_init    = sbi_class_init,
 };
 
-static void sbi_register_devices(void)
+static void sbi_register_types(void)
 {
     type_register_static(&sbi_info);
 }
 
-device_init(sbi_register_devices)
+type_init(sbi_register_types)
index 0ee50a8360d7defef579b90aee744961e37b0698..b3e97ceeecb9454720d390fe7e6cfb6634e94a13 100644 (file)
@@ -1431,9 +1431,9 @@ static TypeInfo scsi_device_type_info = {
     .class_init = scsi_device_class_init,
 };
 
-static void scsi_register_devices(void)
+static void scsi_register_types(void)
 {
     type_register_static(&scsi_device_type_info);
 }
 
-device_init(scsi_register_devices);
+type_init(scsi_register_types)
index 399e51e49428dc2b3ed70a175bb5ccf9a7d9a5b3..c12e3a6cb38bd784bb064494e46f594faf45620f 100644 (file)
@@ -1823,7 +1823,7 @@ static TypeInfo scsi_disk_info = {
     .class_init    = scsi_disk_class_initfn,
 };
 
-static void scsi_disk_register_devices(void)
+static void scsi_disk_register_types(void)
 {
     type_register_static(&scsi_hd_info);
     type_register_static(&scsi_cd_info);
@@ -1832,4 +1832,5 @@ static void scsi_disk_register_devices(void)
 #endif
     type_register_static(&scsi_disk_info);
 }
-device_init(scsi_disk_register_devices)
+
+type_init(scsi_disk_register_types)
index 4859212734a4819c3d0f154a8beb1cfbbb060674..86014aa89355d12c65e177ef24e764698aa263ce 100644 (file)
@@ -483,10 +483,11 @@ static TypeInfo scsi_generic_info = {
     .class_init    = scsi_generic_class_initfn,
 };
 
-static void scsi_generic_register_devices(void)
+static void scsi_generic_register_types(void)
 {
     type_register_static(&scsi_generic_info);
 }
-device_init(scsi_generic_register_devices)
+
+type_init(scsi_generic_register_types)
 
 #endif /* __linux__ */
index 82917e24d7e668518464a0c2b76001f1b9902972..144d1b3526997e9843ebacb41863908bbc34d722 100644 (file)
@@ -903,9 +903,9 @@ static TypeInfo serial_isa_info = {
     .class_init    = serial_isa_class_initfn,
 };
 
-static void serial_register_devices(void)
+static void serial_register_types(void)
 {
     type_register_static(&serial_isa_info);
 }
 
-device_init(serial_register_devices)
+type_init(serial_register_types)
index b08e3c5aea95a8440ea383bd5904649490d011b8..a666349f82128760525ebeda54ffb4fdfa705187 100644 (file)
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -55,9 +55,9 @@ static TypeInfo sga_info = {
     .class_init    = sga_class_initfn,
 };
 
-static void sga_register(void)
+static void sga_register_types(void)
 {
     type_register_static(&sga_info);
 }
 
-device_init(sga_register);
+type_init(sga_register_types)
index 4234d935e7482b4a5f1d299f691c2e178bb4e5f5..0cfac46f7faba0f881b54b7ae3eea92e37187738 100644 (file)
@@ -177,10 +177,10 @@ static TypeInfo sh_pci_device_info = {
     .class_init    = sh_pci_device_class_init,
 };
 
-static void sh_pci_register_devices(void)
+static void sh_pci_register_types(void)
 {
     type_register_static(&sh_pci_device_info);
     type_register_static(&sh_pci_host_info);
 }
 
-device_init(sh_pci_register_devices)
+type_init(sh_pci_register_types)
index e3701c75d22ab87dc487cc0eb23d70397cf64260..7fdc3be08696c855d42fac10afd8bc0e02e0f06c 100644 (file)
@@ -463,9 +463,9 @@ static TypeInfo slavio_intctl_info = {
     .class_init    = slavio_intctl_class_init,
 };
 
-static void slavio_intctl_register_devices(void)
+static void slavio_intctl_register_types(void)
 {
     type_register_static(&slavio_intctl_info);
 }
 
-device_init(slavio_intctl_register_devices)
+type_init(slavio_intctl_register_types)
index 5a025186af8712ab200ab2342189aa4f1c4e3757..944835e8800af3adc8eed68d4033a97fb3d037c3 100644 (file)
@@ -499,10 +499,10 @@ static TypeInfo apc_info = {
     .class_init    = apc_class_init,
 };
 
-static void slavio_misc_register_devices(void)
+static void slavio_misc_register_types(void)
 {
     type_register_static(&slavio_misc_info);
     type_register_static(&apc_info);
 }
 
-device_init(slavio_misc_register_devices)
+type_init(slavio_misc_register_types)
index 3878f6fa5e642c9af1b190956097846a2b30a95a..97edebb3bafa68892bcad23e54ee8fc2210e5780 100644 (file)
@@ -427,9 +427,9 @@ static TypeInfo slavio_timer_info = {
     .class_init    = slavio_timer_class_init,
 };
 
-static void slavio_timer_register_devices(void)
+static void slavio_timer_register_types(void)
 {
     type_register_static(&slavio_timer_info);
 }
 
-device_init(slavio_timer_register_devices)
+type_init(slavio_timer_register_types)
index 94c0abf4cbd832d81521936876c856aadc412f13..786e07629c9c3e5eb12e50fdd84da812f731545d 100644 (file)
@@ -1327,8 +1327,8 @@ static void sm501_draw_crt(SM501State * s)
         ram_addr_t page1 = offset + width * src_bpp - 1;
 
        /* check dirty flags for each line */
-        update = memory_region_get_dirty(&s->local_mem_region, page0, page1,
-                                         DIRTY_MEMORY_VGA);
+        update = memory_region_get_dirty(&s->local_mem_region, page0,
+                                         page1 - page0, DIRTY_MEMORY_VGA);
 
        /* draw line and change status */
        if (update) {
index 77626f36456e92a856c76d2d290ce47342090e3a..e3cf6a2cc8e31de29699e07e2367bc13388782cb 100644 (file)
@@ -327,9 +327,9 @@ static TypeInfo smbus_device_type_info = {
     .class_init = smbus_device_class_init,
 };
 
-static void smbus_device_register_devices(void)
+static void smbus_device_register_types(void)
 {
     type_register_static(&smbus_device_type_info);
 }
 
-device_init(smbus_device_register_devices);
+type_init(smbus_device_register_types)
index 9d96cbe41a7b5b4fa2d45738896dcaad88be67b7..11adab01b86caf5af160e9247b257d0d3b00dd4c 100644 (file)
@@ -130,12 +130,12 @@ static TypeInfo smbus_eeprom_info = {
     .class_init    = smbus_eeprom_class_initfn,
 };
 
-static void smbus_eeprom_register_devices(void)
+static void smbus_eeprom_register_types(void)
 {
     type_register_static(&smbus_eeprom_info);
 }
 
-device_init(smbus_eeprom_register_devices)
+type_init(smbus_eeprom_register_types)
 
 void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
                        const uint8_t *eeprom_spd, int eeprom_spd_size)
index 1bf2901d1aa65b17751f467552d7c06c818bcc79..1a5213fa56cc621990e2d8f3c81b09534eba22e1 100644 (file)
@@ -781,7 +781,7 @@ static TypeInfo smc91c111_info = {
     .class_init    = smc91c111_class_init,
 };
 
-static void smc91c111_register_devices(void)
+static void smc91c111_register_types(void)
 {
     type_register_static(&smc91c111_info);
 }
@@ -802,4 +802,4 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     sysbus_connect_irq(s, 0, irq);
 }
 
-device_init(smc91c111_register_devices)
+type_init(smc91c111_register_types)
index 84281be9e2d6d0b40e0ad41686a2b7a79cba57d4..6ac73840133e2e854556ea25749516b783479418 100644 (file)
@@ -672,7 +672,7 @@ target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
     return H_FUNCTION;
 }
 
-static void hypercall_init(void)
+static void hypercall_register_types(void)
 {
     /* hcall-pft */
     spapr_register_hypercall(H_ENTER, h_enter);
@@ -704,4 +704,5 @@ static void hypercall_init(void)
     /* qemu/KVM-PPC specific hcalls */
     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 }
-device_init(hypercall_init);
+
+type_init(hypercall_register_types)
index 79b394132bf6e5cf8ae5344222af616975d192ef..77d40479c8e731c009100dca7320810868787cc3 100644 (file)
@@ -501,7 +501,7 @@ static TypeInfo spapr_vlan_info = {
     .class_init    = spapr_vlan_class_init,
 };
 
-static void spapr_vlan_register(void)
+static void spapr_vlan_register_types(void)
 {
     spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
     spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
@@ -511,4 +511,5 @@ static void spapr_vlan_register(void)
     spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
     type_register_static(&spapr_vlan_info);
 }
-device_init(spapr_vlan_register);
+
+type_init(spapr_vlan_register_types)
index ed2e4b33e7db9aae004a47bc788e2ac2a97e30d3..cfdd9ddd4177933cf3a2da63950e2d2ef5e947d6 100644 (file)
@@ -242,13 +242,13 @@ static TypeInfo spapr_phb_info = {
     .class_init    = spapr_phb_class_init,
 };
 
-static void spapr_register_devices(void)
+static void spapr_register_types(void)
 {
     type_register_static(&spapr_phb_info);
     type_register_static(&spapr_main_pci_host_info);
 }
 
-device_init(spapr_register_devices)
+type_init(spapr_register_types)
 
 static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
                               unsigned size)
index d1ac74cfbdad39e763c2adfa6c89a64435614066..c0723b3039265efdb9c7510505e49f6cbeb8db27 100644 (file)
@@ -288,7 +288,7 @@ int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
     return 0;
 }
 
-static void register_core_rtas(void)
+static void core_rtas_register_types(void)
 {
     spapr_rtas_register("display-character", rtas_display_character);
     spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
@@ -298,4 +298,5 @@ static void register_core_rtas(void)
                         rtas_query_cpu_stopped_state);
     spapr_rtas_register("start-cpu", rtas_start_cpu);
 }
-device_init(register_core_rtas);
+
+type_init(core_rtas_register_types)
index 64f00098148cd86492eb8c4632cc89b959b76d78..ea317efbe49d03666206c0f97b4a54514bf6d8d2 100644 (file)
@@ -778,13 +778,13 @@ static TypeInfo spapr_vio_type_info = {
     .class_init = vio_spapr_device_class_init,
 };
 
-static void spapr_vio_register_devices(void)
+static void spapr_vio_register_types(void)
 {
     type_register_static(&spapr_vio_bridge_info);
     type_register_static(&spapr_vio_type_info);
 }
 
-device_init(spapr_vio_register_devices)
+type_init(spapr_vio_register_types)
 
 #ifdef CONFIG_FDT
 static int compare_reg(const void *p1, const void *p2)
index 9cfce19a732fc23573012be0faccbc05a224a8e2..ffce261f98a0b86f0de4904588f8e03f8cc20eae 100644 (file)
@@ -973,8 +973,9 @@ static TypeInfo spapr_vscsi_info = {
     .class_init    = spapr_vscsi_class_init,
 };
 
-static void spapr_vscsi_register(void)
+static void spapr_vscsi_register_types(void)
 {
     type_register_static(&spapr_vscsi_info);
 }
-device_init(spapr_vscsi_register);
+
+type_init(spapr_vscsi_register_types)
index a954e7d29b56c2ce844b173519e1d8b798206024..3efe24211e04d752a5f8b551c564fcfdc8b30221 100644 (file)
@@ -212,10 +212,11 @@ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
     return sdev;
 }
 
-static void spapr_vty_register(void)
+static void spapr_vty_register_types(void)
 {
     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);
+
+type_init(spapr_vty_register_types)
index f07cc6fdf069f596b2df7add70fcffa1c97228bd..1dbf69e80821bf88f41f666125d56c9e353c3d23 100644 (file)
@@ -307,9 +307,9 @@ static TypeInfo sparc32_dma_info = {
     .class_init    = sparc32_dma_class_init,
 };
 
-static void sparc32_dma_register_devices(void)
+static void sparc32_dma_register_types(void)
 {
     type_register_static(&sparc32_dma_info);
 }
 
-device_init(sparc32_dma_register_devices)
+type_init(sparc32_dma_register_types)
index 4e6540d9763ba3e82147f61db47d0aff56c4876e..1d6d2b0e1ba0fbd2ca0a32295d70a4823dbb4ee7 100644 (file)
@@ -1138,7 +1138,7 @@ static TypeInfo spitz_lcdtg_info = {
     .class_init    = spitz_lcdtg_class_init,
 };
 
-static void spitz_register_devices(void)
+static void spitz_register_types(void)
 {
     type_register_static(&corgi_ssp_info);
     type_register_static(&spitz_lcdtg_info);
@@ -1146,4 +1146,4 @@ static void spitz_register_devices(void)
     type_register_static(&sl_nand_info);
 }
 
-device_init(spitz_register_devices)
+type_init(spitz_register_types)
index 685602a5847de1aa145402bcdaf1dc1dab7def6b..4e1ee6e12b5c8b30dfc2e79fd4789a533271b0e8 100644 (file)
@@ -313,9 +313,9 @@ static TypeInfo ssd0303_info = {
     .class_init    = ssd0303_class_init,
 };
 
-static void ssd0303_register_devices(void)
+static void ssd0303_register_types(void)
 {
     type_register_static(&ssd0303_info);
 }
 
-device_init(ssd0303_register_devices)
+type_init(ssd0303_register_types)
index 3c43738ae1e293710b4d307b963daee80a8b8214..b0b2e94a816f52e24526b1f2f33741eaf84724bd 100644 (file)
@@ -355,9 +355,9 @@ static TypeInfo ssd0323_info = {
     .class_init    = ssd0323_class_init,
 };
 
-static void ssd03232_register_devices(void)
+static void ssd03232_register_types(void)
 {
     type_register_static(&ssd0323_info);
 }
 
-device_init(ssd03232_register_devices)
+type_init(ssd03232_register_types)
index f2e6cecb7155bd037cd29fb101c470ca82a73079..b519bdb29ac075f7ab9ce09c2110e03a823e95f7 100644 (file)
@@ -259,9 +259,9 @@ static TypeInfo ssi_sd_info = {
     .class_init    = ssi_sd_class_init,
 };
 
-static void ssi_sd_register_devices(void)
+static void ssi_sd_register_types(void)
 {
     type_register_static(&ssi_sd_info);
 }
 
-device_init(ssi_sd_register_devices)
+type_init(ssi_sd_register_types)
index ead446c49a858f4759f47a93651210d3777bac84..8f2d9bc0341c4aee6de9364a36fabfee86aca90a 100644 (file)
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -80,9 +80,9 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
     return ssc->transfer(slave, val);
 }
 
-static void register_ssi_slave(void)
+static void ssi_slave_register_types(void)
 {
     type_register_static(&ssi_slave_info);
 }
 
-device_init(register_ssi_slave);
+type_init(ssi_slave_register_types)
index 31a65cfb770a73a07297e7bfa59ca2ed915b2e4b..562fbbf4943dce2092ff4831b98bfaf5063ae8e1 100644 (file)
@@ -1451,7 +1451,7 @@ static TypeInfo stellaris_adc_info = {
     .class_init    = stellaris_adc_class_init,
 };
 
-static void stellaris_register_devices(void)
+static void stellaris_register_types(void)
 {
     type_register_static(&stellaris_i2c_info);
     type_register_static(&stellaris_gptm_info);
@@ -1459,4 +1459,4 @@ static void stellaris_register_devices(void)
     type_register_static(&stellaris_ssi_bus_info);
 }
 
-device_init(stellaris_register_devices)
+type_init(stellaris_register_types)
index 9b1be8dadcd5d12c824c201c9ec8241aae794a4c..fbe99cb4a9b8108c9866a8dc0268fa6ec055dbf5 100644 (file)
@@ -441,9 +441,9 @@ static TypeInfo stellaris_enet_info = {
     .class_init    = stellaris_enet_class_init,
 };
 
-static void stellaris_enet_register_devices(void)
+static void stellaris_enet_register_types(void)
 {
     type_register_static(&stellaris_enet_info);
 }
 
-device_init(stellaris_enet_register_devices)
+type_init(stellaris_enet_register_types)
index 8d2e7eb6febce0e0c9245ec4eb92e394a21a2cb1..4d5b60fd1f318de90251b5874570f200a28e8a69 100644 (file)
@@ -1609,7 +1609,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
     return s;
 }
 
-static void strongarm_register_devices(void)
+static void strongarm_register_types(void)
 {
     type_register_static(&strongarm_pic_info);
     type_register_static(&strongarm_rtc_sysbus_info);
@@ -1618,4 +1618,5 @@ static void strongarm_register_devices(void)
     type_register_static(&strongarm_uart_info);
     type_register_static(&strongarm_ssp_info);
 }
-device_init(strongarm_register_devices)
+
+type_init(strongarm_register_types)
index 081d6cc8bd239a8faf6de91e5ad794e9ab41462b..8dfa5ecab6abd8a446c830dcc65ac1c8870019e6 100644 (file)
@@ -223,9 +223,9 @@ static TypeInfo sun4c_intctl_info = {
     .class_init    = sun4c_intctl_class_init,
 };
 
-static void sun4c_intctl_register_devices(void)
+static void sun4c_intctl_register_types(void)
 {
     type_register_static(&sun4c_intctl_info);
 }
 
-device_init(sun4c_intctl_register_devices)
+type_init(sun4c_intctl_register_types)
index b79d14c35a374e69ae0cb9ae5703a5e00cbadb42..99fb219b3a5f44b5dc2be74427a4b19afd66626d 100644 (file)
@@ -623,13 +623,6 @@ static TypeInfo idreg_info = {
     .class_init    = idreg_class_init,
 };
 
-static void idreg_register_devices(void)
-{
-    type_register_static(&idreg_info);
-}
-
-device_init(idreg_register_devices);
-
 typedef struct AFXState {
     SysBusDevice busdev;
     MemoryRegion mem;
@@ -672,13 +665,6 @@ static TypeInfo afx_info = {
     .class_init    = afx_class_init,
 };
 
-static void afx_register_devices(void)
-{
-    type_register_static(&afx_info);
-}
-
-device_init(afx_register_devices);
-
 typedef struct PROMState {
     SysBusDevice busdev;
     MemoryRegion prom;
@@ -756,13 +742,6 @@ static TypeInfo prom_info = {
     .class_init    = prom_class_init,
 };
 
-static void prom_register_devices(void)
-{
-    type_register_static(&prom_info);
-}
-
-device_init(prom_register_devices);
-
 typedef struct RamDevice
 {
     SysBusDevice busdev;
@@ -827,13 +806,6 @@ static TypeInfo ram_info = {
     .class_init    = ram_class_init,
 };
 
-static void ram_register_devices(void)
-{
-    type_register_static(&ram_info);
-}
-
-device_init(ram_register_devices);
-
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
@@ -1865,6 +1837,14 @@ static QEMUMachine ss2_machine = {
     .use_scsi = 1,
 };
 
+static void sun4m_register_types(void)
+{
+    type_register_static(&idreg_info);
+    type_register_static(&afx_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
 static void ss2_machine_init(void)
 {
     qemu_register_machine(&ss5_machine);
@@ -1881,4 +1861,5 @@ static void ss2_machine_init(void)
     qemu_register_machine(&ss2_machine);
 }
 
+type_init(sun4m_register_types)
 machine_init(ss2_machine_init);
index 727532cb094876506c853b72ba26cc3efc786f0a..ebefa91b7aaa97c2255608068bfb274b4f3bc48b 100644 (file)
@@ -380,9 +380,9 @@ static TypeInfo iommu_info = {
     .class_init    = iommu_class_init,
 };
 
-static void iommu_register_devices(void)
+static void iommu_register_types(void)
 {
     type_register_static(&iommu_info);
 }
 
-device_init(iommu_register_devices)
+type_init(iommu_register_types)
index 79bbd495eb5bdb29ac63ab1fa49b9622b5301d2c..423108f236078f9daf25cd01fc08f17317e7c4b8 100644 (file)
@@ -580,13 +580,6 @@ static TypeInfo ebus_info = {
     .class_init    = ebus_class_init,
 };
 
-static void pci_ebus_register(void)
-{
-    type_register_static(&ebus_info);
-}
-
-device_init(pci_ebus_register);
-
 typedef struct PROMState {
     SysBusDevice busdev;
     MemoryRegion prom;
@@ -664,13 +657,6 @@ static TypeInfo prom_info = {
     .class_init    = prom_class_init,
 };
 
-static void prom_register_devices(void)
-{
-    type_register_static(&prom_info);
-}
-
-device_init(prom_register_devices);
-
 
 typedef struct RamDevice
 {
@@ -728,13 +714,6 @@ static TypeInfo ram_info = {
     .class_init    = ram_class_init,
 };
 
-static void ram_register_devices(void)
-{
-    type_register_static(&ram_info);
-}
-
-device_init(ram_register_devices);
-
 static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
 {
     CPUState *env;
@@ -957,6 +936,13 @@ static QEMUMachine niagara_machine = {
     .max_cpus = 1, // XXX for now
 };
 
+static void sun4u_register_types(void)
+{
+    type_register_static(&ebus_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
 static void sun4u_machine_init(void)
 {
     qemu_register_machine(&sun4u_machine);
@@ -964,4 +950,5 @@ static void sun4u_machine_init(void)
     qemu_register_machine(&niagara_machine);
 }
 
+type_init(sun4u_register_types)
 machine_init(sun4u_machine_init);
index 282060abb6d59fbbbd65ea3fc6937c30b92fe853..db4efccef40bbf6dca7d32ccd78bec2d2c5e21d0 100644 (file)
@@ -256,9 +256,9 @@ static TypeInfo sysbus_device_type_info = {
     .class_init = sysbus_device_class_init,
 };
 
-static void sysbus_register(void)
+static void sysbus_register_types(void)
 {
     type_register_static(&sysbus_device_type_info);
 }
 
-device_init(sysbus_register);
+type_init(sysbus_register_types)
index ceb94c74a7489d3779e62219683fe794fd1b789d..2b66d8619ef24c157eceb1662bd0c3f481075ed4 100644 (file)
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -664,9 +664,9 @@ static TypeInfo tcx_info = {
     .class_init    = tcx_class_init,
 };
 
-static void tcx_register_devices(void)
+static void tcx_register_types(void)
 {
     type_register_static(&tcx_info);
 }
 
-device_init(tcx_register_devices)
+type_init(tcx_register_types)
index a3bdd91d40247d3d08416ce05edfba3cf3e78614..8e8dbd94eba1876f211bdd891f9375c864c814a9 100644 (file)
@@ -245,9 +245,9 @@ static TypeInfo tmp105_info = {
     .class_init    = tmp105_class_init,
 };
 
-static void tmp105_register_devices(void)
+static void tmp105_register_types(void)
 {
     type_register_static(&tmp105_info);
 }
 
-device_init(tmp105_register_devices)
+type_init(tmp105_register_types)
index c0d401759e9731a85becfd87d55da170673f9ff0..6baa17d6b5f7f3ea8bbeb271281bda98e387f478 100644 (file)
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -291,10 +291,10 @@ static TypeInfo tosa_ssp_info = {
     .class_init    = tosa_ssp_class_init,
 };
 
-static void tosa_register_devices(void)
+static void tosa_register_types(void)
 {
     type_register_static(&tosa_dac_info);
     type_register_static(&tosa_ssp_info);
 }
 
-device_init(tosa_register_devices)
+type_init(tosa_register_types)
index 0ade670906dc27988b579570bea13e1d845aa6c8..5ba8da6d6adeb97aae568f95c071e805225051e2 100644 (file)
@@ -805,9 +805,9 @@ static TypeInfo tusb6010_info = {
     .class_init    = tusb6010_class_init,
 };
 
-static void tusb6010_register_device(void)
+static void tusb6010_register_types(void)
 {
     type_register_static(&tusb6010_info);
 }
 
-device_init(tusb6010_register_device)
+type_init(tusb6010_register_types)
index 03fdccc8cea2f68b1600e24e2a0ab3a6e67b1bf2..873dc8f06875d7326a0779a8029b7a6cbc6ae64b 100644 (file)
@@ -876,9 +876,9 @@ static TypeInfo twl92230_info = {
     .class_init    = twl92230_class_init,
 };
 
-static void twl92230_register_devices(void)
+static void twl92230_register_types(void)
 {
     type_register_static(&twl92230_info);
 }
 
-device_init(twl92230_register_devices)
+type_init(twl92230_register_types)
index 17d86aac68eba19b644f0aa7ba6482bc3d399f9f..409bcd4cc669f12f8fbf9e3c1cd16959fe81bb7d 100644 (file)
@@ -467,7 +467,7 @@ static TypeInfo pci_unin_internal_info = {
     .class_init    = pci_unin_internal_class_init,
 };
 
-static void unin_register_devices(void)
+static void unin_register_types(void)
 {
     type_register_static(&unin_main_pci_host_info);
     type_register_static(&u3_agp_pci_host_info);
@@ -480,4 +480,4 @@ static void unin_register_devices(void)
     type_register_static(&pci_unin_internal_info);
 }
 
-device_init(unin_register_devices)
+type_init(unin_register_types)
index cd589b718ad422e5e6224b6126995df95074965a..fed136117b29a7082d0464bb4bb91263064116c4 100644 (file)
@@ -607,7 +607,7 @@ static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
-        switch (p->devep) {
+        switch (p->ep->nr) {
         case 1:
             ret = usb_audio_handle_dataout(s, p);
             break;
@@ -624,7 +624,7 @@ fail:
     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);
+                        p->pid, p->ep->nr, p->iov.size);
     }
     return ret;
 }
@@ -691,7 +691,6 @@ static void usb_audio_class_init(ObjectClass *klass, void *data)
     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;
@@ -706,10 +705,10 @@ static TypeInfo usb_audio_info = {
     .class_init    = usb_audio_class_init,
 };
 
-static void usb_audio_register_devices(void)
+static void usb_audio_register_types(void)
 {
     type_register_static(&usb_audio_info);
     usb_legacy_register("usb-audio", "audio", NULL);
 }
 
-device_init(usb_audio_register_devices)
+type_init(usb_audio_register_types)
index 90c3b0e0ebb764de3e2a44b6a352102f6136acaf..649bdcf2d75665728a5c2468f5081e84bbd20dba 100644 (file)
@@ -423,7 +423,7 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
 
     switch (p->pid) {
     case USB_TOKEN_IN:
-        switch (p->devep & 0xf) {
+        switch (p->ep->nr) {
         case USB_EVT_EP:
             ret = usb_bt_fifo_dequeue(&s->evt, p);
             break;
@@ -442,7 +442,7 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
         break;
 
     case USB_TOKEN_OUT:
-        switch (p->devep & 0xf) {
+        switch (p->ep->nr) {
         case USB_ACL_EP:
             usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
                             usb_bt_hci_acl_complete, p);
@@ -535,7 +535,6 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -550,8 +549,9 @@ static TypeInfo bt_info = {
     .class_init    = usb_bt_class_initfn,
 };
 
-static void usb_bt_register_devices(void)
+static void usb_bt_register_types(void)
 {
     type_register_static(&bt_info);
 }
-device_init(usb_bt_register_devices)
+
+type_init(usb_bt_register_types)
index b7538345842b48892b31193af403f55dbaef3e80..ae79a4527b0a0e3c2a12127b12371ab237473976 100644 (file)
@@ -74,21 +74,21 @@ static int usb_device_init(USBDevice *dev)
     return 0;
 }
 
-static void usb_device_handle_destroy(USBDevice *dev)
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
 {
     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_destroy) {
-        klass->handle_destroy(dev);
+    if (klass->find_device) {
+        return klass->find_device(dev, addr);
     }
+    return NULL;
 }
 
-int usb_device_handle_packet(USBDevice *dev, USBPacket *p)
+static void usb_device_handle_destroy(USBDevice *dev)
 {
     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
-    if (klass->handle_packet) {
-        return klass->handle_packet(dev, p);
+    if (klass->handle_destroy) {
+        klass->handle_destroy(dev);
     }
-    return -ENOSYS;
 }
 
 void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
@@ -586,9 +586,9 @@ static TypeInfo usb_device_type_info = {
     .class_init = usb_device_class_init,
 };
 
-static void usb_register_devices(void)
+static void usb_register_types(void)
 {
     type_register_static(&usb_device_type_info);
 }
 
-device_init(usb_register_devices);
+type_init(usb_register_types)
index 881da3002e0c2e55bfe77bc6cf8d0518a62e5be3..0b2ac8037a9688c2f501b1b141e5e2de75c6605d 100644 (file)
@@ -267,6 +267,7 @@ typedef struct CCIDBus {
  */
 typedef struct USBCCIDState {
     USBDevice dev;
+    USBEndpoint *intr;
     CCIDBus bus;
     CCIDCardState *card;
     BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
@@ -839,7 +840,7 @@ static void ccid_on_slot_change(USBCCIDState *s, bool full)
         s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
     }
     s->notify_slot_change = true;
-    usb_wakeup(&s->dev);
+    usb_wakeup(s->intr);
 }
 
 static void ccid_write_data_block_error(
@@ -995,7 +996,7 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
         break;
 
     case USB_TOKEN_IN:
-        switch (p->devep & 0xf) {
+        switch (p->ep->nr) {
         case CCID_BULK_IN_EP:
             if (!p->iov.size) {
                 ret = USB_RET_NAK;
@@ -1190,6 +1191,7 @@ static int ccid_initfn(USBDevice *dev)
 
     usb_desc_init(dev);
     qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
     s->bus.qbus.allow_hotplug = 1;
     s->card = NULL;
     s->migration_state = MIGRATION_NONE;
@@ -1320,7 +1322,6 @@ static void ccid_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -1354,10 +1355,11 @@ static TypeInfo ccid_card_type_info = {
     .class_init = ccid_card_class_init,
 };
 
-static void ccid_register_devices(void)
+static void ccid_register_types(void)
 {
     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)
+
+type_init(ccid_register_types)
index 75ef71e69ee98844b319f69924c47e7ccc9dc10b..e6998143052af0a38eac6c16569a6949e95ce2f4 100644 (file)
@@ -715,8 +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 == NULL ||
-            q->packet.owner->dev != dev) {
+        if (!usb_packet_is_inflight(&q->packet) ||
+            q->packet.ep->dev != dev) {
             continue;
         }
         ehci_free_queue(q);
@@ -765,6 +765,11 @@ static void ehci_detach(USBPort *port)
         USBPort *companion = s->companion_ports[port->index];
         companion->ops->detach(companion);
         companion->dev = NULL;
+        /*
+         * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
+         * the port ownership is returned immediately to the EHCI controller."
+         */
+        *portsc &= ~PORTSC_POWNER;
         return;
     }
 
@@ -845,6 +850,26 @@ static int ehci_register_companion(USBBus *bus, USBPort *ports[],
     return 0;
 }
 
+static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
+{
+    USBDevice *dev;
+    USBPort *port;
+    int i;
+
+    for (i = 0; i < NB_PORTS; i++) {
+        port = &ehci->ports[i];
+        if (!(ehci->portsc[i] & PORTSC_PED)) {
+            DPRINTF("Port %d not enabled\n", i);
+            continue;
+        }
+        dev = usb_find_device(port, addr);
+        if (dev != NULL) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
 /* 4.1 host controller initialization */
 static void ehci_reset(void *opaque)
 {
@@ -883,7 +908,7 @@ static void ehci_reset(void *opaque)
         }
         if (devs[i] && devs[i]->attached) {
             usb_attach(&s->ports[i]);
-            usb_send_msg(devs[i], USB_MSG_RESET);
+            usb_device_reset(devs[i]);
         }
     }
     ehci_queues_rip_all(s);
@@ -982,7 +1007,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
     if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
         trace_usb_ehci_port_reset(port, 0);
         if (dev && dev->attached) {
-            usb_reset(&s->ports[port]);
+            usb_port_reset(&s->ports[port]);
             *portsc &= ~PORTSC_CSC;
         }
 
@@ -1331,10 +1356,9 @@ err:
 
 static int ehci_execute(EHCIQueue *q)
 {
-    USBPort *port;
     USBDevice *dev;
+    USBEndpoint *ep;
     int ret;
-    int i;
     int endp;
     int devadr;
 
@@ -1364,33 +1388,18 @@ static int ehci_execute(EHCIQueue *q)
     endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
     devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
 
-    ret = USB_RET_NODEV;
+    /* TODO: associating device with ehci port */
+    dev = ehci_find_device(q->ehci, devadr);
+    ep = usb_ep_get(dev, q->pid, endp);
 
-    usb_packet_setup(&q->packet, q->pid, devadr, endp);
+    usb_packet_setup(&q->packet, q->pid, ep);
     usb_packet_map(&q->packet, &q->sgl);
 
-    // TO-DO: associating device with ehci port
-    for(i = 0; i < NB_PORTS; i++) {
-        port = &q->ehci->ports[i];
-        dev = port->dev;
-
-        if (!(q->ehci->portsc[i] &(PORTSC_CONNECT))) {
-            DPRINTF("Port %d, no exec, not connected(%08X)\n",
-                    i, q->ehci->portsc[i]);
-            continue;
-        }
-
-        ret = usb_handle_packet(dev, &q->packet);
-
-        DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
-                "(total %d) endp %x ret %d\n",
-                q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
-                q->packet.iov.size, q->tbytes, endp, ret);
-
-        if (ret != USB_RET_NODEV) {
-            break;
-        }
-    }
+    ret = usb_handle_packet(dev, &q->packet);
+    DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
+            "(total %d) endp %x ret %d\n",
+            q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
+            q->packet.iov.size, q->tbytes, endp, ret);
 
     if (ret > BUFF_SIZE) {
         fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
@@ -1406,10 +1415,10 @@ static int ehci_execute(EHCIQueue *q)
 static int ehci_process_itd(EHCIState *ehci,
                             EHCIitd *itd)
 {
-    USBPort *port;
     USBDevice *dev;
+    USBEndpoint *ep;
     int ret;
-    uint32_t i, j, len, pid, dir, devaddr, endp;
+    uint32_t i, len, pid, dir, devaddr, endp;
     uint32_t pg, off, ptr1, ptr2, max, mult;
 
     dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
@@ -1447,24 +1456,12 @@ static int ehci_process_itd(EHCIState *ehci,
 
             pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
 
-            usb_packet_setup(&ehci->ipacket, pid, devaddr, endp);
+            dev = ehci_find_device(ehci, devaddr);
+            ep = usb_ep_get(dev, pid, endp);
+            usb_packet_setup(&ehci->ipacket, pid, ep);
             usb_packet_map(&ehci->ipacket, &ehci->isgl);
 
-            ret = USB_RET_NODEV;
-            for (j = 0; j < NB_PORTS; j++) {
-                port = &ehci->ports[j];
-                dev = port->dev;
-
-                if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
-                    continue;
-                }
-
-                ret = usb_handle_packet(dev, &ehci->ipacket);
-
-                if (ret != USB_RET_NODEV) {
-                    break;
-                }
-            }
+            ret = usb_handle_packet(dev, &ehci->ipacket);
 
             usb_packet_unmap(&ehci->ipacket);
             qemu_sglist_destroy(&ehci->isgl);
@@ -2376,12 +2373,13 @@ static int usb_ehci_initfn(PCIDevice *dev)
     return 0;
 }
 
-static void ehci_register(void)
+static void ehci_register_types(void)
 {
     type_register_static(&ehci_info);
     type_register_static(&ich9_ehci_info);
 }
-device_init(ehci_register);
+
+type_init(ehci_register_types)
 
 /*
  * vim: expandtab ts=4
index 3c4e45da702aadd5a43add040d427d201a63bd61..7fc0bd81aac775fa39f4568723641afbfd6cde9d 100644 (file)
@@ -44,6 +44,7 @@
 
 typedef struct USBHIDState {
     USBDevice dev;
+    USBEndpoint *intr;
     HIDState hid;
 } USBHIDState;
 
@@ -360,7 +361,7 @@ static void usb_hid_changed(HIDState *hs)
 {
     USBHIDState *us = container_of(hs, USBHIDState, hid);
 
-    usb_wakeup(&us->dev);
+    usb_wakeup(us->intr);
 }
 
 static void usb_hid_handle_reset(USBDevice *dev)
@@ -463,7 +464,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 
     switch (p->pid) {
     case USB_TOKEN_IN:
-        if (p->devep == 1) {
+        if (p->ep->nr == 1) {
             int64_t curtime = qemu_get_clock_ns(vm_clock);
             if (!hid_has_events(hs) &&
                 (!hs->idle || hs->next_idle_clock - curtime > 0)) {
@@ -501,6 +502,7 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
 
     usb_desc_init(dev);
+    us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
     hid_init(&us->hid, kind, usb_hid_changed);
     return 0;
 }
@@ -557,7 +559,6 @@ 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;
@@ -621,7 +622,7 @@ static TypeInfo usb_keyboard_info = {
     .class_init    = usb_keyboard_class_initfn,
 };
 
-static void usb_hid_register_devices(void)
+static void usb_hid_register_types(void)
 {
     type_register_static(&usb_tablet_info);
     usb_legacy_register("usb-tablet", "tablet", NULL);
@@ -630,4 +631,5 @@ static void usb_hid_register_devices(void)
     type_register_static(&usb_keyboard_info);
     usb_legacy_register("usb-kbd", "keyboard", NULL);
 }
-device_init(usb_hid_register_devices)
+
+type_init(usb_hid_register_types)
index 956b020eede56af62b67a09fe55da9b8111f3cbc..a12856e2e93411ecd641f73050e02cfc0c9a58f7 100644 (file)
@@ -37,6 +37,7 @@ typedef struct USBHubPort {
 
 typedef struct USBHubState {
     USBDevice dev;
+    USBEndpoint *intr;
     USBHubPort ports[NUM_PORTS];
 } USBHubState;
 
@@ -163,7 +164,7 @@ static void usb_hub_attach(USBPort *port1)
     } else {
         port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
     }
-    usb_wakeup(&s->dev);
+    usb_wakeup(s->intr);
 }
 
 static void usb_hub_detach(USBPort *port1)
@@ -171,7 +172,7 @@ static void usb_hub_detach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
-    usb_wakeup(&s->dev);
+    usb_wakeup(s->intr);
 
     /* Let upstream know the device on this port is gone */
     s->dev.port->ops->child_detach(s->dev.port, port1->dev);
@@ -199,7 +200,7 @@ static void usb_hub_wakeup(USBPort *port1)
 
     if (port->wPortStatus & PORT_STAT_SUSPEND) {
         port->wPortChange |= PORT_STAT_C_SUSPEND;
-        usb_wakeup(&s->dev);
+        usb_wakeup(s->intr);
     }
 }
 
@@ -220,6 +221,26 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
     s->dev.port->ops->complete(s->dev.port, packet);
 }
 
+static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
+{
+    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubPort *port;
+    USBDevice *downstream;
+    int i;
+
+    for (i = 0; i < NUM_PORTS; i++) {
+        port = &s->ports[i];
+        if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
+            continue;
+        }
+        downstream = usb_find_device(&port->port, addr);
+        if (downstream != NULL) {
+            return downstream;
+        }
+    }
+    return NULL;
+}
+
 static void usb_hub_handle_reset(USBDevice *dev)
 {
     USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
@@ -305,7 +326,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                 break;
             case PORT_RESET:
                 if (dev && dev->attached) {
-                    usb_send_msg(dev, USB_MSG_RESET);
+                    usb_device_reset(dev);
                     port->wPortChange |= PORT_STAT_C_RESET;
                     /* set enable bit */
                     port->wPortStatus |= PORT_STAT_ENABLE;
@@ -396,7 +417,7 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
 
     switch(p->pid) {
     case USB_TOKEN_IN:
-        if (p->devep == 1) {
+        if (p->ep->nr == 1) {
             USBHubPort *port;
             unsigned int status;
             uint8_t buf[4];
@@ -435,44 +456,6 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
     return ret;
 }
 
-static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
-{
-    USBHubPort *port;
-    USBDevice *dev;
-    int i, ret;
-
-    for(i = 0; i < NUM_PORTS; i++) {
-        port = &s->ports[i];
-        dev = port->port.dev;
-        if (dev && dev->attached && (port->wPortStatus & PORT_STAT_ENABLE)) {
-            ret = usb_handle_packet(dev, p);
-            if (ret != USB_RET_NODEV) {
-                return ret;
-            }
-        }
-    }
-    return USB_RET_NODEV;
-}
-
-static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
-{
-    USBHubState *s = (USBHubState *)dev;
-
-#if defined(DEBUG) && 0
-    printf("usb_hub: pid=0x%x\n", pid);
-#endif
-    if (dev->state == USB_STATE_DEFAULT &&
-        dev->addr != 0 &&
-        p->devaddr != dev->addr &&
-        (p->pid == USB_TOKEN_SETUP ||
-         p->pid == USB_TOKEN_OUT ||
-         p->pid == USB_TOKEN_IN)) {
-        /* broadcast the packet to the devices */
-        return usb_hub_broadcast_packet(s, p);
-    }
-    return usb_generic_handle_packet(dev, p);
-}
-
 static void usb_hub_handle_destroy(USBDevice *dev)
 {
     USBHubState *s = (USBHubState *)dev;
@@ -499,6 +482,7 @@ static int usb_hub_initfn(USBDevice *dev)
     int i;
 
     usb_desc_init(dev);
+    s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
     for (i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
@@ -541,7 +525,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data)
     uc->init           = usb_hub_initfn;
     uc->product_desc   = "QEMU USB Hub";
     uc->usb_desc       = &desc_hub;
-    uc->handle_packet  = usb_hub_handle_packet;
+    uc->find_device    = usb_hub_find_device;
     uc->handle_reset   = usb_hub_handle_reset;
     uc->handle_control = usb_hub_handle_control;
     uc->handle_data    = usb_hub_handle_data;
@@ -557,8 +541,9 @@ static TypeInfo hub_info = {
     .class_init    = usb_hub_class_initfn,
 };
 
-static void usb_hub_register_devices(void)
+static void usb_hub_register_types(void)
 {
     type_register_static(&hub_info);
 }
-device_init(usb_hub_register_devices)
+
+type_init(usb_hub_register_types)
index 6153376f3f355e6d10dfdbf7631b12ae1dc1b666..c933efe19aa4053b3235d13a2f479a24d6149117 100644 (file)
@@ -341,7 +341,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
     uint32_t tag;
     int ret = 0;
     struct usb_msd_cbw cbw;
-    uint8_t devep = p->devep;
+    uint8_t devep = p->ep->nr;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -651,7 +651,6 @@ static void usb_msd_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -669,9 +668,10 @@ static TypeInfo msd_info = {
     .class_init    = usb_msd_class_initfn,
 };
 
-static void usb_msd_register_devices(void)
+static void usb_msd_register_types(void)
 {
     type_register_static(&msd_info);
     usb_legacy_register("usb-storage", "disk", usb_msd_init);
 }
-device_init(usb_msd_register_devices)
+
+type_init(usb_msd_register_types)
index 4f528d25e56514d1033e4a658eace3bda9e42b7d..820907a9a9ffc71167feded602fd2fce23f01a08 100644 (file)
@@ -605,6 +605,8 @@ static int musb_timeout(int ttype, int speed, int val)
 static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
                 int epnum, int pid, int len, USBCallback cb, int dir)
 {
+    USBDevice *dev;
+    USBEndpoint *uep;
     int ret;
     int idx = epnum && dir;
     int ttype;
@@ -622,16 +624,14 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     ep->delayed_cb[dir] = cb;
 
     /* A wild guess on the FADDR semantics... */
-    usb_packet_setup(&ep->packey[dir].p, pid, ep->faddr[idx],
-                     ep->type[idx] & 0xf);
+    dev = usb_find_device(&s->port, ep->faddr[idx]);
+    uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
+    usb_packet_setup(&ep->packey[dir].p, pid, uep);
     usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
     ep->packey[dir].ep = ep;
     ep->packey[dir].dir = dir;
 
-    if (s->port.dev)
-        ret = usb_handle_packet(s->port.dev, &ep->packey[dir].p);
-    else
-        ret = USB_RET_NODEV;
+    ret = usb_handle_packet(dev, &ep->packey[dir].p);
 
     if (ret == USB_RET_ASYNC) {
         ep->status[dir] = len;
@@ -812,8 +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 == NULL ||
-                s->ep[ep].packey[dir].p.owner->dev != dev) {
+            if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) ||
+                s->ep[ep].packey[dir].p.ep->dev != dev) {
                 continue;
             }
             usb_cancel_packet(&s->ep[ep].packey[dir].p);
@@ -1310,7 +1310,7 @@ static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
         s->power = (value & 0xef) | (s->power & 0x10);
         /* MGC_M_POWER_RESET is also read-only in Peripheral Mode */
         if ((value & MGC_M_POWER_RESET) && s->port.dev) {
-            usb_send_msg(s->port.dev, USB_MSG_RESET);
+            usb_device_reset(s->port.dev);
             /* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set.  */
             if ((value & MGC_M_POWER_HSENAB) &&
                             s->port.dev->speed == USB_SPEED_HIGH)
index e2111413b49adfd480bbcbad8f4ade4a7f461d88..49d5d4db65cbd6316c736a2f524526671024a3e8 100644 (file)
@@ -1210,7 +1210,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
 
     switch(p->pid) {
     case USB_TOKEN_IN:
-        switch (p->devep) {
+        switch (p->ep->nr) {
         case 1:
             ret = usb_net_handle_statusin(s, p);
             break;
@@ -1225,7 +1225,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
         break;
 
     case USB_TOKEN_OUT:
-        switch (p->devep) {
+        switch (p->ep->nr) {
         case 2:
             ret = usb_net_handle_dataout(s, p);
             break;
@@ -1243,7 +1243,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
     if (ret == USB_RET_STALL)
         fprintf(stderr, "usbnet: failed data transaction: "
                         "pid 0x%x ep 0x%x len 0x%zx\n",
-                        p->pid, p->devep, p->iov.size);
+                        p->pid, p->ep->nr, p->iov.size);
     return ret;
 }
 
@@ -1398,7 +1398,6 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -1415,9 +1414,10 @@ static TypeInfo net_info = {
     .class_init    = usb_net_class_initfn,
 };
 
-static void usb_net_register_devices(void)
+static void usb_net_register_types(void)
 {
     type_register_static(&net_info);
     usb_legacy_register("usb-net", "net", usb_net_init);
 }
-device_init(usb_net_register_devices)
+
+type_init(usb_net_register_types)
index 425030f141c8cba515e071759d42584914ecfad2..7aa19fe781c9b09d9b1cba75e2276c5cc539b972 100644 (file)
@@ -408,6 +408,23 @@ static void ohci_child_detach(USBPort *port1, USBDevice *child)
     ohci_async_cancel_device(s, child);
 }
 
+static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
+{
+    USBDevice *dev;
+    int i;
+
+    for (i = 0; i < ohci->num_ports; i++) {
+        if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
+            continue;
+        }
+        dev = usb_find_device(&ohci->rhport[i].port, addr);
+        if (dev != NULL) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
 /* Reset the controller */
 static void ohci_reset(void *opaque)
 {
@@ -449,7 +466,7 @@ static void ohci_reset(void *opaque)
         port = &ohci->rhport[i];
         port->ctrl = 0;
         if (port->port.dev && port->port.dev->attached) {
-            usb_reset(&port->port);
+            usb_port_reset(&port->port);
         }
       }
     if (ohci->async_td) {
@@ -640,6 +657,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     int ret;
     int i;
     USBDevice *dev;
+    USBEndpoint *ep;
     struct ohci_iso_td iso_td;
     uint32_t addr;
     uint16_t starting_frame;
@@ -779,20 +797,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     if (completion) {
         ret = ohci->usb_packet.result;
     } else {
-        ret = USB_RET_NODEV;
-        for (i = 0; i < ohci->num_ports; i++) {
-            dev = ohci->rhport[i].port.dev;
-            if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
-                continue;
-            usb_packet_setup(&ohci->usb_packet, pid,
-                             OHCI_BM(ed->flags, ED_FA),
-                             OHCI_BM(ed->flags, ED_EN));
-            usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
-            ret = usb_handle_packet(dev, &ohci->usb_packet);
-            if (ret != USB_RET_NODEV)
-                break;
-        }
-    
+        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+        usb_packet_setup(&ohci->usb_packet, pid, ep);
+        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
+        ret = usb_handle_packet(dev, &ohci->usb_packet);
         if (ret == USB_RET_ASYNC) {
             return 1;
         }
@@ -880,6 +889,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     int ret;
     int i;
     USBDevice *dev;
+    USBEndpoint *ep;
     struct ohci_td td;
     uint32_t addr;
     int flag_r;
@@ -972,31 +982,22 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         ohci->async_td = 0;
         ohci->async_complete = 0;
     } else {
-        ret = USB_RET_NODEV;
-        for (i = 0; i < ohci->num_ports; i++) {
-            dev = ohci->rhport[i].port.dev;
-            if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0)
-                continue;
-
-            if (ohci->async_td) {
-                /* ??? The hardware should allow one active packet per
-                   endpoint.  We only allow one active packet per controller.
-                   This should be sufficient as long as devices respond in a
-                   timely manner.
-                 */
+        if (ohci->async_td) {
+            /* ??? The hardware should allow one active packet per
+               endpoint.  We only allow one active packet per controller.
+               This should be sufficient as long as devices respond in a
+               timely manner.
+            */
 #ifdef DEBUG_PACKET
-                DPRINTF("Too many pending packets\n");
+            DPRINTF("Too many pending packets\n");
 #endif
-                return 1;
-            }
-            usb_packet_setup(&ohci->usb_packet, pid,
-                             OHCI_BM(ed->flags, ED_FA),
-                             OHCI_BM(ed->flags, ED_EN));
-            usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
-            ret = usb_handle_packet(dev, &ohci->usb_packet);
-            if (ret != USB_RET_NODEV)
-                break;
+            return 1;
         }
+        dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+        ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
+        usb_packet_setup(&ohci->usb_packet, pid, ep);
+        usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
+        ret = usb_handle_packet(dev, &ohci->usb_packet);
 #ifdef DEBUG_PACKET
         DPRINTF("ret=%d\n", ret);
 #endif
@@ -1435,7 +1436,7 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
 
     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
         DPRINTF("usb-ohci: port %d: RESET\n", portnum);
-        usb_send_msg(port->port.dev, USB_MSG_RESET);
+        usb_device_reset(port->port.dev);
         port->ctrl &= ~OHCI_PORT_PRS;
         /* ??? Should this also set OHCI_PORT_PESC.  */
         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
@@ -1708,8 +1709,8 @@ 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 != NULL &&
-        ohci->usb_packet.owner->dev == dev) {
+        usb_packet_is_inflight(&ohci->usb_packet) &&
+        ohci->usb_packet.ep->dev == dev) {
         usb_cancel_packet(&ohci->usb_packet);
         ohci->async_td = 0;
     }
@@ -1886,9 +1887,10 @@ static TypeInfo ohci_sysbus_info = {
     .class_init    = ohci_sysbus_class_init,
 };
 
-static void ohci_register(void)
+static void ohci_register_types(void)
 {
     type_register_static(&ohci_pci_info);
     type_register_static(&ohci_sysbus_info);
 }
-device_init(ohci_register);
+
+type_init(ohci_register_types)
index c2cb6d24e81a2b8e85719ed1f6c3a9540d87f57e..52676e8f7bce34535693e14218bd6a1c49c77fdc 100644 (file)
@@ -353,7 +353,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBSerialState *s = (USBSerialState *)dev;
     int i, ret = 0;
-    uint8_t devep = p->devep;
+    uint8_t devep = p->ep->nr;
     struct iovec *iov;
     uint8_t header[2];
     int first_len, len;
@@ -583,7 +583,6 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -612,7 +611,6 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data)
     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;
@@ -628,11 +626,12 @@ static TypeInfo braille_info = {
     .class_init    = usb_braille_class_initfn,
 };
 
-static void usb_serial_register_devices(void)
+static void usb_serial_register_types(void)
 {
     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)
+
+type_init(usb_serial_register_types)
index cddcc8927a01885b1f92519a75dcbddd8abb02c7..2280dc792ddb1401b997cf3c8b5153a97bf0614f 100644 (file)
@@ -73,7 +73,7 @@
 
 #define FRAME_TIMER_FREQ 1000
 
-#define FRAME_MAX_LOOPS  100
+#define FRAME_MAX_LOOPS  256
 
 #define NB_PORTS 2
 
@@ -94,15 +94,6 @@ static const char *pid2str(int pid)
 #define DPRINTF(...)
 #endif
 
-#ifdef DEBUG_DUMP_DATA
-static void dump_data(USBPacket *p, int ret)
-{
-    iov_hexdump(p->iov.iov, p->iov.niov, stderr, "uhci", ret);
-}
-#else
-static void dump_data(USBPacket *p, int ret) {}
-#endif
-
 typedef struct UHCIState UHCIState;
 
 /* 
@@ -245,8 +236,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 == NULL ||
-            curr->packet.owner->dev != dev) {
+        if (!usb_packet_is_inflight(&curr->packet) ||
+            curr->packet.ep->dev != dev) {
             continue;
         }
         uhci_async_unlink(s, curr);
@@ -342,7 +333,7 @@ static void uhci_reset(void *opaque)
         port = &s->ports[i];
         port->ctrl = 0x0080;
         if (port->port.dev && port->port.dev->attached) {
-            usb_reset(&port->port);
+            usb_port_reset(&port->port);
         }
     }
 
@@ -440,16 +431,12 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
         }
         if (val & UHCI_CMD_GRESET) {
             UHCIPort *port;
-            USBDevice *dev;
             int i;
 
             /* send reset on the USB bus */
             for(i = 0; i < NB_PORTS; i++) {
                 port = &s->ports[i];
-                dev = port->port.dev;
-                if (dev && dev->attached) {
-                    usb_send_msg(dev, USB_MSG_RESET);
-                }
+                usb_device_reset(port->port.dev);
             }
             uhci_reset(s);
             return;
@@ -491,7 +478,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                 /* port reset */
                 if ( (val & UHCI_PORT_RESET) &&
                      !(port->ctrl & UHCI_PORT_RESET) ) {
-                    usb_send_msg(dev, USB_MSG_RESET);
+                    usb_device_reset(dev);
                 }
             }
             port->ctrl &= UHCI_PORT_READ_ONLY;
@@ -647,30 +634,22 @@ static void uhci_wakeup(USBPort *port1)
     }
 }
 
-static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
+static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
 {
-    int i, ret;
-
-    DPRINTF("uhci: packet enter. pid %s addr 0x%02x ep %d len %zd\n",
-           pid2str(p->pid), p->devaddr, p->devep, p->iov.size);
-    if (p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_SETUP)
-        dump_data(p, 0);
+    USBDevice *dev;
+    int i;
 
-    ret = USB_RET_NODEV;
-    for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) {
+    for (i = 0; i < NB_PORTS; i++) {
         UHCIPort *port = &s->ports[i];
-        USBDevice *dev = port->port.dev;
-
-        if (dev && dev->attached && (port->ctrl & UHCI_PORT_EN)) {
-            ret = usb_handle_packet(dev, p);
+        if (!(port->ctrl & UHCI_PORT_EN)) {
+            continue;
+        }
+        dev = usb_find_device(&port->port, addr);
+        if (dev != NULL) {
+            return dev;
         }
     }
-
-    DPRINTF("uhci: packet exit. ret %d len %zd\n", ret, p->iov.size);
-    if (p->pid == USB_TOKEN_IN && ret > 0)
-        dump_data(p, ret);
-
-    return ret;
+    return NULL;
 }
 
 static void uhci_async_complete(USBPort *port, USBPacket *packet);
@@ -782,6 +761,8 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     int len = 0, max_len;
     uint8_t pid, isoc;
     uint32_t token;
+    USBDevice *dev;
+    USBEndpoint *ep;
 
     /* Is active ? */
     if (!(td->ctrl & TD_CTRL_ACTIVE))
@@ -826,21 +807,22 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
 
-    usb_packet_setup(&async->packet, pid, (td->token >> 8) & 0x7f,
-                     (td->token >> 15) & 0xf);
+    dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
+    ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+    usb_packet_setup(&async->packet, pid, ep);
     qemu_sglist_add(&async->sgl, td->buffer, max_len);
     usb_packet_map(&async->packet, &async->sgl);
 
     switch(pid) {
     case USB_TOKEN_OUT:
     case USB_TOKEN_SETUP:
-        len = uhci_broadcast_packet(s, &async->packet);
+        len = usb_handle_packet(dev, &async->packet);
         if (len >= 0)
             len = max_len;
         break;
 
     case USB_TOKEN_IN:
-        len = uhci_broadcast_packet(s, &async->packet);
+        len = usb_handle_packet(dev, &async->packet);
         break;
 
     default:
@@ -942,7 +924,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr)
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
-    uint32_t curr_qh;
+    uint32_t curr_qh, td_count = 0, bytes_count = 0;
     int cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
@@ -967,13 +949,26 @@ static void uhci_process_frame(UHCIState *s)
             if (qhdb_insert(&qhdb, link)) {
                 /*
                  * We're going in circles. Which is not a bug because
-                 * HCD is allowed to do that as part of the BW management. 
-                 * In our case though it makes no sense to spin here. Sync transations 
-                 * are already done, and async completion handler will re-process 
-                 * the frame when something is ready.
+                 * HCD is allowed to do that as part of the BW management.
+                 *
+                 * Stop processing here if
+                 *  (a) no transaction has been done since we've been
+                 *      here last time, or
+                 *  (b) we've reached the usb 1.1 bandwidth, which is
+                 *      1280 bytes/frame.
                  */
                 DPRINTF("uhci: detected loop. qh 0x%x\n", link);
-                break;
+                if (td_count == 0) {
+                    DPRINTF("uhci: no transaction last round, stop\n");
+                    break;
+                } else if (bytes_count >= 1280) {
+                    DPRINTF("uhci: bandwidth limit reached, stop\n");
+                    break;
+                } else {
+                    td_count = 0;
+                    qhdb_reset(&qhdb);
+                    qhdb_insert(&qhdb, link);
+                }
             }
 
             pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
@@ -1033,6 +1028,8 @@ static void uhci_process_frame(UHCIState *s)
                 link, td.link, td.ctrl, td.token, curr_qh);
 
         link = td.link;
+        td_count++;
+        bytes_count += (td.ctrl & 0x7ff) + 1;
 
         if (curr_qh) {
            /* update QH element link */
@@ -1321,7 +1318,7 @@ static TypeInfo ich9_uhci3_info = {
     .class_init    = ich9_uhci3_class_init,
 };
 
-static void uhci_register(void)
+static void uhci_register_types(void)
 {
     type_register_static(&piix3_uhci_info);
     type_register_static(&piix4_uhci_info);
@@ -1330,7 +1327,8 @@ static void uhci_register(void)
     type_register_static(&ich9_uhci2_info);
     type_register_static(&ich9_uhci3_info);
 }
-device_init(uhci_register);
+
+type_init(uhci_register_types)
 
 void usb_uhci_piix3_init(PCIBus *bus, int devfn)
 {
index 14de14d5f763068232c145b6f45c19c21ddb4c01..197e2dced5ca5655ef877153d3d71a9f9b4c5c7f 100644 (file)
@@ -306,7 +306,7 @@ static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
 
     switch (p->pid) {
     case USB_TOKEN_IN:
-        if (p->devep == 1) {
+        if (p->ep->nr == 1) {
             if (!(s->changed || s->idle))
                 return USB_RET_NAK;
             s->changed = 0;
@@ -357,7 +357,6 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data)
     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;
@@ -373,9 +372,10 @@ static TypeInfo wacom_info = {
     .class_init    = usb_wacom_class_init,
 };
 
-static void usb_wacom_register_devices(void)
+static void usb_wacom_register_types(void)
 {
     type_register_static(&wacom_info);
     usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL);
 }
-device_init(usb_wacom_register_devices)
+
+type_init(usb_wacom_register_types)
index 37e887c43101e1b4539a233d7f789cc2bb04a98b..008b0b5718e50842347cd0e23e9ed1660b64b892 100644 (file)
@@ -307,7 +307,8 @@ typedef struct XHCIState XHCIState;
 typedef struct XHCITransfer {
     XHCIState *xhci;
     USBPacket packet;
-    bool running;
+    bool running_async;
+    bool running_retry;
     bool cancelled;
     bool complete;
     bool backgrounded;
@@ -338,6 +339,7 @@ typedef struct XHCIEPContext {
     unsigned int next_xfer;
     unsigned int comp_xfer;
     XHCITransfer transfers[TD_QUEUE];
+    XHCITransfer *retry;
     bool bg_running;
     bool bg_updating;
     unsigned int next_bg;
@@ -420,6 +422,60 @@ typedef struct XHCIEvRingSeg {
     uint32_t rsvd;
 } XHCIEvRingSeg;
 
+#ifdef DEBUG_XHCI
+static const char *TRBType_names[] = {
+    [TRB_RESERVED]                     = "TRB_RESERVED",
+    [TR_NORMAL]                        = "TR_NORMAL",
+    [TR_SETUP]                         = "TR_SETUP",
+    [TR_DATA]                          = "TR_DATA",
+    [TR_STATUS]                        = "TR_STATUS",
+    [TR_ISOCH]                         = "TR_ISOCH",
+    [TR_LINK]                          = "TR_LINK",
+    [TR_EVDATA]                        = "TR_EVDATA",
+    [TR_NOOP]                          = "TR_NOOP",
+    [CR_ENABLE_SLOT]                   = "CR_ENABLE_SLOT",
+    [CR_DISABLE_SLOT]                  = "CR_DISABLE_SLOT",
+    [CR_ADDRESS_DEVICE]                = "CR_ADDRESS_DEVICE",
+    [CR_CONFIGURE_ENDPOINT]            = "CR_CONFIGURE_ENDPOINT",
+    [CR_EVALUATE_CONTEXT]              = "CR_EVALUATE_CONTEXT",
+    [CR_RESET_ENDPOINT]                = "CR_RESET_ENDPOINT",
+    [CR_STOP_ENDPOINT]                 = "CR_STOP_ENDPOINT",
+    [CR_SET_TR_DEQUEUE]                = "CR_SET_TR_DEQUEUE",
+    [CR_RESET_DEVICE]                  = "CR_RESET_DEVICE",
+    [CR_FORCE_EVENT]                   = "CR_FORCE_EVENT",
+    [CR_NEGOTIATE_BW]                  = "CR_NEGOTIATE_BW",
+    [CR_SET_LATENCY_TOLERANCE]         = "CR_SET_LATENCY_TOLERANCE",
+    [CR_GET_PORT_BANDWIDTH]            = "CR_GET_PORT_BANDWIDTH",
+    [CR_FORCE_HEADER]                  = "CR_FORCE_HEADER",
+    [CR_NOOP]                          = "CR_NOOP",
+    [ER_TRANSFER]                      = "ER_TRANSFER",
+    [ER_COMMAND_COMPLETE]              = "ER_COMMAND_COMPLETE",
+    [ER_PORT_STATUS_CHANGE]            = "ER_PORT_STATUS_CHANGE",
+    [ER_BANDWIDTH_REQUEST]             = "ER_BANDWIDTH_REQUEST",
+    [ER_DOORBELL]                      = "ER_DOORBELL",
+    [ER_HOST_CONTROLLER]               = "ER_HOST_CONTROLLER",
+    [ER_DEVICE_NOTIFICATION]           = "ER_DEVICE_NOTIFICATION",
+    [ER_MFINDEX_WRAP]                  = "ER_MFINDEX_WRAP",
+    [CR_VENDOR_VIA_CHALLENGE_RESPONSE] = "CR_VENDOR_VIA_CHALLENGE_RESPONSE",
+    [CR_VENDOR_NEC_FIRMWARE_REVISION]  = "CR_VENDOR_NEC_FIRMWARE_REVISION",
+    [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
+};
+
+static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
+{
+    if (index >= llen || list[index] == NULL) {
+        return "???";
+    }
+    return list[index];
+}
+
+static const char *trb_name(XHCITRB *trb)
+{
+    return lookup_name(TRB_TYPE(*trb), TRBType_names,
+                       ARRAY_SIZE(TRBType_names));
+}
+#endif
+
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                          unsigned int epid);
 
@@ -487,8 +543,9 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
     }
     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);
+    DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x %s\n",
+            xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control,
+            trb_name(&ev_trb));
 
     addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
     cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
@@ -649,8 +706,9 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
         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);
+                "%016" PRIx64 " %08x %08x %s\n",
+                ring->dequeue, trb->parameter, trb->status, trb->control,
+                trb_name(trb));
 
         if ((trb->control & TRB_C) != ring->ccs) {
             return 0;
@@ -859,12 +917,17 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
     xferi = epctx->next_xfer;
     for (i = 0; i < TD_QUEUE; i++) {
         XHCITransfer *t = &epctx->transfers[xferi];
-        if (t->running) {
+        if (t->running_async) {
+            usb_cancel_packet(&t->packet);
+            t->running_async = 0;
             t->cancelled = 1;
-            /* libusb_cancel_transfer(t->usbxfer) */
             DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
             killed++;
         }
+        if (t->running_retry) {
+            t->running_retry = 0;
+            epctx->retry = NULL;
+        }
         if (t->backgrounded) {
             t->backgrounded = 0;
         }
@@ -885,9 +948,10 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
         xferi = epctx->next_bg;
         for (i = 0; i < BG_XFERS; i++) {
             XHCITransfer *t = &epctx->bg_transfers[xferi];
-            if (t->running) {
+            if (t->running_async) {
+                usb_cancel_packet(&t->packet);
+                t->running_async = 0;
                 t->cancelled = 1;
-                /* libusb_cancel_transfer(t->usbxfer); */
                 DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
                 killed++;
             }
@@ -1336,27 +1400,37 @@ static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
 }
 #endif
 
-static int xhci_setup_packet(XHCITransfer *xfer, XHCIPort *port, int ep)
+static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
 {
-    usb_packet_setup(&xfer->packet,
-                     xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT,
-                     xfer->xhci->slots[xfer->slotid-1].devaddr,
-                     ep & 0x7f);
+    USBEndpoint *ep;
+    int dir;
+
+    dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
+    ep = usb_ep_get(dev, dir, xfer->epid >> 1);
+    usb_packet_setup(&xfer->packet, dir, ep);
     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);
+            xfer->packet.pid, dev->addr, ep->nr);
     return 0;
 }
 
 static int xhci_complete_packet(XHCITransfer *xfer, int ret)
 {
     if (ret == USB_RET_ASYNC) {
-        xfer->running = 1;
+        xfer->running_async = 1;
+        xfer->running_retry = 0;
+        xfer->complete = 0;
+        xfer->cancelled = 0;
+        return 0;
+    } else if (ret == USB_RET_NAK) {
+        xfer->running_async = 0;
+        xfer->running_retry = 1;
         xfer->complete = 0;
         xfer->cancelled = 0;
         return 0;
     } else {
-        xfer->running = 0;
+        xfer->running_async = 0;
+        xfer->running_retry = 0;
         xfer->complete = 1;
     }
 
@@ -1385,6 +1459,14 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
     return 0;
 }
 
+static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
+{
+    if (!(port->portsc & PORTSC_PED)) {
+        return NULL;
+    }
+    return usb_find_device(&port->port, addr);
+}
+
 static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 {
     XHCITRB *trb_setup, *trb_status;
@@ -1444,7 +1526,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     xfer->data_length = wLength;
 
     port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = port->port.dev;
+    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
     if (!dev) {
         fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
                 xhci->slots[xfer->slotid-1].port);
@@ -1454,7 +1536,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     xfer->in_xfer = bmRequestType & USB_DIR_IN;
     xfer->iso_xfer = false;
 
-    xhci_setup_packet(xfer, port, 0);
+    xhci_setup_packet(xfer, dev);
     if (!xfer->in_xfer) {
         xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
     }
@@ -1463,7 +1545,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
                                     wValue, wIndex, wLength, xfer->data);
 
     xhci_complete_packet(xfer, ret);
-    if (!xfer->running) {
+    if (!xfer->running_async && !xfer->running_retry) {
         xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
     }
     return 0;
@@ -1476,12 +1558,8 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
     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;
@@ -1502,14 +1580,14 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
     }
 
     port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = port->port.dev;
+    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
     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);
+    xhci_setup_packet(xfer, dev);
 
     switch(epctx->type) {
     case ET_INTR_OUT:
@@ -1522,8 +1600,9 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
         FIXME();
         break;
     default:
-        fprintf(stderr, "xhci: unknown or unhandled EP type %d (ep %02x)\n",
-                epctx->type, ep);
+        fprintf(stderr, "xhci: unknown or unhandled EP "
+                "(type %d, in %d, ep %02x)\n",
+                epctx->type, xfer->in_xfer, xfer->epid);
         return -1;
     }
 
@@ -1533,7 +1612,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
     ret = usb_handle_packet(dev, &xfer->packet);
 
     xhci_complete_packet(xfer, ret);
-    if (!xfer->running) {
+    if (!xfer->running_async && !xfer->running_retry) {
         xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
     }
     return 0;
@@ -1604,6 +1683,25 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         return;
     }
 
+    if (epctx->retry) {
+        /* retry nak'ed transfer */
+        XHCITransfer *xfer = epctx->retry;
+        int result;
+
+        DPRINTF("xhci: retry nack'ed transfer ...\n");
+        assert(xfer->running_retry);
+        xhci_setup_packet(xfer, xfer->packet.ep->dev);
+        result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+        if (result == USB_RET_NAK) {
+            DPRINTF("xhci: ... xfer still nacked\n");
+            return;
+        }
+        DPRINTF("xhci: ... result %d\n", result);
+        xhci_complete_packet(xfer, result);
+        assert(!xfer->running_retry);
+        epctx->retry = NULL;
+    }
+
     if (epctx->state == EP_HALTED) {
         DPRINTF("xhci: ep halted, not running schedule\n");
         return;
@@ -1613,9 +1711,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
     while (1) {
         XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
-        if (xfer->running || xfer->backgrounded) {
-            DPRINTF("xhci: ep is busy\n");
+        if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
+            DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
+                    epctx->next_xfer, xfer->running_async,
+                    xfer->running_retry, xfer->backgrounded);
             break;
+        } else {
+            DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
         }
         length = xhci_ring_chain_length(xhci, &epctx->ring);
         if (length < 0) {
@@ -1658,10 +1760,19 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
             }
         }
 
+        if (epctx->state == EP_HALTED) {
+            DPRINTF("xhci: ep halted, stopping schedule\n");
+            break;
+        }
+        if (xfer->running_retry) {
+            DPRINTF("xhci: xfer nacked, stopping schedule\n");
+            epctx->retry = xfer;
+            break;
+        }
+
         /*
          * Qemu usb can't handle multiple in-flight xfers.
-         * Also xfers might be finished here already,
-         * possibly with an error.  Stop here for now.
+         * Stop here for now.
          */
         break;
     }
@@ -2346,9 +2457,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         /* 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);
-            }
+            usb_device_reset(xhci->ports[port].port.dev);
             portsc |= PORTSC_PRC | PORTSC_PED;
         }
         xhci->ports[port].portsc = portsc;
@@ -2633,6 +2742,26 @@ static void xhci_detach(USBPort *usbport)
     xhci_update_port(xhci, port, 1);
 }
 
+static void xhci_wakeup(USBPort *usbport)
+{
+    XHCIState *xhci = usbport->opaque;
+    XHCIPort *port = &xhci->ports[usbport->index];
+    int nr = port->port.index + 1;
+    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+    uint32_t pls;
+
+    pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
+    if (pls != 3) {
+        return;
+    }
+    port->portsc |= 0xf << PORTSC_PLS_SHIFT;
+    if (port->portsc & PORTSC_PLC) {
+        return;
+    }
+    port->portsc |= PORTSC_PLC;
+    xhci_event(xhci, &ev);
+}
+
 static void xhci_complete(USBPort *port, USBPacket *packet)
 {
     XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
@@ -2649,11 +2778,53 @@ static void xhci_child_detach(USBPort *port, USBDevice *child)
 static USBPortOps xhci_port_ops = {
     .attach   = xhci_attach,
     .detach   = xhci_detach,
+    .wakeup   = xhci_wakeup,
     .complete = xhci_complete,
     .child_detach = xhci_child_detach,
 };
 
+static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev)
+{
+    XHCISlot *slot;
+    int slotid;
+
+    for (slotid = 1; slotid <= MAXSLOTS; slotid++) {
+        slot = &xhci->slots[slotid-1];
+        if (slot->devaddr == dev->addr) {
+            return slotid;
+        }
+    }
+    return 0;
+}
+
+static int xhci_find_epid(USBEndpoint *ep)
+{
+    if (ep->nr == 0) {
+        return 1;
+    }
+    if (ep->pid == USB_TOKEN_IN) {
+        return ep->nr * 2 + 1;
+    } else {
+        return ep->nr * 2;
+    }
+}
+
+static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+    XHCIState *xhci = container_of(bus, XHCIState, bus);
+    int slotid;
+
+    DPRINTF("%s\n", __func__);
+    slotid = xhci_find_slotid(xhci, ep->dev);
+    if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
+        DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
+        return;
+    }
+    xhci_kick_ep(xhci, slotid, xhci_find_epid(ep));
+}
+
 static USBBusOps xhci_bus_ops = {
+    .wakeup_endpoint = xhci_wakeup_endpoint,
 };
 
 static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
@@ -2667,7 +2838,10 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
     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);
+                          &xhci_port_ops,
+                          USB_SPEED_MASK_LOW  |
+                          USB_SPEED_MASK_FULL |
+                          USB_SPEED_MASK_HIGH);
     }
     for (i = 0; i < MAXSLOTS; i++) {
         xhci->slots[i].enabled = 0;
@@ -2752,8 +2926,9 @@ static TypeInfo xhci_info = {
     .class_init    = xhci_class_init,
 };
 
-static void xhci_register(void)
+static void xhci_register_types(void)
 {
     type_register_static(&xhci_info);
 }
-device_init(xhci_register);
+
+type_init(xhci_register_types)
index c3ff5b7093e49f982be7011d575c2b4ad58ade73..e5b8f335dc388e7ba00fb50bf9e8b03cbc5f8357 100644 (file)
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -35,7 +35,8 @@ void usb_attach(USBPort *port)
     assert(dev->attached);
     assert(dev->state == USB_STATE_NOTATTACHED);
     port->ops->attach(port);
-    usb_send_msg(dev, USB_MSG_ATTACH);
+    dev->state = USB_STATE_ATTACHED;
+    usb_device_handle_attach(dev);
 }
 
 void usb_detach(USBPort *port)
@@ -45,24 +46,41 @@ void usb_detach(USBPort *port)
     assert(dev != NULL);
     assert(dev->state != USB_STATE_NOTATTACHED);
     port->ops->detach(port);
-    usb_send_msg(dev, USB_MSG_DETACH);
+    dev->state = USB_STATE_NOTATTACHED;
 }
 
-void usb_reset(USBPort *port)
+void usb_port_reset(USBPort *port)
 {
     USBDevice *dev = port->dev;
 
     assert(dev != NULL);
     usb_detach(port);
     usb_attach(port);
-    usb_send_msg(dev, USB_MSG_RESET);
+    usb_device_reset(dev);
 }
 
-void usb_wakeup(USBDevice *dev)
+void usb_device_reset(USBDevice *dev)
 {
+    if (dev == NULL || !dev->attached) {
+        return;
+    }
+    dev->remote_wakeup = 0;
+    dev->addr = 0;
+    dev->state = USB_STATE_DEFAULT;
+    usb_device_handle_reset(dev);
+}
+
+void usb_wakeup(USBEndpoint *ep)
+{
+    USBDevice *dev = ep->dev;
+    USBBus *bus = usb_bus_from_device(dev);
+
     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
         dev->port->ops->wakeup(dev->port);
     }
+    if (bus->ops->wakeup_endpoint) {
+        bus->ops->wakeup_endpoint(bus, ep);
+    }
 }
 
 /**********************/
@@ -128,8 +146,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
     int request, value, index;
     int ret = 0;
 
-    if (p->devep != 0)
-        return usb_device_handle_data(s, p);
+    assert(p->ep->nr == 0);
 
     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -175,8 +192,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
 
 static int do_token_out(USBDevice *s, USBPacket *p)
 {
-    if (p->devep != 0)
-        return usb_device_handle_data(s, p);
+    assert(p->ep->nr == 0);
 
     switch(s->setup_state) {
     case SETUP_STATE_ACK:
@@ -209,51 +225,6 @@ static int do_token_out(USBDevice *s, USBPacket *p)
     }
 }
 
-/*
- * Generic packet handler.
- * Called by the HC (host controller).
- *
- * Returns length of the transaction or one of the USB_RET_XXX codes.
- */
-int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
-{
-    switch(p->pid) {
-    case USB_MSG_ATTACH:
-        s->state = USB_STATE_ATTACHED;
-        usb_device_handle_attach(s);
-        return 0;
-
-    case USB_MSG_DETACH:
-        s->state = USB_STATE_NOTATTACHED;
-        return 0;
-
-    case USB_MSG_RESET:
-        s->remote_wakeup = 0;
-        s->addr = 0;
-        s->state = USB_STATE_DEFAULT;
-        usb_device_handle_reset(s);
-        return 0;
-    }
-
-    /* Rest of the PIDs must match our address */
-    if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
-        return USB_RET_NODEV;
-
-    switch (p->pid) {
-    case USB_TOKEN_SETUP:
-        return do_token_setup(s, p);
-
-    case USB_TOKEN_IN:
-        return do_token_in(s, p);
-
-    case USB_TOKEN_OUT:
-        return do_token_out(s, p);
-    default:
-        return USB_RET_STALL;
-    }
-}
-
 /* ctrl complete function for devices which use usb_generic_handle_packet and
    may return USB_RET_ASYNC from their handle_control callback. Device code
    which does this *must* call this function instead of the normal
@@ -301,17 +272,39 @@ int set_usb_string(uint8_t *buf, const char *str)
     return q - buf;
 }
 
-/* Send an internal message to a USB device.  */
-void usb_send_msg(USBDevice *dev, int msg)
+USBDevice *usb_find_device(USBPort *port, uint8_t addr)
 {
-    USBPacket p;
-    int ret;
+    USBDevice *dev = port->dev;
 
-    memset(&p, 0, sizeof(p));
-    p.pid = msg;
-    ret = usb_handle_packet(dev, &p);
-    /* This _must_ be synchronous */
-    assert(ret != USB_RET_ASYNC);
+    if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
+        return NULL;
+    }
+    if (dev->addr == addr) {
+        return dev;
+    }
+    return usb_device_find_device(dev, addr);
+}
+
+static int usb_process_one(USBPacket *p)
+{
+    USBDevice *dev = p->ep->dev;
+
+    if (p->ep->nr == 0) {
+        /* control pipe */
+        switch (p->pid) {
+        case USB_TOKEN_SETUP:
+            return do_token_setup(dev, p);
+        case USB_TOKEN_IN:
+            return do_token_in(dev, p);
+        case USB_TOKEN_OUT:
+            return do_token_out(dev, p);
+        default:
+            return USB_RET_STALL;
+        }
+    } else {
+        /* data pipe */
+        return usb_device_handle_data(dev, p);
+    }
 }
 
 /* Hand over a packet to a device for processing.  Return value
@@ -321,17 +314,27 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
 {
     int ret;
 
-    assert(p->owner == NULL);
-    ret = usb_device_handle_packet(dev, p);
-    if (ret == USB_RET_ASYNC) {
-        if (p->owner == NULL) {
-            p->owner = usb_ep_get(dev, p->pid, p->devep);
+    if (dev == NULL) {
+        return USB_RET_NODEV;
+    }
+    assert(dev == p->ep->dev);
+    assert(dev->state == USB_STATE_DEFAULT);
+    assert(p->state == USB_PACKET_SETUP);
+    assert(p->ep != NULL);
+
+    if (QTAILQ_EMPTY(&p->ep->queue)) {
+        ret = usb_process_one(p);
+        if (ret == USB_RET_ASYNC) {
+            usb_packet_set_state(p, USB_PACKET_ASYNC);
+            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
         } else {
-            /* We'll end up here when usb_handle_packet is called
-             * recursively due to a hub being in the chain.  Nothing
-             * to do.  Leave p->owner pointing to the device, not the
-             * hub. */;
+            p->result = ret;
+            usb_packet_set_state(p, USB_PACKET_COMPLETE);
         }
+    } else {
+        ret = USB_RET_ASYNC;
+        usb_packet_set_state(p, USB_PACKET_QUEUED);
+        QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
     }
     return ret;
 }
@@ -341,10 +344,28 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
    handle_packet. */
 void usb_packet_complete(USBDevice *dev, USBPacket *p)
 {
-    /* Note: p->owner != dev is possible in case dev is a hub */
-    assert(p->owner != NULL);
-    p->owner = NULL;
+    USBEndpoint *ep = p->ep;
+    int ret;
+
+    assert(p->state == USB_PACKET_ASYNC);
+    assert(QTAILQ_FIRST(&ep->queue) == p);
+    usb_packet_set_state(p, USB_PACKET_COMPLETE);
+    QTAILQ_REMOVE(&ep->queue, p, queue);
     dev->port->ops->complete(dev->port, p);
+
+    while (!QTAILQ_EMPTY(&ep->queue)) {
+        p = QTAILQ_FIRST(&ep->queue);
+        assert(p->state == USB_PACKET_QUEUED);
+        ret = usb_process_one(p);
+        if (ret == USB_RET_ASYNC) {
+            usb_packet_set_state(p, USB_PACKET_ASYNC);
+            break;
+        }
+        p->result = ret;
+        usb_packet_set_state(p, USB_PACKET_COMPLETE);
+        QTAILQ_REMOVE(&ep->queue, p, queue);
+        dev->port->ops->complete(dev->port, p);
+    }
 }
 
 /* Cancel an active packet.  The packed must have been deferred by
@@ -352,9 +373,13 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
    completed.  */
 void usb_cancel_packet(USBPacket * p)
 {
-    assert(p->owner != NULL);
-    usb_device_cancel_packet(p->owner->dev, p);
-    p->owner = NULL;
+    bool callback = (p->state == USB_PACKET_ASYNC);
+    assert(usb_packet_is_inflight(p));
+    usb_packet_set_state(p, USB_PACKET_CANCELED);
+    QTAILQ_REMOVE(&p->ep->queue, p, queue);
+    if (callback) {
+        usb_device_cancel_packet(p->ep->dev, p);
+    }
 }
 
 
@@ -363,13 +388,50 @@ void usb_packet_init(USBPacket *p)
     qemu_iovec_init(&p->iov, 1);
 }
 
-void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep)
+void usb_packet_set_state(USBPacket *p, USBPacketState state)
+{
+#ifdef DEBUG
+    static const char *name[] = {
+        [USB_PACKET_UNDEFINED] = "undef",
+        [USB_PACKET_SETUP]     = "setup",
+        [USB_PACKET_QUEUED]    = "queued",
+        [USB_PACKET_ASYNC]     = "async",
+        [USB_PACKET_COMPLETE]  = "complete",
+        [USB_PACKET_CANCELED]  = "canceled",
+    };
+    static const char *rets[] = {
+        [-USB_RET_NODEV]  = "NODEV",
+        [-USB_RET_NAK]    = "NAK",
+        [-USB_RET_STALL]  = "STALL",
+        [-USB_RET_BABBLE] = "BABBLE",
+        [-USB_RET_ASYNC]  = "ASYNC",
+    };
+    char add[16] = "";
+
+    if (state == USB_PACKET_COMPLETE) {
+        if (p->result < 0) {
+            snprintf(add, sizeof(add), " - %s", rets[-p->result]);
+        } else {
+            snprintf(add, sizeof(add), " - %d", p->result);
+        }
+    }
+    fprintf(stderr, "bus %s, port %s, dev %d, ep %d: packet %p: %s -> %s%s\n",
+            p->ep->dev->qdev.parent_bus->name,
+            p->ep->dev->port->path,
+            p->ep->dev->addr, p->ep->nr,
+            p, name[p->state], name[state], add);
+#endif
+    p->state = state;
+}
+
+void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
 {
+    assert(!usb_packet_is_inflight(p));
     p->pid = pid;
-    p->devaddr = addr;
-    p->devep = ep;
+    p->ep = ep;
     p->result = 0;
     qemu_iovec_reset(&p->iov);
+    usb_packet_set_state(p, USB_PACKET_SETUP);
 }
 
 void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
@@ -408,6 +470,7 @@ void usb_packet_skip(USBPacket *p, size_t bytes)
 
 void usb_packet_cleanup(USBPacket *p)
 {
+    assert(!usb_packet_is_inflight(p));
     qemu_iovec_destroy(&p->iov);
 }
 
@@ -415,16 +478,24 @@ void usb_ep_init(USBDevice *dev)
 {
     int ep;
 
+    dev->ep_ctl.nr = 0;
     dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
     dev->ep_ctl.ifnum = 0;
     dev->ep_ctl.dev = dev;
+    QTAILQ_INIT(&dev->ep_ctl.queue);
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
+        dev->ep_in[ep].nr = ep + 1;
+        dev->ep_out[ep].nr = ep + 1;
+        dev->ep_in[ep].pid = USB_TOKEN_IN;
+        dev->ep_out[ep].pid = USB_TOKEN_OUT;
         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;
+        QTAILQ_INIT(&dev->ep_in[ep].queue);
+        QTAILQ_INIT(&dev->ep_out[ep].queue);
     }
 }
 
@@ -472,7 +543,12 @@ void usb_ep_dump(USBDevice *dev)
 
 struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
 {
-    struct USBEndpoint *eps = pid == USB_TOKEN_IN ? dev->ep_in : dev->ep_out;
+    struct USBEndpoint *eps;
+
+    if (dev == NULL) {
+        return NULL;
+    }
+    eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
     if (ep == 0) {
         return &dev->ep_ctl;
     }
index 13e7c8ea7f26b5bb966a80f3ea50fa09ddf90612..4470ea890a2fa61e8861a9a2879b5d1d973b389a 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
 
-/* specific usb messages, also sent in the 'pid' parameter */
-#define USB_MSG_ATTACH   0x100
-#define USB_MSG_DETACH   0x101
-#define USB_MSG_RESET    0x102
-
 #define USB_RET_NODEV  (-1)
 #define USB_RET_NAK    (-2)
 #define USB_RET_STALL  (-3)
@@ -176,10 +171,13 @@ struct USBDescString {
 #define USB_MAX_INTERFACES 16
 
 struct USBEndpoint {
+    uint8_t nr;
+    uint8_t pid;
     uint8_t type;
     uint8_t ifnum;
     int max_packet_size;
     USBDevice *dev;
+    QTAILQ_HEAD(, USBPacket) queue;
 };
 
 /* definition of a USB device */
@@ -234,13 +232,10 @@ typedef struct USBDeviceClass {
     int (*init)(USBDevice *dev);
 
     /*
-     * Process USB packet.
-     * Called by the HC (Host Controller).
-     *
-     * Returns length of the transaction
-     * or one of the USB_RET_XXX codes.
+     * Walk (enabled) downstream ports, check for a matching device.
+     * Only hubs implement this.
      */
-    int (*handle_packet)(USBDevice *dev, USBPacket *p);
+    USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
 
     /*
      * Called when a packet is canceled.
@@ -297,8 +292,7 @@ typedef struct USBPortOps {
     void (*wakeup)(USBPort *port);
     /*
      * Note that port->dev will be different then the device from which
-     * the packet originated when a hub is involved, if you want the orginating
-     * device use p->owner
+     * the packet originated when a hub is involved.
      */
     void (*complete)(USBPort *port, USBPacket *p);
 } USBPortOps;
@@ -316,20 +310,30 @@ struct USBPort {
 
 typedef void USBCallback(USBPacket * packet, void *opaque);
 
+typedef enum USBPacketState {
+    USB_PACKET_UNDEFINED = 0,
+    USB_PACKET_SETUP,
+    USB_PACKET_QUEUED,
+    USB_PACKET_ASYNC,
+    USB_PACKET_COMPLETE,
+    USB_PACKET_CANCELED,
+} USBPacketState;
+
 /* Structure used to hold information about an active USB packet.  */
 struct USBPacket {
     /* Data fields for use by the driver.  */
     int pid;
-    uint8_t devaddr;
-    uint8_t devep;
+    USBEndpoint *ep;
     QEMUIOVector iov;
     int result; /* transfer length or USB_RET_* status code */
     /* Internal use by the USB layer.  */
-    USBEndpoint *owner;
+    USBPacketState state;
+    QTAILQ_ENTRY(USBPacket) queue;
 };
 
 void usb_packet_init(USBPacket *p);
-void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep);
+void usb_packet_set_state(USBPacket *p, USBPacketState state);
+void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep);
 void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
 int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
 void usb_packet_unmap(USBPacket *p);
@@ -337,6 +341,14 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
 void usb_packet_skip(USBPacket *p, size_t bytes);
 void usb_packet_cleanup(USBPacket *p);
 
+static inline bool usb_packet_is_inflight(USBPacket *p)
+{
+    return (p->state == USB_PACKET_QUEUED ||
+            p->state == USB_PACKET_ASYNC);
+}
+
+USBDevice *usb_find_device(USBPort *port, uint8_t addr);
+
 int usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
@@ -354,12 +366,11 @@ 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);
-void usb_wakeup(USBDevice *dev);
-int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
+void usb_port_reset(USBPort *port);
+void usb_device_reset(USBDevice *dev);
+void usb_wakeup(USBEndpoint *ep);
 void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
 int set_usb_string(uint8_t *buf, const char *str);
-void usb_send_msg(USBDevice *dev, int msg);
 
 /* usb-linux.c */
 USBDevice *usb_host_device_open(const char *devname);
@@ -414,6 +425,7 @@ struct USBBus {
 struct USBBusOps {
     int (*register_companion)(USBBus *bus, USBPort *ports[],
                               uint32_t portcount, uint32_t firstport);
+    void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep);
 };
 
 void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
@@ -451,7 +463,7 @@ extern const VMStateDescription vmstate_usb_device;
     .offset     = vmstate_offset_value(_state, _field, USBDevice),   \
 }
 
-int usb_device_handle_packet(USBDevice *dev, USBPacket *p);
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr);
 
 void usb_device_cancel_packet(USBDevice *dev, USBPacket *p);
 
index c4105e977be45fad4782ea1f6abdf9a85e5f147a..ae53a8b37bc6b1540275c0e7a3dd9c13d5e44e4b 100644 (file)
@@ -154,11 +154,11 @@ static TypeInfo pci_realview_info = {
     .class_init    = pci_realview_class_init,
 };
 
-static void versatile_pci_register_devices(void)
+static void versatile_pci_register_types(void)
 {
     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)
+type_init(versatile_pci_register_types)
index 6e28e78f44d49fb2f44347fea1e5afe163cee3d4..1903db6435a6f70c2d8d06b455ce7bb52df4ac8e 100644 (file)
@@ -198,8 +198,8 @@ static void versatile_init(ram_addr_t ram_size,
 
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
-    qdev_init_nofail(sysctl);
     qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
+    qdev_init_nofail(sysctl);
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
     cpu_pic = arm_pic_init_cpu(env);
@@ -382,9 +382,9 @@ static TypeInfo vpb_sic_info = {
     .class_init    = vpb_sic_class_init,
 };
 
-static void versatilepb_register_devices(void)
+static void versatilepb_register_types(void)
 {
     type_register_static(&vpb_sic_info);
 }
 
-device_init(versatilepb_register_devices)
+type_init(versatilepb_register_types)
index 64fab4574ced68399e2049f80a5085bc6af8e46d..43f47a65cee105f4213974563e99de81b53c25f1 100644 (file)
@@ -123,8 +123,8 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* 0x10000000 System registers */
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_init_nofail(sysctl);
     qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
     sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
 
     /* 0x10001000 SP810 system control */
index 8d3ff0d47b3aa128886ed41ea2eb4843a4a903ab..4bcc4db62fe5b992d76f098ccb457267f0f64ec4 100644 (file)
@@ -85,8 +85,9 @@ static TypeInfo vga_info = {
     .class_init    = vga_class_initfn,
 };
 
-static void vga_register(void)
+static void vga_register_types(void)
 {
     type_register_static(&vga_info);
 }
-device_init(vga_register)
+
+type_init(vga_register_types)
index 974a7a9d6f217e98a5052139d78c8c57cab39748..465b643d21c98296b5c0c321f72c63cf1db574d1 100644 (file)
@@ -96,8 +96,9 @@ static TypeInfo vga_info = {
     .class_init    = vga_class_init,
 };
 
-static void vga_register(void)
+static void vga_register_types(void)
 {
     type_register_static(&vga_info);
 }
-device_init(vga_register);
+
+type_init(vga_register_types)
index d87c4f9f5bb0c215b0ce9f194872aeef28b4d6a1..c1029dbd9b5b07283941b735f05e8775a73e95d0 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1777,10 +1777,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!(s->cr[VGA_CRTC_MODE] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
+        update = full_update;
         page0 = addr;
         page1 = addr + bwidth - 1;
-        update = memory_region_get_dirty(&s->vram, page0, page1,
-                                         DIRTY_MEMORY_VGA);
+        update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
+                                          DIRTY_MEMORY_VGA);
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
         if (update) {
index 4f2c3e4379181e82f89dd9d2c2d6d66ab3afabb5..cffee3d4706ececdbf37afc8d49508d8908ceb25 100644 (file)
@@ -149,12 +149,6 @@ static TypeInfo virtconsole_info = {
     .class_init    = virtconsole_class_init,
 };
 
-static void virtconsole_register(void)
-{
-    type_register_static(&virtconsole_info);
-}
-device_init(virtconsole_register)
-
 static Property virtserialport_properties[] = {
     DEFINE_PROP_CHR("chardev", VirtConsole, chr),
     DEFINE_PROP_END_OF_LIST(),
@@ -179,8 +173,10 @@ static TypeInfo virtserialport_info = {
     .class_init    = virtserialport_class_init,
 };
 
-static void virtserialport_register(void)
+static void virtconsole_register_types(void)
 {
+    type_register_static(&virtconsole_info);
     type_register_static(&virtserialport_info);
 }
-device_init(virtserialport_register)
+
+type_init(virtconsole_register_types)
index 93fff5478238291bccd3d514ecfe5188fc43fe5b..907b52a25d8e4bb4d03aba5baeac5d86e8e58b1c 100644 (file)
@@ -930,7 +930,7 @@ static TypeInfo virtio_balloon_info = {
     .class_init    = virtio_balloon_class_init,
 };
 
-static void virtio_pci_register_devices(void)
+static void virtio_pci_register_types(void)
 {
     type_register_static(&virtio_blk_info);
     type_register_static(&virtio_net_info);
@@ -938,4 +938,4 @@ static void virtio_pci_register_devices(void)
     type_register_static(&virtio_balloon_info);
 }
 
-device_init(virtio_pci_register_devices)
+type_init(virtio_pci_register_types)
index 61176299a3892cf0cef342e305cd39fa7d556331..e22940ecb29a246b60c4a9f12966edf9146e030c 100644 (file)
@@ -949,9 +949,9 @@ static TypeInfo virtio_serial_port_type_info = {
     .class_init = virtio_serial_port_class_init,
 };
 
-static void virtio_serial_register_devices(void)
+static void virtio_serial_register_types(void)
 {
     type_register_static(&virtio_serial_port_type_info);
 }
 
-device_init(virtio_serial_register_devices);
+type_init(virtio_serial_register_types)
index fda4f89a767baea89eabf963c2ba64bd1a6242d6..6338efa1c396d1b33c41333f0dba466a0b57ce61 100644 (file)
@@ -294,8 +294,9 @@ static TypeInfo vmmouse_info = {
     .class_init    = vmmouse_class_initfn,
 };
 
-static void vmmouse_dev_register(void)
+static void vmmouse_register_types(void)
 {
     type_register_static(&vmmouse_info);
 }
-device_init(vmmouse_dev_register)
+
+type_init(vmmouse_register_types)
index a2c45e1950f596a5f076af468adf2b7be20280b7..9373be9775c2a14f0f187f00c05563948ebc5ca8 100644 (file)
@@ -159,8 +159,9 @@ static TypeInfo vmport_info = {
     .class_init    = vmport_class_initfn,
 };
 
-static void vmport_dev_register(void)
+static void vmport_register_types(void)
 {
     type_register_static(&vmport_info);
 }
-device_init(vmport_dev_register)
+
+type_init(vmport_register_types)
index 3f3eb21d02cb8c5dfca123cf454c17d419d1502e..f8afa3c367a1fe3990d78a6cdf9a9cf2187d903d 100644 (file)
@@ -1223,8 +1223,9 @@ static TypeInfo vmsvga_info = {
     .class_init    = vmsvga_class_init,
 };
 
-static void vmsvga_register(void)
+static void vmsvga_register_types(void)
 {
     type_register_static(&vmsvga_info);
 }
-device_init(vmsvga_register);
+
+type_init(vmsvga_register_types)
index aa0954f487d659af15ee8cbac6e9a0cd94899e16..fbab0bbc07838a9642e41fc140f705be08d59b5e 100644 (file)
@@ -366,13 +366,6 @@ static TypeInfo via_ac97_info = {
     .class_init    = via_ac97_class_init,
 };
 
-static void vt82c686b_ac97_register(void)
-{
-    type_register_static(&via_ac97_info);
-}
-
-device_init(vt82c686b_ac97_register);
-
 static int vt82c686b_mc97_initfn(PCIDevice *dev)
 {
     VT686MC97State *s = DO_UPCAST(VT686MC97State, dev, dev);
@@ -414,13 +407,6 @@ static TypeInfo via_mc97_info = {
     .class_init    = via_mc97_class_init,
 };
 
-static void vt82c686b_mc97_register(void)
-{
-    type_register_static(&via_mc97_info);
-}
-
-device_init(vt82c686b_mc97_register);
-
 /* vt82c686 pm init */
 static int vt82c686b_pm_initfn(PCIDevice *dev)
 {
@@ -497,13 +483,6 @@ static TypeInfo via_pm_info = {
     .class_init    = via_pm_class_init,
 };
 
-static void vt82c686b_pm_register(void)
-{
-    type_register_static(&via_pm_info);
-}
-
-device_init(vt82c686b_pm_register);
-
 static const VMStateDescription vmstate_via = {
     .name = "vt82c686b",
     .version_id = 1,
@@ -571,8 +550,12 @@ static TypeInfo via_info = {
     .class_init    = via_class_init,
 };
 
-static void vt82c686b_register(void)
+static void vt82c686b_register_types(void)
 {
+    type_register_static(&via_ac97_info);
+    type_register_static(&via_mc97_info);
+    type_register_static(&via_pm_info);
     type_register_static(&via_info);
 }
-device_init(vt82c686b_register);
+
+type_init(vt82c686b_register_types)
index 41325f095592ecac6d0f0a9103290c1ca413b7f3..15c69db9321746927237c953f4758eb376ee3142 100644 (file)
@@ -448,10 +448,10 @@ static TypeInfo i6300esb_info = {
     .class_init    = i6300esb_class_init,
 };
 
-static void i6300esb_register_devices(void)
+static void i6300esb_register_types(void)
 {
     watchdog_add_model(&model);
     type_register_static(&i6300esb_info);
 }
 
-device_init(i6300esb_register_devices);
+type_init(i6300esb_register_types)
index 8faa2316c91e6bbe2567d958a1897b67dd72602c..7f6c21d8095040797c8d1391efd7dcf239333070 100644 (file)
@@ -136,10 +136,10 @@ static TypeInfo wdt_ib700_info = {
     .class_init    = wdt_ib700_class_init,
 };
 
-static void wdt_ib700_register_devices(void)
+static void wdt_ib700_register_types(void)
 {
     watchdog_add_model(&model);
     type_register_static(&wdt_ib700_info);
 }
 
-device_init(wdt_ib700_register_devices);
+type_init(wdt_ib700_register_types)
index 18afa4c1ac097f6d760996cff776446fbe90ebdc..11bcec34106ee99145d09ffcdf9c4c1ada61484f 100644 (file)
@@ -708,9 +708,9 @@ static TypeInfo wm8750_info = {
     .class_init    = wm8750_class_init,
 };
 
-static void wm8750_register_devices(void)
+static void wm8750_register_types(void)
 {
     type_register_static(&wm8750_info);
 }
 
-device_init(wm8750_register_devices)
+type_init(wm8750_register_types)
index e7571022e4e92dece5b2bcb28635b9f61ef05247..5a7c4cc97be4be060b36251c97b670962c9118ab 100644 (file)
@@ -396,9 +396,9 @@ static TypeInfo xen_platform_info = {
     .class_init    = xen_platform_class_init,
 };
 
-static void xen_platform_register(void)
+static void xen_platform_register_types(void)
 {
     type_register_static(&xen_platform_info);
 }
 
-device_init(xen_platform_register);
+type_init(xen_platform_register_types)
index d395b1cc2da8920f2ad8dd85e446d8793ecec38a..dd4bdc46f5fcb4d986b7d6f1f32af75a6a9ff36c 100644 (file)
@@ -425,9 +425,9 @@ static TypeInfo xgmac_enet_info = {
     .class_init    = xgmac_enet_class_init,
 };
 
-static void xgmac_enet_register(void)
+static void xgmac_enet_register_types(void)
 {
     type_register_static(&xgmac_enet_info);
 }
 
-device_init(xgmac_enet_register)
+type_init(xgmac_enet_register_types)
index e8a53123f99639e00b2e00cb32e073ec4bc0150a..85dfcbf2b9ad47663202e748a1dc2a175a89551b 100644 (file)
@@ -508,9 +508,9 @@ static TypeInfo axidma_info = {
     .class_init    = axidma_class_init,
 };
 
-static void xilinx_axidma_register(void)
+static void xilinx_axidma_register_types(void)
 {
     type_register_static(&axidma_info);
 }
 
-device_init(xilinx_axidma_register)
+type_init(xilinx_axidma_register_types)
index 1ce2db4510449833281888887fab69c330b508c7..7526273b4d400caba4eccaaa2f9fb336cd4a21cf 100644 (file)
@@ -894,9 +894,10 @@ static TypeInfo xilinx_enet_info = {
     .instance_size = sizeof(struct XilinxAXIEnet),
     .class_init    = xilinx_enet_class_init,
 };
-static void xilinx_enet_register(void)
+
+static void xilinx_enet_register_types(void)
 {
     type_register_static(&xilinx_enet_info);
 }
 
-device_init(xilinx_enet_register)
+type_init(xilinx_enet_register_types)
index 499feef4888767c85bb94184114d21db60f7672d..857b33d17245da54cc3a87c8713f30c1510c36a2 100644 (file)
@@ -249,9 +249,9 @@ static TypeInfo xilinx_ethlite_info = {
     .class_init    = xilinx_ethlite_class_init,
 };
 
-static void xilinx_ethlite_register(void)
+static void xilinx_ethlite_register_types(void)
 {
     type_register_static(&xilinx_ethlite_info);
 }
 
-device_init(xilinx_ethlite_register)
+type_init(xilinx_ethlite_register_types)
index 73eed6dc5f68cffa79f36c6467e30e04bb768107..553f8488f6632e5e188b44205732f89e98865953 100644 (file)
@@ -182,9 +182,9 @@ static TypeInfo xilinx_intc_info = {
     .class_init    = xilinx_intc_class_init,
 };
 
-static void xilinx_intc_register(void)
+static void xilinx_intc_register_types(void)
 {
     type_register_static(&xilinx_intc_info);
 }
 
-device_init(xilinx_intc_register)
+type_init(xilinx_intc_register_types)
index c8236d2e2a8bd28f78d83fc1943a54cc152b42b4..3ab2f2bb032e9ef81e0859e7445c29317ee3e6d0 100644 (file)
@@ -241,9 +241,9 @@ static TypeInfo xilinx_timer_info = {
     .class_init    = xilinx_timer_class_init,
 };
 
-static void xilinx_timer_register(void)
+static void xilinx_timer_register_types(void)
 {
     type_register_static(&xilinx_timer_info);
 }
 
-device_init(xilinx_timer_register)
+type_init(xilinx_timer_register_types)
index 1c2b9087b44b645ee539af0c72932db4ba2788b7..aa0170db4949d428b919bbf732fafa69f071ef3b 100644 (file)
@@ -225,9 +225,9 @@ static TypeInfo xilinx_uartlite_info = {
     .class_init    = xilinx_uartlite_class_init,
 };
 
-static void xilinx_uart_register(void)
+static void xilinx_uart_register_types(void)
 {
     type_register_static(&xilinx_uartlite_info);
 }
 
-device_init(xilinx_uart_register)
+type_init(xilinx_uart_register_types)
index 07e4fc101832f0b5870f73fcabc89f7d3501c225..319624f212052b297ed874be6ead8050e6ed7ad6 100644 (file)
@@ -203,12 +203,12 @@ static TypeInfo xio3130_downstream_info = {
     .class_init    = xio3130_downstream_class_init,
 };
 
-static void xio3130_downstream_register(void)
+static void xio3130_downstream_register_types(void)
 {
     type_register_static(&xio3130_downstream_info);
 }
 
-device_init(xio3130_downstream_register);
+type_init(xio3130_downstream_register_types)
 
 /*
  * Local variables:
index 7887c92fcc12548f2501b8a96a0dae2f310a59e7..34a99bba081247e3d89026ac84026153500b56b0 100644 (file)
@@ -177,12 +177,12 @@ static TypeInfo xio3130_upstream_info = {
     .class_init    = xio3130_upstream_class_init,
 };
 
-static void xio3130_upstream_register(void)
+static void xio3130_upstream_register_types(void)
 {
     type_register_static(&xio3130_upstream_info);
 }
 
-device_init(xio3130_upstream_register);
+type_init(xio3130_upstream_register_types)
 
 
 /*
index 055df9b4e2580fbb5b2c879cde9238b2e61a1ce0..72838ec440805ed0c19164ac0d5925325a7f05cf 100644 (file)
@@ -243,11 +243,12 @@ static TypeInfo scoop_sysbus_info = {
     .class_init    = scoop_sysbus_class_init,
 };
 
-static void scoop_register(void)
+static void scoop_register_types(void)
 {
     type_register_static(&scoop_sysbus_info);
 }
-device_init(scoop_register);
+
+type_init(scoop_register_types)
 
 /* Write the bootloader parameters memory area.  */
 
index 9d0251d56ade44768d48870b1ba541bf88ea8f19..69cc2abc66c5da9c78bed6ac3ab04d60faf8ca53 100644 (file)
@@ -55,6 +55,9 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * #define TYPE_MY_DEVICE "my-device"
  *
+ * // No new virtual functions: we can reuse the typedef for the
+ * // superclass.
+ * typedef DeviceClass MyDeviceClass;
  * typedef struct MyDevice
  * {
  *     DeviceState parent;
@@ -68,12 +71,12 @@ typedef struct InterfaceInfo InterfaceInfo;
  *     .instance_size = sizeof(MyDevice),
  * };
  *
- * static void my_device_module_init(void)
+ * static void my_device_register_types(void)
  * {
  *     type_register_static(&my_device_info);
  * }
  *
- * device_init(my_device_module_init);
+ * type_init(my_device_register_types)
  *   </programlisting>
  * </example>
  *
@@ -88,8 +91,21 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * Using object_new(), a new #Object derivative will be instantiated.  You can
  * cast an #Object to a subclass (or base-class) type using
- * object_dynamic_cast().  You typically want to define a macro wrapper around
- * object_dynamic_cast_assert() to make it easier to convert to a specific type.
+ * object_dynamic_cast().  You typically want to define macro wrappers around
+ * OBJECT_CHECK() and OBJECT_CLASS_CHECK() to make it easier to convert to a
+ * specific type:
+ *
+ * <example>
+ *   <title>Typecasting macros</title>
+ *   <programlisting>
+ *    #define MY_DEVICE_GET_CLASS(obj) \
+ *       OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
+ *    #define MY_DEVICE_CLASS(klass) \
+ *       OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
+ *    #define MY_DEVICE(obj) \
+ *       OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
+ *   </programlisting>
+ * </example>
  *
  * # Class Initialization #
  *
@@ -108,7 +124,61 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * Once all of the parent classes have been initialized, #TypeInfo::class_init
  * is called to let the class being instantiated provide default initialize for
- * it's virtual functions.
+ * it's virtual functions.  Here is how the above example might be modified
+ * to introduce an overridden virtual function:
+ *
+ * <example>
+ *   <title>Overriding a virtual function</title>
+ *   <programlisting>
+ * #include "qdev.h"
+ *
+ * void my_device_class_init(ObjectClass *klass, void *class_data)
+ * {
+ *     DeviceClass *dc = DEVICE_CLASS(klass);
+ *     dc->reset = my_device_reset;
+ * }
+ *
+ * static TypeInfo my_device_info = {
+ *     .name = TYPE_MY_DEVICE,
+ *     .parent = TYPE_DEVICE,
+ *     .instance_size = sizeof(MyDevice),
+ *     .class_init = my_device_class_init,
+ * };
+ *   </programlisting>
+ * </example>
+ *
+ * Introducing new virtual functions requires a class to define its own
+ * struct and to add a .class_size member to the TypeInfo.  Each function
+ * will also have a wrapper to call it easily:
+ *
+ * <example>
+ *   <title>Defining an abstract class</title>
+ *   <programlisting>
+ * #include "qdev.h"
+ *
+ * typedef struct MyDeviceClass
+ * {
+ *     DeviceClass parent;
+ *
+ *     void (*frobnicate) (MyDevice *obj);
+ * } MyDeviceClass;
+ *
+ * static TypeInfo my_device_info = {
+ *     .name = TYPE_MY_DEVICE,
+ *     .parent = TYPE_DEVICE,
+ *     .instance_size = sizeof(MyDevice),
+ *     .abstract = true, // or set a default in my_device_class_init
+ *     .class_size = sizeof(MyDeviceClass),
+ * };
+ *
+ * void my_device_frobnicate(MyDevice *obj)
+ * {
+ *     MyDeviceClass *klass = MY_DEVICE_GET_CLASS(obj);
+ *
+ *     klass->frobnicate(obj);
+ * }
+ *   </programlisting>
+ * </example>
  *
  * # Interfaces #
  *
@@ -258,6 +328,16 @@ struct TypeInfo
 #define OBJECT(obj) \
     ((Object *)(obj))
 
+/**
+ * OBJECT_CLASS:
+ * @class: A derivative of #ObjectClas.
+ *
+ * Converts a class to an #ObjectClass.  Since all objects are #Objects,
+ * this function will always succeed.
+ */
+#define OBJECT_CLASS(class) \
+    ((ObjectClass *)(class))
+
 /**
  * OBJECT_CHECK:
  * @type: The C type to use for the return value.
@@ -272,7 +352,7 @@ struct TypeInfo
  * generated.
  */
 #define OBJECT_CHECK(type, obj, name) \
-    ((type *)object_dynamic_cast_assert((Object *)(obj), (name)))
+    ((type *)object_dynamic_cast_assert(OBJECT(obj), (name)))
 
 /**
  * OBJECT_CLASS_CHECK:
@@ -280,11 +360,12 @@ struct TypeInfo
  * @obj: A derivative of @type to cast.
  * @name: the QOM typename of @class.
  *
- * A type safe version of @object_check_class.  This macro is typically wrapped
- * by each type to perform type safe casts of a class to a specific class type.
+ * A type safe version of @object_class_dynamic_cast_assert.  This macro is
+ * typically wrapped by each type to perform type safe casts of a class to a
+ * specific class type.
  */
 #define OBJECT_CLASS_CHECK(class, obj, name) \
-    ((class *)object_class_dynamic_cast_assert((ObjectClass *)(obj), (name)))
+    ((class *)object_class_dynamic_cast_assert(OBJECT_CLASS(obj), (name)))
 
 /**
  * OBJECT_GET_CLASS:
@@ -299,9 +380,6 @@ struct TypeInfo
 #define OBJECT_GET_CLASS(class, obj, name) \
     OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name)
 
-#define OBJECT_CLASS(class) \
-    ((ObjectClass *)(class))
-
 /**
  * InterfaceClass:
  * @parent_class: the base class
@@ -543,6 +621,100 @@ void object_unparent(Object *obj);
 void object_property_get(Object *obj, struct Visitor *v, const char *name,
                          struct Error **errp);
 
+/**
+ * object_property_set_str:
+ * @value: the value to be written to the property
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes a string value to a property.
+ */
+void object_property_set_str(Object *obj, const char *value,
+                             const char *name, struct Error **errp);
+
+/**
+ * object_property_get_str:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, converted to a C string, or NULL if
+ * an error occurs (including when the property value is not a string).
+ * The caller should free the string.
+ */
+char *object_property_get_str(Object *obj, const char *name,
+                              struct Error **errp);
+
+/**
+ * object_property_set_link:
+ * @value: the value to be written to the property
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes an object's canonical path to a property.
+ */
+void object_property_set_link(Object *obj, Object *value,
+                              const char *name, struct Error **errp);
+
+/**
+ * object_property_get_link:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, resolved from a path to an Object,
+ * or NULL if an error occurs (including when the property value is not a
+ * string or not a valid object path).
+ */
+Object *object_property_get_link(Object *obj, const char *name,
+                                 struct Error **errp);
+
+/**
+ * object_property_set_bool:
+ * @value: the value to be written to the property
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes a bool value to a property.
+ */
+void object_property_set_bool(Object *obj, bool value,
+                              const char *name, struct Error **errp);
+
+/**
+ * object_property_get_bool:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, converted to a boolean, or NULL if
+ * an error occurs (including when the property value is not a bool).
+ */
+bool object_property_get_bool(Object *obj, const char *name,
+                              struct Error **errp);
+
+/**
+ * object_property_set_int:
+ * @value: the value to be written to the property
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes an integer value to a property.
+ */
+void object_property_set_int(Object *obj, int64_t value,
+                             const char *name, struct Error **errp);
+
+/**
+ * object_property_get_int:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, converted to an integer, or NULL if
+ * an error occurs (including when the property value is not an integer).
+ */
+int64_t object_property_get_int(Object *obj, const char *name,
+                                struct Error **errp);
+
 /**
  * object_property_set:
  * @obj: the object
@@ -601,13 +773,34 @@ gchar *object_get_canonical_path(Object *obj);
  * specifying objects 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.
+ * only one match is found.  If more than one match is found, a flag is
+ * returned to indicate that the match was ambiguous.
  *
  * Returns: The matched object or NULL on path lookup failure.
  */
 Object *object_resolve_path(const char *path, bool *ambiguous);
 
+/**
+ * object_resolve_path_type:
+ * @path: the path to resolve
+ * @typename: the type to look for.
+ * @ambiguous: returns true if the path resolution failed because of an
+ *   ambiguous match
+ *
+ * This is similar to object_resolve_path.  However, when looking for a
+ * partial path only matches that implement the given type are considered.
+ * This restricts the search and avoids spuriously flagging matches as
+ * ambiguous.
+ *
+ * For both partial and absolute paths, the return value goes through
+ * a dynamic cast to @typename.  This is important if either the link,
+ * or the typename itself are of interface types.
+ *
+ * Returns: The matched object or NULL on path lookup failure.
+ */
+Object *object_resolve_path_type(const char *path, const char *typename,
+                                 bool *ambiguous);
+
 /**
  * object_property_add_child:
  * @obj: the object to add a property to
diff --git a/include/qemu/qom-qobject.h b/include/qemu/qom-qobject.h
new file mode 100644 (file)
index 0000000..f9dff12
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * QEMU Object Model - QObject wrappers
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_QOM_QOBJECT_H
+#define QEMU_QOM_QOBJECT_H
+
+#include "qemu/object.h"
+
+/*
+ * object_property_get_qobject:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: the value of the property, converted to QObject, or NULL if
+ * an error occurs.
+ */
+struct QObject *object_property_get_qobject(Object *obj, const char *name,
+                                            struct Error **errp);
+
+/**
+ * object_property_set_qobject:
+ * @obj: the object
+ * @ret: The value that will be written to the property.
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Writes a property to a object.
+ */
+void object_property_set_qobject(Object *obj, struct QObject *qobj,
+                                 const char *name, struct Error **errp);
+
+#endif
index a1455690443ce674a175398bcceb0d6805ef4ca8..c6a896a7397026397a2900ca537b25361eb0b840 100644 (file)
@@ -15,8 +15,6 @@ QEMU_OBJS_LIB=$(addsuffix .lo,$(basename $(QEMU_OBJS)))
 
 QEMU_CFLAGS+=-I../
 
-QEMU_CFLAGS+=$(GLIB_CFLAGS)
-
 libcacard.lib-y=$(addsuffix .lo,$(basename $(libcacard-y)))
 
 vscclient: $(libcacard-y) $(QEMU_OBJS) vscclient.o
index 5e77d8a2f4bf56d9e553b296fc24e43de3d0b153..22816e20f93fba991ba56d93c5b43b49af12e07c 100644 (file)
--- a/memory.c
+++ b/memory.c
@@ -1609,23 +1609,31 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
             ml->printed = false;
             QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
         }
-        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): alias %s @%s "
-                   TARGET_FMT_plx "-" TARGET_FMT_plx "\n",
+        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
+                   " (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx
+                   "-" TARGET_FMT_plx "\n",
                    base + mr->addr,
                    base + mr->addr
                    + (target_phys_addr_t)int128_get64(mr->size) - 1,
                    mr->priority,
+                   mr->readable ? 'R' : '-',
+                   !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
+                                                                      : '-',
                    mr->name,
                    mr->alias->name,
                    mr->alias_offset,
                    mr->alias_offset
                    + (target_phys_addr_t)int128_get64(mr->size) - 1);
     } else {
-        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): %s\n",
+        mon_printf(f,
+                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n",
                    base + mr->addr,
                    base + mr->addr
                    + (target_phys_addr_t)int128_get64(mr->size) - 1,
                    mr->priority,
+                   mr->readable ? 'R' : '-',
+                   !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
+                                                                      : '-',
                    mr->name);
     }
 
index ef667304c44f825c2f76d16b0a04656a7e9c0dec..c4ccd5716640070649ed5638107273e9933cb06e 100644 (file)
--- a/module.h
+++ b/module.h
@@ -22,16 +22,16 @@ static void __attribute__((constructor)) do_qemu_init_ ## function(void) {  \
 
 typedef enum {
     MODULE_INIT_BLOCK,
-    MODULE_INIT_DEVICE,
     MODULE_INIT_MACHINE,
     MODULE_INIT_QAPI,
+    MODULE_INIT_QOM,
     MODULE_INIT_MAX
 } module_init_type;
 
 #define block_init(function) module_init(function, MODULE_INIT_BLOCK)
-#define device_init(function) module_init(function, MODULE_INIT_DEVICE)
 #define machine_init(function) module_init(function, MODULE_INIT_MACHINE)
 #define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
+#define type_init(function) module_init(function, MODULE_INIT_QOM)
 
 void register_module_init(void (*fn)(void), module_init_type type);
 
index 8b69a9eea573e9ef6b06f8e65b3fe181b085c2d7..c5e9cad35ec1ce7599eee9414aada42878e34bdf 100644 (file)
@@ -255,6 +255,7 @@ typedef enum LostTickPolicy {
     LOST_TICK_DELAY,
     LOST_TICK_MERGE,
     LOST_TICK_SLEW,
+    LOST_TICK_MAX
 } LostTickPolicy;
 
 void tcg_exec_init(unsigned long tb_size);
@@ -334,6 +335,8 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
 void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
                             size_t skip);
 
+bool buffer_is_zero(const void *buf, size_t len);
+
 void qemu_progress_init(int enabled, float min_skip);
 void qemu_progress_end(void);
 void qemu_progress_print(float delta, int max);
index 95bf5e52026f73c854af24c26143d0fcd1bf7383..12f5c275351b137e459c0fa81253f5c9c0a20be8 100644 (file)
@@ -118,6 +118,32 @@ static QemuOptsList qemu_drive_opts = {
     },
 };
 
+static QemuOptsList qemu_iscsi_opts = {
+    .name = "iscsi",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
+    .desc = {
+        {
+            .name = "user",
+            .type = QEMU_OPT_STRING,
+            .help = "username for CHAP authentication to target",
+        },{
+            .name = "password",
+            .type = QEMU_OPT_STRING,
+            .help = "password for CHAP authentication to target",
+        },{
+            .name = "header-digest",
+            .type = QEMU_OPT_STRING,
+            .help = "HeaderDigest setting. "
+                    "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
+        },{
+            .name = "initiator-name",
+            .type = QEMU_OPT_STRING,
+            .help = "Initiator iqn name to use when connecting",
+        },
+        { /* end of list */ }
+    },
+};
+
 static QemuOptsList qemu_chardev_opts = {
     .name = "chardev",
     .implied_opt_name = "backend",
@@ -584,6 +610,7 @@ static QemuOptsList *vm_config_groups[32] = {
     &qemu_option_rom_opts,
     &qemu_machine_opts,
     &qemu_boot_opts,
+    &qemu_iscsi_opts,
     NULL,
 };
 
index 11f4166995e23e3310b21cdbdcba22c44080cae0..83b2ad523708f9b4817d547f846fd4413bfeae6a 100644 (file)
@@ -730,6 +730,57 @@ export LIBISCSI_CHAP_PASSWORD=<password>
 iscsi://<host>/<target-iqn-name>/<lun>
 @end example
 
+Various session related parameters can be set via special options, either
+in a configuration file provided via '-readconfig' or directly on the
+command line.
+
+@example
+Setting a specific initiator name to use when logging in to the target
+-iscsi initiator-name=iqn.qemu.test:my-initiator
+@end example
+
+@example
+Controlling which type of header digest to negotiate with the target
+-iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
+@end example
+
+These can also be set via a configuration file
+@example
+[iscsi]
+  user = "CHAP username"
+  password = "CHAP password"
+  initiator-name = "iqn.qemu.test:my-initiator"
+  # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
+  header-digest = "CRC32C"
+@end example
+
+
+Setting the target name allows different options for different targets
+@example
+[iscsi "iqn.target.name"]
+  user = "CHAP username"
+  password = "CHAP password"
+  initiator-name = "iqn.qemu.test:my-initiator"
+  # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
+  header-digest = "CRC32C"
+@end example
+
+
+Howto use a configuration file to set iSCSI configuration options:
+@example
+cat >iscsi.conf <<EOF
+[iscsi]
+  user = "me"
+  password = "my password"
+  initiator-name = "iqn.qemu.test:my-initiator"
+  header-digest = "CRC32C"
+EOF
+
+qemu-system-i386 -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
+    -readconfig iscsi.conf
+@end example
+
+
 Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
 @example
 This example shows how to set up an iSCSI target with one CDROM and one DISK
@@ -744,7 +795,8 @@ tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
     -b /IMAGES/cd.iso --device-type=cd
 tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
 
-qemu-system-i386 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
+qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
+    -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
     -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
 @end example
 
index 01cc0d35ad7d964196d0cbdc9a08ca0c13197cf0..c4bcf41e15707cd6c839f21494452cf09bef2989 100644 (file)
@@ -514,40 +514,6 @@ static int img_commit(int argc, char **argv)
     return 0;
 }
 
-/*
- * Checks whether the sector is not a zero sector.
- *
- * Attention! The len must be a multiple of 4 * sizeof(long) due to
- * restriction of optimizations in this function.
- */
-static int is_not_zero(const uint8_t *sector, int len)
-{
-    /*
-     * Use long as the biggest available internal data type that fits into the
-     * CPU register and unroll the loop to smooth out the effect of memory
-     * latency.
-     */
-
-    int i;
-    long d0, d1, d2, d3;
-    const long * const data = (const long *) sector;
-
-    len /= sizeof(long);
-
-    for(i = 0; i < len; i += 4) {
-        d0 = data[i + 0];
-        d1 = data[i + 1];
-        d2 = data[i + 2];
-        d3 = data[i + 3];
-
-        if (d0 || d1 || d2 || d3) {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
 /*
  * Returns true iff the first sector pointed to by 'buf' contains at least
  * a non-NUL byte.
@@ -557,20 +523,22 @@ static int is_not_zero(const uint8_t *sector, int len)
  */
 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
 {
-    int v, i;
+    bool is_zero;
+    int i;
 
     if (n <= 0) {
         *pnum = 0;
         return 0;
     }
-    v = is_not_zero(buf, 512);
+    is_zero = buffer_is_zero(buf, 512);
     for(i = 1; i < n; i++) {
         buf += 512;
-        if (v != is_not_zero(buf, 512))
+        if (is_zero != buffer_is_zero(buf, 512)) {
             break;
+        }
     }
     *pnum = i;
-    return v;
+    return !is_zero;
 }
 
 /*
@@ -955,7 +923,7 @@ static int img_convert(int argc, char **argv)
             if (n < cluster_sectors) {
                 memset(buf + n * 512, 0, cluster_size - n * 512);
             }
-            if (is_not_zero(buf, cluster_size)) {
+            if (!buffer_is_zero(buf, cluster_size)) {
                 ret = bdrv_write_compressed(out_bs, sector_num, buf,
                                             cluster_sectors);
                 if (ret != 0) {
index d4a5fcbcbccf7c15fdcd31db9fcd262dd9b7b130..0249be4e71e7d36b5d6474c3aa06bf4c5e7cfb79 100644 (file)
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -218,6 +218,51 @@ static int do_pwrite(char *buf, int64_t offset, int count, int *total)
     return 1;
 }
 
+typedef struct {
+    int64_t offset;
+    int count;
+    int *total;
+    int ret;
+    bool done;
+} CoWriteZeroes;
+
+static void coroutine_fn co_write_zeroes_entry(void *opaque)
+{
+    CoWriteZeroes *data = opaque;
+
+    data->ret = bdrv_co_write_zeroes(bs, data->offset / BDRV_SECTOR_SIZE,
+                                     data->count / BDRV_SECTOR_SIZE);
+    data->done = true;
+    if (data->ret < 0) {
+        *data->total = data->ret;
+        return;
+    }
+
+    *data->total = data->count;
+}
+
+static int do_co_write_zeroes(int64_t offset, int count, int *total)
+{
+    Coroutine *co;
+    CoWriteZeroes data = {
+        .offset = offset,
+        .count  = count,
+        .total  = total,
+        .done   = false,
+    };
+
+    co = qemu_coroutine_create(co_write_zeroes_entry);
+    qemu_coroutine_enter(co, &data);
+    while (!data.done) {
+        qemu_aio_wait();
+    }
+    if (data.ret < 0) {
+        return data.ret;
+    } else {
+        return 1;
+    }
+}
+
 static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
 {
     *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
@@ -643,6 +688,7 @@ static void write_help(void)
 " -P, -- use different pattern to fill file\n"
 " -C, -- report statistics in a machine parsable format\n"
 " -q, -- quiet mode, do not show I/O statistics\n"
+" -z, -- write zeroes using bdrv_co_write_zeroes\n"
 "\n");
 }
 
@@ -654,7 +700,7 @@ static const cmdinfo_t write_cmd = {
     .cfunc      = write_f,
     .argmin     = 2,
     .argmax     = -1,
-    .args       = "[-abCpq] [-P pattern ] off len",
+    .args       = "[-bCpqz] [-P pattern ] off len",
     .oneline    = "writes a number of bytes at a specified offset",
     .help       = write_help,
 };
@@ -662,16 +708,16 @@ static const cmdinfo_t write_cmd = {
 static int write_f(int argc, char **argv)
 {
     struct timeval t1, t2;
-    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
+    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
     int c, cnt;
-    char *buf;
+    char *buf = NULL;
     int64_t offset;
     int count;
     /* Some compilers get confused and warn if this is not initialized.  */
     int total = 0;
     int pattern = 0xcd;
 
-    while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
+    while ((c = getopt(argc, argv, "bCpP:qz")) != EOF) {
         switch (c) {
         case 'b':
             bflag = 1;
@@ -683,6 +729,7 @@ static int write_f(int argc, char **argv)
             pflag = 1;
             break;
         case 'P':
+            Pflag = 1;
             pattern = parse_pattern(optarg);
             if (pattern < 0) {
                 return 0;
@@ -691,6 +738,9 @@ static int write_f(int argc, char **argv)
         case 'q':
             qflag = 1;
             break;
+        case 'z':
+            zflag = 1;
+            break;
         default:
             return command_usage(&write_cmd);
         }
@@ -700,8 +750,13 @@ static int write_f(int argc, char **argv)
         return command_usage(&write_cmd);
     }
 
-    if (bflag && pflag) {
-        printf("-b and -p cannot be specified at the same time\n");
+    if (bflag + pflag + zflag > 1) {
+        printf("-b, -p, or -z cannot be specified at the same time\n");
+        return 0;
+    }
+
+    if (zflag && Pflag) {
+        printf("-z and -P cannot be specified at the same time\n");
         return 0;
     }
 
@@ -732,13 +787,17 @@ static int write_f(int argc, char **argv)
         }
     }
 
-    buf = qemu_io_alloc(count, pattern);
+    if (!zflag) {
+        buf = qemu_io_alloc(count, pattern);
+    }
 
     gettimeofday(&t1, NULL);
     if (pflag) {
         cnt = do_pwrite(buf, offset, count, &total);
     } else if (bflag) {
         cnt = do_save_vmstate(buf, offset, count, &total);
+    } else if (zflag) {
+        cnt = do_co_write_zeroes(offset, count, &total);
     } else {
         cnt = do_write(buf, offset, count, &total);
     }
@@ -758,7 +817,9 @@ static int write_f(int argc, char **argv)
     print_report("wrote", &t2, offset, count, total, cnt, Cflag);
 
 out:
-    qemu_io_free(buf);
+    if (!zflag) {
+        qemu_io_free(buf);
+    }
 
     return 0;
 }
index 4ad1fc72fdf1de026c27ea71c2ac3fd8ff0bd41a..b12999649f7892305969ff006e83d9dbfbabf68f 100644 (file)
@@ -557,7 +557,7 @@ DEFHEADING()
 DEFHEADING(File system options:)
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
-    "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
+    "-fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}]\n"
     " [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
@@ -577,12 +577,13 @@ Specifies the export path for the file system device. Files under
 this path will be available to the 9p client on the guest.
 @item security_model=@var{security_model}
 Specifies the security model to be used for this export path.
-Supported security models are "passthrough", "mapped" and "none".
+Supported security models are "passthrough", "mapped-xattr", "mapped-file" and "none".
 In "passthrough" security model, files are stored using the same
 credentials as they are created on the guest. This requires qemu
-to run as root. In "mapped" security model, some of the file
+to run as root. In "mapped-xattr" security model, some of the file
 attributes like uid, gid, mode bits and link target are stored as
-file attributes. Directories exported by this security model cannot
+file attributes. For "mapped-file" these attributes are stored in the
+hidden .virtfs_metadata directory. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory
@@ -622,7 +623,7 @@ DEFHEADING()
 DEFHEADING(Virtual File system pass-through options:)
 
 DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
-    "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
+    "-virtfs local,path=path,mount_tag=tag,security_model=[mapped-xattr|mapped-file|passthrough|none]\n"
     "        [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
     QEMU_ARCH_ALL)
 
@@ -643,12 +644,13 @@ Specifies the export path for the file system device. Files under
 this path will be available to the 9p client on the guest.
 @item security_model=@var{security_model}
 Specifies the security model to be used for this export path.
-Supported security models are "passthrough", "mapped" and "none".
+Supported security models are "passthrough", "mapped-xattr", "mapped-file" and "none".
 In "passthrough" security model, files are stored using the same
 credentials as they are created on the guest. This requires qemu
-to run as root. In "mapped" security model, some of the file
+to run as root. In "mapped-xattr" security model, some of the file
 attributes like uid, gid, mode bits and link target are stored as
-file attributes. Directories exported by this security model cannot
+file attributes. For "mapped-file" these attributes are stored in the
+hidden .virtfs_metadata directory. Directories exported by this security model cannot
 interact with other unix tools. "none" security model is same as
 passthrough except the sever won't report failures if it fails to
 set file attributes like ownership. Security model is mandatory only
@@ -1096,6 +1098,19 @@ This can be really helpful to save bandwidth when playing videos. Disabling
 adaptive encodings allows to restore the original static behavior of encodings
 like Tight.
 
+@item share=[allow-exclusive|force-shared|ignore]
+
+Set display sharing policy.  'allow-exclusive' allows clients to ask
+for exclusive access.  As suggested by the rfb spec this is
+implemented by dropping other connections.  Connecting multiple
+clients in parallel requires all clients asking for a shared session
+(vncviewer: -shared switch).  This is the default.  'force-shared'
+disables exclusive client access.  Useful for shared desktop sessions,
+where you don't want someone forgetting specify -shared disconnect
+everybody else.  'ignore' completely ignores the shared flag and
+allows everybody connect unconditionally.  Doesn't conform to the rfb
+spec but is traditional qemu behavior.
+
 @end table
 ETEXI
 
@@ -1830,24 +1845,32 @@ Syntax for specifying iSCSI LUNs is
 
 Example (without authentication):
 @example
-qemu -cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \
---drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
+qemu -iscsi initiator-name=iqn.2001-04.com.example:my-initiator \
+-cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \
+-drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
 @end example
 
 Example (CHAP username/password via URL):
 @example
-qemu --drive file=iscsi://user%password@@192.0.2.1/iqn.2001-04.com.example/1
+qemu -drive file=iscsi://user%password@@192.0.2.1/iqn.2001-04.com.example/1
 @end example
 
 Example (CHAP username/password via environment variables):
 @example
 LIBISCSI_CHAP_USERNAME="user" \
 LIBISCSI_CHAP_PASSWORD="password" \
-qemu --drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
+qemu -drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
 @end example
 
 iSCSI support is an optional feature of QEMU and only available when
 compiled and linked against libiscsi.
+ETEXI
+DEF("iscsi", HAS_ARG, QEMU_OPTION_iscsi,
+    "-iscsi [user=user][,password=password]\n"
+    "       [,header-digest=CRC32C|CR32C-NONE|NONE-CRC32C|NONE\n"
+    "       [,initiator-name=iqn]\n"
+    "                iSCSI session parameters\n", QEMU_ARCH_ALL)
+STEXI
 
 @item NBD
 QEMU supports NBD (Network Block Devices) both using TCP protocol as well
index fe9b93186352e77a90bc8a2a64cedd037eca16da..3524c8b785a4cb4a29798464143eb7fe629cb704 100644 (file)
@@ -215,8 +215,6 @@ static unsigned __stdcall win32_start_routine(void *arg)
     if (data->mode == QEMU_THREAD_DETACHED) {
         g_free(data);
         data = NULL;
-    } else {
-        InitializeCriticalSection(&data->cs);
     }
     TlsSetValue(qemu_thread_tls_index, data);
     qemu_thread_exit(start_routine(thread_arg));
@@ -227,6 +225,7 @@ void qemu_thread_exit(void *arg)
 {
     QemuThreadData *data = TlsGetValue(qemu_thread_tls_index);
     if (data) {
+        assert(data->mode != QEMU_THREAD_DETACHED);
         data->ret = arg;
         EnterCriticalSection(&data->cs);
         data->exited = true;
@@ -258,6 +257,7 @@ void *qemu_thread_join(QemuThread *thread)
         CloseHandle(handle);
     }
     ret = data->ret;
+    assert(data->mode != QEMU_THREAD_DETACHED);
     DeleteCriticalSection(&data->cs);
     g_free(data);
     return ret;
@@ -288,6 +288,10 @@ void qemu_thread_create(QemuThread *thread,
     data->mode = mode;
     data->exited = false;
 
+    if (data->mode != QEMU_THREAD_DETACHED) {
+        InitializeCriticalSection(&data->cs);
+    }
+
     hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
                                       data, 0, &thread->tid);
     if (!hThread) {
@@ -314,6 +318,7 @@ HANDLE qemu_thread_get_handle(QemuThread *thread)
         return NULL;
     }
 
+    assert(data->mode != QEMU_THREAD_DETACHED);
     EnterCriticalSection(&data->cs);
     if (!data->exited) {
         handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
index 3d179c87ea83ad78a17d115e012507d85eb528f4..f55d435d11e0e95b826780a5905f65ed01624847 100644 (file)
--- a/qerror.c
+++ b/qerror.c
@@ -47,6 +47,10 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_ADD_CLIENT_FAILED,
         .desc      = "Could not add client",
     },
+    {
+        .error_fmt = QERR_AMBIGUOUS_PATH,
+        .desc      = "Path '%(path)' does not uniquely identify a %(object)"
+    },
     {
         .error_fmt = QERR_BAD_BUS_FOR_DEVICE,
         .desc      = "Device '%(device)' can't go on a %(bad_bus_type) bus",
@@ -568,6 +572,14 @@ void qerror_report_err(Error *err)
     }
 }
 
+void assert_no_error(Error *err)
+{
+    if (err) {
+        qerror_report_err(err);
+        abort();
+    }
+}
+
 /**
  * qobject_to_qerror(): Convert a QObject into a QError
  */
index 8c36ddb7e100c44d11ce43fd4adf98f44ad21f1a..e26c63598d907815a3ed2328efbc4d87656984c8 100644 (file)
--- a/qerror.h
+++ b/qerror.h
@@ -41,6 +41,7 @@ void qerror_print(QError *qerror);
 void qerror_report_internal(const char *file, int linenr, const char *func,
                             const char *fmt, ...) GCC_FMT_ATTR(4, 5);
 void qerror_report_err(Error *err);
+void assert_no_error(Error *err);
 QString *qerror_format(const char *fmt, QDict *error);
 #define qerror_report(fmt, ...) \
     qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
@@ -54,6 +55,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_ADD_CLIENT_FAILED \
     "{ 'class': 'AddClientFailed', 'data': {} }"
 
+#define QERR_AMBIGUOUS_PATH \
+    "{ 'class': 'AmbiguousPath', 'data': { 'path': %s } }"
+
 #define QERR_BAD_BUS_FOR_DEVICE \
     "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
 
diff --git a/qmp.c b/qmp.c
index 45052cc9781f5d852e8ac78261d31518bd4ea5e2..1f64844095b6c40f732f88220bcadde1ef8471e7 100644 (file)
--- a/qmp.c
+++ b/qmp.c
@@ -21,9 +21,8 @@
 #include "kvm.h"
 #include "arch_init.h"
 #include "hw/qdev.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
 #include "blockdev.h"
+#include "qemu/qom-qobject.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -198,7 +197,6 @@ int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
     const char *property = qdict_get_str(qdict, "property");
     QObject *value = qdict_get(qdict, "value");
     Error *local_err = NULL;
-    QmpInputVisitor *mi;
     Object *obj;
 
     obj = object_resolve_path(path, NULL);
@@ -207,10 +205,7 @@ int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
         goto out;
     }
 
-    mi = qmp_input_visitor_new(value);
-    object_property_set(obj, qmp_input_get_visitor(mi), property, &local_err);
-
-    qmp_input_visitor_cleanup(mi);
+    object_property_set_qobject(obj, value, property, &local_err);
 
 out:
     if (local_err) {
@@ -227,7 +222,6 @@ int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
     const char *path = qdict_get_str(qdict, "path");
     const char *property = qdict_get_str(qdict, "property");
     Error *local_err = NULL;
-    QmpOutputVisitor *mo;
     Object *obj;
 
     obj = object_resolve_path(path, NULL);
@@ -236,13 +230,7 @@ int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
         goto out;
     }
 
-    mo = qmp_output_visitor_new();
-    object_property_get(obj, qmp_output_get_visitor(mo), property, &local_err);
-    if (!local_err) {
-        *ret = qmp_output_get_qobject(mo);
-    }
-
-    qmp_output_visitor_cleanup(mo);
+    *ret = object_property_get_qobject(obj, property, &local_err);
 
 out:
     if (local_err) {
index f33f0be8c9db6ddbf232f0e3cb206e82c3dbe4f6..885a2631bbe0e91604c36c45f1bcf40c9e5dd17d 100644 (file)
@@ -1 +1 @@
-qom-y = object.o container.o
+qom-y = object.o container.o qom-qobject.o
index 946cbff90f4d456551276601e07d55c90924207c..f107208867081d1d929838f56fbd0f352218702f 100644 (file)
@@ -19,9 +19,9 @@ static TypeInfo container_info = {
     .parent        = TYPE_OBJECT,
 };
 
-static void container_init(void)
+static void container_register_types(void)
 {
     type_register_static(&container_info);
 }
 
-device_init(container_init);
+type_init(container_register_types)
index 426194484961eb663d23267fa3832070143bc21d..0cbd9bb0040a81f2bb3d62c5cca3907728f76180 100644 (file)
 #include "qemu/object.h"
 #include "qemu-common.h"
 #include "qapi/qapi-visit-core.h"
-#include "hw/qdev.h"
-// FIXME remove above
+
+/* TODO: replace QObject with a simpler visitor to avoid a dependency
+ * of the QOM core on QObject?  */
+#include "qemu/qom-qobject.h"
+#include "qobject.h"
+#include "qbool.h"
+#include "qint.h"
+#include "qstring.h"
 
 #define MAX_INTERFACES 32
 
@@ -63,6 +69,8 @@ typedef struct Interface
 
 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
 
+static Type type_interface;
+
 static GHashTable *type_table_get(void)
 {
     static GHashTable *type_table;
@@ -368,11 +376,9 @@ void object_delete(Object *obj)
     g_free(obj);
 }
 
-static bool object_is_type(Object *obj, const char *typename)
+static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
 {
-    TypeImpl *target_type = type_get_by_name(typename);
-    TypeImpl *type = obj->class->type;
-    GSList *i;
+    assert(target_type);
 
     /* Check if typename is a direct ancestor of type */
     while (type) {
@@ -383,24 +389,45 @@ static bool object_is_type(Object *obj, const char *typename)
         type = type_get_parent(type);
     }
 
-    /* Check if obj has an interface of typename */
-    for (i = obj->interfaces; i; i = i->next) {
-        Interface *iface = i->data;
-
-        if (object_is_type(OBJECT(iface), typename)) {
-            return true;
-        }
-    }
-
     return false;
 }
 
+static bool object_is_type(Object *obj, TypeImpl *target_type)
+{
+    return !target_type || type_is_ancestor(obj->class->type, target_type);
+}
+
 Object *object_dynamic_cast(Object *obj, const char *typename)
 {
+    TypeImpl *target_type = type_get_by_name(typename);
     GSList *i;
 
-    /* Check if typename is a direct ancestor */
-    if (object_is_type(obj, typename)) {
+    /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
+     * we want to go back from interfaces to the parent.
+    */
+    if (target_type && object_is_type(obj, target_type)) {
+        return obj;
+    }
+
+    /* Check if obj is an interface and its containing object is a direct
+     * ancestor of typename.  In principle we could do this test at the very
+     * beginning of object_dynamic_cast, avoiding a second call to
+     * object_is_type.  However, casting between interfaces is relatively
+     * rare, and object_is_type(obj, type_interface) would fail almost always.
+     *
+     * Perhaps we could add a magic value to the object header for increased
+     * (run-time) type safety and to speed up tests like this one.  If we ever
+     * do that we can revisit the order here.
+     */
+    if (object_is_type(obj, type_interface)) {
+        assert(!obj->interfaces);
+        obj = INTERFACE(obj)->obj;
+        if (object_is_type(obj, target_type)) {
+            return obj;
+        }
+    }
+
+    if (!target_type) {
         return obj;
     }
 
@@ -408,26 +435,16 @@ Object *object_dynamic_cast(Object *obj, const char *typename)
     for (i = obj->interfaces; i; i = i->next) {
         Interface *iface = i->data;
 
-        if (object_is_type(OBJECT(iface), typename)) {
+        if (object_is_type(OBJECT(iface), target_type)) {
             return OBJECT(iface);
         }
     }
 
-    /* Check if obj is an interface and its containing object is a direct
-     * ancestor of typename */
-    if (object_is_type(obj, TYPE_INTERFACE)) {
-        Interface *iface = INTERFACE(obj);
-
-        if (object_is_type(iface->obj, typename)) {
-            return iface->obj;
-        }
-    }
-
     return NULL;
 }
 
 
-static void register_interface(void)
+static void register_types(void)
 {
     static TypeInfo interface_info = {
         .name = TYPE_INTERFACE,
@@ -435,10 +452,10 @@ static void register_interface(void)
         .abstract = true,
     };
 
-    type_register_static(&interface_info);
+    type_interface = type_register_static(&interface_info);
 }
 
-device_init(register_interface);
+type_init(register_types)
 
 Object *object_dynamic_cast_assert(Object *obj, const char *typename)
 {
@@ -648,6 +665,123 @@ void object_property_set(Object *obj, Visitor *v, const char *name,
     }
 }
 
+void object_property_set_str(Object *obj, const char *value,
+                             const char *name, Error **errp)
+{
+    QString *qstr = qstring_from_str(value);
+    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
+
+    QDECREF(qstr);
+}
+
+char *object_property_get_str(Object *obj, const char *name,
+                              Error **errp)
+{
+    QObject *ret = object_property_get_qobject(obj, name, errp);
+    QString *qstring;
+    char *retval;
+
+    if (!ret) {
+        return NULL;
+    }
+    qstring = qobject_to_qstring(ret);
+    if (!qstring) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
+        retval = NULL;
+    } else {
+        retval = g_strdup(qstring_get_str(qstring));
+    }
+
+    QDECREF(qstring);
+    return retval;
+}
+
+void object_property_set_link(Object *obj, Object *value,
+                              const char *name, Error **errp)
+{
+    object_property_set_str(obj, object_get_canonical_path(value),
+                            name, errp);
+}
+
+Object *object_property_get_link(Object *obj, const char *name,
+                                 Error **errp)
+{
+    char *str = object_property_get_str(obj, name, errp);
+    Object *target = NULL;
+
+    if (str && *str) {
+        target = object_resolve_path(str, NULL);
+        if (!target) {
+            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
+        }
+    }
+
+    g_free(str);
+    return target;
+}
+
+void object_property_set_bool(Object *obj, bool value,
+                              const char *name, Error **errp)
+{
+    QBool *qbool = qbool_from_int(value);
+    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
+
+    QDECREF(qbool);
+}
+
+bool object_property_get_bool(Object *obj, const char *name,
+                              Error **errp)
+{
+    QObject *ret = object_property_get_qobject(obj, name, errp);
+    QBool *qbool;
+    bool retval;
+
+    if (!ret) {
+        return false;
+    }
+    qbool = qobject_to_qbool(ret);
+    if (!qbool) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
+        retval = false;
+    } else {
+        retval = qbool_get_int(qbool);
+    }
+
+    QDECREF(qbool);
+    return retval;
+}
+
+void object_property_set_int(Object *obj, int64_t value,
+                             const char *name, Error **errp)
+{
+    QInt *qint = qint_from_int(value);
+    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
+
+    QDECREF(qint);
+}
+
+int64_t object_property_get_int(Object *obj, const char *name,
+                                Error **errp)
+{
+    QObject *ret = object_property_get_qobject(obj, name, errp);
+    QInt *qint;
+    int64_t retval;
+
+    if (!ret) {
+        return -1;
+    }
+    qint = qobject_to_qint(ret);
+    if (!qint) {
+        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
+        retval = -1;
+    } else {
+        retval = qint_get_int(qint);
+    }
+
+    QDECREF(qint);
+    return retval;
+}
+
 const char *object_property_get_type(Object *obj, const char *name, Error **errp)
 {
     ObjectProperty *prop = object_property_find(obj, name);
@@ -695,6 +829,12 @@ void object_property_add_child(Object *obj, const char *name,
 {
     gchar *type;
 
+    /* Registering an interface object in the composition tree will mightily
+     * confuse object_get_canonical_path (which, on the other hand, knows how
+     * to get the canonical path of an interface object).
+     */
+    assert(!object_is_type(obj, type_interface));
+
     type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
 
     object_property_add(obj, name, type, object_get_child_property,
@@ -730,6 +870,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
     bool ambiguous = false;
     const char *type;
     char *path;
+    gchar *target_type;
 
     type = object_property_get_type(obj, name, NULL);
 
@@ -737,31 +878,30 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
 
     if (*child) {
         object_unref(*child);
+        *child = NULL;
     }
 
     if (strcmp(path, "") != 0) {
         Object *target;
 
-        target = object_resolve_path(path, &ambiguous);
-        if (target) {
-            gchar *target_type;
-
-            target_type = g_strdup(&type[5]);
-            target_type[strlen(target_type) - 2] = 0;
+        /* Go from link<FOO> to FOO.  */
+        target_type = g_strndup(&type[5], strlen(type) - 6);
+        target = object_resolve_path_type(path, target_type, &ambiguous);
 
-            if (object_dynamic_cast(target, target_type)) {
-                object_ref(target);
-                *child = target;
+        if (ambiguous) {
+            error_set(errp, QERR_AMBIGUOUS_PATH, path);
+        } else if (target) {
+            object_ref(target);
+            *child = target;
+        } else {
+            target = object_resolve_path(path, &ambiguous);
+            if (target || ambiguous) {
+                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
             } else {
-                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
+                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
             }
-
-            g_free(target_type);
-        } else {
-            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
         }
-    } else {
-        *child = NULL;
+        g_free(target_type);
     }
 
     g_free(path);
@@ -788,6 +928,10 @@ gchar *object_get_canonical_path(Object *obj)
     Object *root = object_get_root();
     char *newpath = NULL, *path = NULL;
 
+    if (object_is_type(obj, type_interface)) {
+        obj = INTERFACE(obj)->obj;
+    }
+
     while (obj != root) {
         ObjectProperty *prop = NULL;
 
@@ -823,17 +967,18 @@ gchar *object_get_canonical_path(Object *obj)
 
 static Object *object_resolve_abs_path(Object *parent,
                                           gchar **parts,
+                                          const char *typename,
                                           int index)
 {
     ObjectProperty *prop;
     Object *child;
 
     if (parts[index] == NULL) {
-        return parent;
+        return object_dynamic_cast(parent, typename);
     }
 
     if (strcmp(parts[index], "") == 0) {
-        return object_resolve_abs_path(parent, parts, index + 1);
+        return object_resolve_abs_path(parent, parts, typename, index + 1);
     }
 
     prop = object_property_find(parent, parts[index]);
@@ -855,17 +1000,18 @@ static Object *object_resolve_abs_path(Object *parent,
         return NULL;
     }
 
-    return object_resolve_abs_path(child, parts, index + 1);
+    return object_resolve_abs_path(child, parts, typename, index + 1);
 }
 
 static Object *object_resolve_partial_path(Object *parent,
                                               gchar **parts,
+                                              const char *typename,
                                               bool *ambiguous)
 {
     Object *obj;
     ObjectProperty *prop;
 
-    obj = object_resolve_abs_path(parent, parts, 0);
+    obj = object_resolve_abs_path(parent, parts, typename, 0);
 
     QTAILQ_FOREACH(prop, &parent->properties, node) {
         Object *found;
@@ -874,7 +1020,8 @@ static Object *object_resolve_partial_path(Object *parent,
             continue;
         }
 
-        found = object_resolve_partial_path(prop->opaque, parts, ambiguous);
+        found = object_resolve_partial_path(prop->opaque, parts,
+                                            typename, ambiguous);
         if (found) {
             if (obj) {
                 if (ambiguous) {
@@ -893,7 +1040,8 @@ static Object *object_resolve_partial_path(Object *parent,
     return obj;
 }
 
-Object *object_resolve_path(const char *path, bool *ambiguous)
+Object *object_resolve_path_type(const char *path, const char *typename,
+                                 bool *ambiguous)
 {
     bool partial_path = true;
     Object *obj;
@@ -913,9 +1061,10 @@ Object *object_resolve_path(const char *path, bool *ambiguous)
         if (ambiguous) {
             *ambiguous = false;
         }
-        obj = object_resolve_partial_path(object_get_root(), parts, ambiguous);
+        obj = object_resolve_partial_path(object_get_root(), parts,
+                                          typename, ambiguous);
     } else {
-        obj = object_resolve_abs_path(object_get_root(), parts, 1);
+        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
     }
 
     g_strfreev(parts);
@@ -923,14 +1072,19 @@ Object *object_resolve_path(const char *path, bool *ambiguous)
     return obj;
 }
 
+Object *object_resolve_path(const char *path, bool *ambiguous)
+{
+    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
+}
+
 typedef struct StringProperty
 {
     char *(*get)(Object *, Error **);
     void (*set)(Object *, const char *, Error **);
 } StringProperty;
 
-static void object_property_get_str(Object *obj, Visitor *v, void *opaque,
-                                    const char *name, Error **errp)
+static void property_get_str(Object *obj, Visitor *v, void *opaque,
+                             const char *name, Error **errp)
 {
     StringProperty *prop = opaque;
     char *value;
@@ -942,8 +1096,8 @@ static void object_property_get_str(Object *obj, Visitor *v, void *opaque,
     }
 }
 
-static void object_property_set_str(Object *obj, Visitor *v, void *opaque,
-                                  const char *name, Error **errp)
+static void property_set_str(Object *obj, Visitor *v, void *opaque,
+                             const char *name, Error **errp)
 {
     StringProperty *prop = opaque;
     char *value;
@@ -959,8 +1113,8 @@ static void object_property_set_str(Object *obj, Visitor *v, void *opaque,
     g_free(value);
 }
 
-static void object_property_release_str(Object *obj, const char *name,
-                                      void *opaque)
+static void property_release_str(Object *obj, const char *name,
+                                 void *opaque)
 {
     StringProperty *prop = opaque;
     g_free(prop);
@@ -977,8 +1131,8 @@ void object_property_add_str(Object *obj, const char *name,
     prop->set = set;
 
     object_property_add(obj, name, "string",
-                        get ? object_property_get_str : NULL,
-                        set ? object_property_set_str : NULL,
-                        object_property_release_str,
+                        get ? property_get_str : NULL,
+                        set ? property_set_str : NULL,
+                        property_release_str,
                         prop, errp);
 }
diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c
new file mode 100644 (file)
index 0000000..0689914
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * QEMU Object Model - QObject wrappers
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "qemu/object.h"
+#include "qemu/qom-qobject.h"
+#include "qapi/qapi-visit-core.h"
+#include "qapi/qmp-input-visitor.h"
+#include "qapi/qmp-output-visitor.h"
+
+void object_property_set_qobject(Object *obj, QObject *value,
+                                 const char *name, Error **errp)
+{
+    QmpInputVisitor *mi;
+    mi = qmp_input_visitor_new(value);
+    object_property_set(obj, qmp_input_get_visitor(mi), name, errp);
+
+    qmp_input_visitor_cleanup(mi);
+}
+
+QObject *object_property_get_qobject(Object *obj, const char *name,
+                                     Error **errp)
+{
+    QObject *ret = NULL;
+    Error *local_err = NULL;
+    QmpOutputVisitor *mo;
+
+    mo = qmp_output_visitor_new();
+    object_property_get(obj, qmp_output_get_visitor(mo), name, &local_err);
+    if (!local_err) {
+        ret = qmp_output_get_qobject(mo);
+    }
+    error_propagate(errp, local_err);
+    qmp_output_visitor_cleanup(mo);
+    return ret;
+}
index 4b43994dbcb2e8884e119de0254b5d9e848a36e8..5dbf21da9d7dc82e3d2325a731ad4d603cce0a08 100644 (file)
@@ -262,6 +262,11 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
 #endif
   if(ip->ip_off & IP_OFFMASK) goto end_error;    /* Only reply to fragment 0 */
 
+  /* Do not reply to source-only IPs */
+  if ((ip->ip_src.s_addr & htonl(~(0xf << 28))) == 0) {
+      goto end_error;
+  }
+
   shlen=ip->ip_hl << 2;
   s_ip_len=ip->ip_len;
   if(ip->ip_p == IPPROTO_ICMP) {
index 6c80e69685c2d4525ca5519ab9c5b1c2e0c8a161..3432fbfeb74052d6a8c2e4ad530837104dfd10aa 100644 (file)
@@ -113,7 +113,6 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
        struct sockaddr_in addr;
        socklen_t addrlen = sizeof(addr);
        int opt;
-        int master = -1;
        const char *argv[256];
        /* don't want to clobber the original */
        char *bptr;
@@ -148,32 +147,23 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
         case -1:
                lprint("Error: fork failed: %s\n", strerror(errno));
                close(s);
-               if (do_pty == 2)
-                  close(master);
                return 0;
 
         case 0:
                 setsid();
 
                /* Set the DISPLAY */
-               if (do_pty == 2) {
-                       (void) close(master);
-#ifdef TIOCSCTTY /* XXXXX */
-                       ioctl(s, TIOCSCTTY, (char *)NULL);
-#endif
-               } else {
-                       getsockname(s, (struct sockaddr *)&addr, &addrlen);
-                       close(s);
-                       /*
-                        * Connect to the socket
-                        * XXX If any of these fail, we're in trouble!
-                        */
-                       s = qemu_socket(AF_INET, SOCK_STREAM, 0);
-                       addr.sin_addr = loopback_addr;
-                        do {
-                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
-                        } while (ret < 0 && errno == EINTR);
-               }
+                getsockname(s, (struct sockaddr *)&addr, &addrlen);
+                close(s);
+                /*
+                 * Connect to the socket
+                 * XXX If any of these fail, we're in trouble!
+                 */
+                s = qemu_socket(AF_INET, SOCK_STREAM, 0);
+                addr.sin_addr = loopback_addr;
+                do {
+                    ret = connect(s, (struct sockaddr *)&addr, addrlen);
+                } while (ret < 0 && errno == EINTR);
 
                dup2(s, 0);
                dup2(s, 1);
@@ -210,26 +200,21 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 
         default:
                qemu_add_child_watch(pid);
-               if (do_pty == 2) {
-                       close(s);
-                       so->s = master;
-               } else {
-                       /*
-                        * XXX this could block us...
-                        * XXX Should set a timer here, and if accept() doesn't
-                        * return after X seconds, declare it a failure
-                        * The only reason this will block forever is if socket()
-                        * of connect() fail in the child process
-                        */
-                        do {
-                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
-                        } while (so->s < 0 && errno == EINTR);
-                        closesocket(s);
-                       opt = 1;
-                       setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
-                       opt = 1;
-                       setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
-               }
+                /*
+                 * XXX this could block us...
+                 * XXX Should set a timer here, and if accept() doesn't
+                 * return after X seconds, declare it a failure
+                 * The only reason this will block forever is if socket()
+                 * of connect() fail in the child process
+                 */
+                do {
+                    so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
+                } while (so->s < 0 && errno == EINTR);
+                closesocket(s);
+                opt = 1;
+                setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
+                opt = 1;
+                setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
                fd_nonblock(so->s);
 
                /* Append the telnet options now */
index e56fac8684717a2fa21e095dd1c271e738ddecee..928fbcf3cbe99206ea80a927b63134abd03912f2 100644 (file)
@@ -1293,11 +1293,8 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
 
 target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
 {
-    uint32_t tlbncfg;
-    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
     int tlbm_size;
 
-    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
     tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
 
     return 1024ULL << tlbm_size;
index 5d057496436dc00e33418059b99893958777badc..9b26ce23041e70226199b8c9da1099e5e8101f63 100644 (file)
@@ -67,6 +67,7 @@ bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
 bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_copy_on_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
+bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_io_em(void *bs, int64_t sector_num, int nb_sectors, int is_write, void *acb) "bs %p sector_num %"PRId64" nb_sectors %d is_write %d acb %p"
 bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d"
 
@@ -320,7 +321,7 @@ qed_need_check_timer_cb(void *s) "s %p"
 qed_start_need_check_timer(void *s) "s %p"
 qed_cancel_need_check_timer(void *s) "s %p"
 qed_aio_complete(void *s, void *acb, int ret) "s %p acb %p ret %d"
-qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int is_write) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p is_write %d"
+qed_aio_setup(void *s, void *acb, int64_t sector_num, int nb_sectors, void *opaque, int flags) "s %p acb %p sector_num %"PRId64" nb_sectors %d opaque %p flags %#x"
 qed_aio_next_io(void *s, void *acb, int ret, uint64_t cur_pos) "s %p acb %p ret %d cur_pos %"PRIu64
 qed_aio_read_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
 qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
index 5639c6f5314a964dd9b0400e072a48e23cb7dfb9..b4629f895be7e7b3ce7499e0d3692a5be12048a5 100644 (file)
@@ -753,8 +753,9 @@ static void spice_register_config(void)
 }
 machine_init(spice_register_config);
 
-static void spice_initialize(void)
+static void spice_register_types(void)
 {
     qemu_spice_init();
 }
-device_init(spice_initialize);
+
+type_init(spice_register_types)
index 16b79ec423b89c467a714eda3b085455d2ff0c59..02b71bcd2ca5c572a1c9cd702c29eab7b679a8d1 100644 (file)
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -46,6 +46,30 @@ static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
 
 static int vnc_cursor_define(VncState *vs);
+static void vnc_release_modifiers(VncState *vs);
+
+static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
+{
+#ifdef _VNC_DEBUG
+    static const char *mn[] = {
+        [0]                           = "undefined",
+        [VNC_SHARE_MODE_CONNECTING]   = "connecting",
+        [VNC_SHARE_MODE_SHARED]       = "shared",
+        [VNC_SHARE_MODE_EXCLUSIVE]    = "exclusive",
+        [VNC_SHARE_MODE_DISCONNECTED] = "disconnected",
+    };
+    fprintf(stderr, "%s/%d: %s -> %s\n", __func__,
+            vs->csock, mn[vs->share_mode], mn[mode]);
+#endif
+
+    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+        vs->vd->num_exclusive--;
+    }
+    vs->share_mode = mode;
+    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+        vs->vd->num_exclusive++;
+    }
+}
 
 static char *addr_to_string(const char *format,
                             struct sockaddr_storage *sa,
@@ -997,6 +1021,7 @@ static void vnc_disconnect_start(VncState *vs)
 {
     if (vs->csock == -1)
         return;
+    vnc_set_share_mode(vs, VNC_SHARE_MODE_DISCONNECTED);
     qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
     closesocket(vs->csock);
     vs->csock = -1;
@@ -1027,6 +1052,7 @@ static void vnc_disconnect_finish(VncState *vs)
     vnc_sasl_client_cleanup(vs);
 #endif /* CONFIG_VNC_SASL */
     audio_del(vs);
+    vnc_release_modifiers(vs);
 
     QTAILQ_REMOVE(&vs->vd->clients, vs, next);
 
@@ -1552,9 +1578,11 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         else
             kbd_put_keycode(keycode | SCANCODE_UP);
     } else {
+        bool numlock = vs->modifiers_state[0x45];
+        bool control = (vs->modifiers_state[0x1d] ||
+                        vs->modifiers_state[0x9d]);
         /* QEMU console emulation */
         if (down) {
-            int numlock = vs->modifiers_state[0x45];
             switch (keycode) {
             case 0x2a:                          /* Left Shift */
             case 0x36:                          /* Right Shift */
@@ -1642,13 +1670,40 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
                 break;
 
             default:
-                kbd_put_keysym(sym);
+                if (control) {
+                    kbd_put_keysym(sym & 0x1f);
+                } else {
+                    kbd_put_keysym(sym);
+                }
                 break;
             }
         }
     }
 }
 
+static void vnc_release_modifiers(VncState *vs)
+{
+    static const int keycodes[] = {
+        /* shift, control, alt keys, both left & right */
+        0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
+    };
+    int i, keycode;
+
+    if (!is_graphic_console()) {
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
+        keycode = keycodes[i];
+        if (!vs->modifiers_state[keycode]) {
+            continue;
+        }
+        if (keycode & SCANCODE_GREY) {
+            kbd_put_keycode(SCANCODE_EMUL0);
+        }
+        kbd_put_keycode(keycode | SCANCODE_UP);
+    }
+}
+
 static void key_event(VncState *vs, int down, uint32_t sym)
 {
     int keycode;
@@ -2048,8 +2103,67 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
 {
     char buf[1024];
+    VncShareMode mode;
     int size;
 
+    mode = data[0] ? VNC_SHARE_MODE_SHARED : VNC_SHARE_MODE_EXCLUSIVE;
+    switch (vs->vd->share_policy) {
+    case VNC_SHARE_POLICY_IGNORE:
+        /*
+         * Ignore the shared flag.  Nothing to do here.
+         *
+         * Doesn't conform to the rfb spec but is traditional qemu
+         * behavior, thus left here as option for compatibility
+         * reasons.
+         */
+        break;
+    case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE:
+        /*
+         * Policy: Allow clients ask for exclusive access.
+         *
+         * Implementation: When a client asks for exclusive access,
+         * disconnect all others. Shared connects are allowed as long
+         * as no exclusive connection exists.
+         *
+         * This is how the rfb spec suggests to handle the shared flag.
+         */
+        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
+            VncState *client;
+            QTAILQ_FOREACH(client, &vs->vd->clients, next) {
+                if (vs == client) {
+                    continue;
+                }
+                if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE &&
+                    client->share_mode != VNC_SHARE_MODE_SHARED) {
+                    continue;
+                }
+                vnc_disconnect_start(client);
+            }
+        }
+        if (mode == VNC_SHARE_MODE_SHARED) {
+            if (vs->vd->num_exclusive > 0) {
+                vnc_disconnect_start(vs);
+                return 0;
+            }
+        }
+        break;
+    case VNC_SHARE_POLICY_FORCE_SHARED:
+        /*
+         * Policy: Shared connects only.
+         * Implementation: Disallow clients asking for exclusive access.
+         *
+         * Useful for shared desktop sessions where you don't want
+         * someone forgetting to say -shared when running the vnc
+         * client disconnect everybody else.
+         */
+        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
+            vnc_disconnect_start(vs);
+            return 0;
+        }
+        break;
+    }
+    vnc_set_share_mode(vs, mode);
+
     vs->client_width = ds_get_width(vs->ds);
     vs->client_height = ds_get_height(vs->ds);
     vnc_write_u16(vs, vs->client_width);
@@ -2445,7 +2559,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
             guest_ptr  = guest_row;
             server_ptr = server_row;
 
-            for (x = 0; x < vd->guest.ds->width;
+            for (x = 0; x + 15 < vd->guest.ds->width;
                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
                 if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
                     continue;
@@ -2556,6 +2670,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
 
     vnc_client_cache_addr(vs);
     vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
+    vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
 
     vs->vd = vd;
     vs->ds = vd->ds;
@@ -2749,6 +2864,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
 
     if (!(vs->display = strdup(display)))
         return -1;
+    vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
 
     options = display;
     while ((options = strchr(options, ','))) {
@@ -2804,6 +2920,19 @@ int vnc_display_open(DisplayState *ds, const char *display)
             vs->lossy = true;
         } else if (strncmp(options, "non-adapative", 13) == 0) {
             vs->non_adaptive = true;
+        } else if (strncmp(options, "share=", 6) == 0) {
+            if (strncmp(options+6, "ignore", 6) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_IGNORE;
+            } else if (strncmp(options+6, "allow-exclusive", 15) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
+            } else if (strncmp(options+6, "force-shared", 12) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED;
+            } else {
+                fprintf(stderr, "unknown vnc share= option\n");
+                g_free(vs->display);
+                vs->display = NULL;
+                return -1;
+            }
         }
     }
 
index 66689f1d60c718f9c076544d81e8c849e2158db2..0bd1fc6d2342edabd0556130bbf8e6de1c563917 100644 (file)
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -122,9 +122,24 @@ struct VncSurface
     DisplaySurface *ds;
 };
 
+typedef enum VncShareMode {
+    VNC_SHARE_MODE_CONNECTING = 1,
+    VNC_SHARE_MODE_SHARED,
+    VNC_SHARE_MODE_EXCLUSIVE,
+    VNC_SHARE_MODE_DISCONNECTED,
+} VncShareMode;
+
+typedef enum VncSharePolicy {
+    VNC_SHARE_POLICY_IGNORE = 1,
+    VNC_SHARE_POLICY_ALLOW_EXCLUSIVE,
+    VNC_SHARE_POLICY_FORCE_SHARED,
+} VncSharePolicy;
+
 struct VncDisplay
 {
     QTAILQ_HEAD(, VncState) clients;
+    int num_exclusive;
+    VncSharePolicy share_policy;
     QEMUTimer *timer;
     int timer_interval;
     int lsock;
@@ -250,6 +265,7 @@ struct VncState
     int last_y;
     int client_width;
     int client_height;
+    VncShareMode share_mode;
 
     uint32_t vnc_encoding;
 
index fc722b3cfacc1438184002e4b13dde941529a841..4fa4b4215859c818b6b0bf585d8729606fab7c48 100644 (file)
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -214,7 +214,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
     int ret, fd, mode;
     int one = 1, shortpacket = 0, timeout = 50;
     sigset_t new_mask, old_mask;
-    uint8_t devep = p->devep;
+    uint8_t devep = p->ep->nr;
 
     /* protect data transfers from SIGALRM signal */
     sigemptyset(&new_mask);
@@ -403,7 +403,6 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
 
     uc->product_desc   = "USB Host Device";
     uc->init           = usb_host_initfn;
-    uc->handle_packet  = usb_generic_handle_packet;
     uc->handle_reset   = usb_host_handle_reset;
     uc->handle_control = usb_host_handle_control;
     uc->handle_data    = usb_host_handle_data;
@@ -417,11 +416,12 @@ static TypeInfo usb_host_dev_info = {
     .class_init    = usb_host_class_initfn,
 };
 
-static void usb_host_register_devices(void)
+static void usb_host_register_types(void)
 {
     type_register_static(&usb_host_dev_info);
 }
-device_init(usb_host_register_devices)
+
+type_init(usb_host_register_types)
 
 static int usb_host_scan(void *opaque, USBScanFunc *func)
 {
index e7fc9ecd5c3a73bc4add03b775e2c9c18f1fd06f..24700fc1f7830c2e9bfb3ff1cb5728f38ac92f14 100644 (file)
@@ -137,7 +137,7 @@ static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
         [USB_ENDPOINT_XFER_BULK]    = USBDEVFS_URB_TYPE_BULK,
         [USB_ENDPOINT_XFER_INT]     = USBDEVFS_URB_TYPE_INTERRUPT,
     };
-    uint8_t type = usb_ep_get_type(&s->dev, p->pid, p->devep);
+    uint8_t type = p->ep->type;
     assert(type < ARRAY_SIZE(usbfs));
     return usbfs[type];
 }
@@ -360,7 +360,7 @@ static void async_complete(void *opaque)
                 break;
 
             case -EPIPE:
-                set_halt(s, p->pid, p->devep);
+                set_halt(s, p->pid, p->ep->nr);
                 p->result = USB_RET_STALL;
                 break;
 
@@ -733,16 +733,16 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
     int i, j, ret, max_packet_size, offset, len = 0;
     uint8_t *buf;
 
-    max_packet_size = usb_ep_get_max_packet_size(&s->dev, p->pid, p->devep);
+    max_packet_size = p->ep->max_packet_size;
     if (max_packet_size == 0)
         return USB_RET_NAK;
 
-    aurb = get_iso_urb(s, p->pid, p->devep);
+    aurb = get_iso_urb(s, p->pid, p->ep->nr);
     if (!aurb) {
-        aurb = usb_host_alloc_iso(s, p->pid, p->devep);
+        aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr);
     }
 
-    i = get_iso_urb_idx(s, p->pid, p->devep);
+    i = get_iso_urb_idx(s, p->pid, p->ep->nr);
     j = aurb[i].iso_frame_idx;
     if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
         if (in) {
@@ -769,7 +769,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             }
         } else {
             len = p->iov.size;
-            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->devep);
+            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr);
 
             /* Check the frame fits */
             if (len > max_packet_size) {
@@ -781,27 +781,27 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
             usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
             aurb[i].urb.iso_frame_desc[j].length = len;
             offset += len;
-            set_iso_buffer_used(s, p->pid, p->devep, offset);
+            set_iso_buffer_used(s, p->pid, p->ep->nr, offset);
 
             /* Start the stream once we have buffered enough data */
-            if (!is_iso_started(s, p->pid, p->devep) && i == 1 && j == 8) {
-                set_iso_started(s, p->pid, p->devep);
+            if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) {
+                set_iso_started(s, p->pid, p->ep->nr);
             }
         }
         aurb[i].iso_frame_idx++;
         if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
             i = (i + 1) % s->iso_urb_count;
-            set_iso_urb_idx(s, p->pid, p->devep, i);
+            set_iso_urb_idx(s, p->pid, p->ep->nr, i);
         }
     } else {
         if (in) {
-            set_iso_started(s, p->pid, p->devep);
+            set_iso_started(s, p->pid, p->ep->nr);
         } else {
             DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
         }
     }
 
-    if (is_iso_started(s, p->pid, p->devep)) {
+    if (is_iso_started(s, p->pid, p->ep->nr)) {
         /* (Re)-submit all fully consumed / filled urbs */
         for (i = 0; i < s->iso_urb_count; i++) {
             if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
@@ -821,7 +821,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
                     break;
                 }
                 aurb[i].iso_frame_idx = -1;
-                change_iso_inflight(s, p->pid, p->devep, 1);
+                change_iso_inflight(s, p->pid, p->ep->nr, 1);
             }
         }
     }
@@ -840,20 +840,20 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
 
     trace_usb_host_req_data(s->bus_num, s->addr,
                             p->pid == USB_TOKEN_IN,
-                            p->devep, p->iov.size);
+                            p->ep->nr, p->iov.size);
 
-    if (!is_valid(s, p->pid, p->devep)) {
+    if (!is_valid(s, p->pid, p->ep->nr)) {
         trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
         return USB_RET_NAK;
     }
 
     if (p->pid == USB_TOKEN_IN) {
-        ep = p->devep | 0x80;
+        ep = p->ep->nr | 0x80;
     } else {
-        ep = p->devep;
+        ep = p->ep->nr;
     }
 
-    if (is_halted(s, p->pid, p->devep)) {
+    if (is_halted(s, p->pid, p->ep->nr)) {
         unsigned int arg = ep;
         ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
         if (ret < 0) {
@@ -861,10 +861,10 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
             trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
             return USB_RET_NAK;
         }
-        clear_halt(s, p->pid, p->devep);
+        clear_halt(s, p->pid, p->ep->nr);
     }
 
-    if (is_isoc(s, p->pid, p->devep)) {
+    if (is_isoc(s, p->pid, p->ep->nr)) {
         return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
     }
 
@@ -1057,7 +1057,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
     urb = &aurb->urb;
 
     urb->type     = USBDEVFS_URB_TYPE_CONTROL;
-    urb->endpoint = p->devep;
+    urb->endpoint = p->ep->nr;
 
     urb->buffer        = &dev->setup_buf;
     urb->buffer_length = length + 8;
@@ -1419,7 +1419,6 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
 
     uc->init           = usb_host_initfn;
     uc->product_desc   = "USB Host Device";
-    uc->handle_packet  = usb_generic_handle_packet;
     uc->cancel_packet  = usb_host_async_cancel;
     uc->handle_data    = usb_host_handle_data;
     uc->handle_control = usb_host_handle_control;
@@ -1436,12 +1435,13 @@ static TypeInfo usb_host_dev_info = {
     .class_init    = usb_host_class_initfn,
 };
 
-static void usb_host_register_devices(void)
+static void usb_host_register_types(void)
 {
     type_register_static(&usb_host_dev_info);
     usb_legacy_register("usb-host", "host", usb_host_device_open);
 }
-device_init(usb_host_register_devices)
+
+type_init(usb_host_register_types)
 
 USBDevice *usb_host_device_open(const char *devname)
 {
index 303292acd696118d1289654735eced4753c162de..a59b347f01537cf44323b12b3155e7ed6ee723db 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/ioctl.h>
 #include <signal.h>
 #include <usbredirparser.h>
+#include <usbredirfilter.h>
 
 #include "hw/usb.h"
 
@@ -72,6 +73,7 @@ struct USBRedirDevice {
     /* Properties */
     CharDriverState *cs;
     uint8_t debug;
+    char *filter_str;
     /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
     const uint8_t *read_buf;
     int read_buf_size;
@@ -84,6 +86,11 @@ struct USBRedirDevice {
     struct endp_data endpoint[MAX_ENDPOINTS];
     uint32_t packet_id;
     QTAILQ_HEAD(, AsyncURB) asyncq;
+    /* Data for device filtering */
+    struct usb_redir_device_connect_header device_info;
+    struct usb_redir_interface_info_header interface_info;
+    struct usbredirfilter_rule *filter_rules;
+    int filter_rules_count;
 };
 
 struct AsyncURB {
@@ -603,7 +610,7 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
     uint8_t ep;
 
-    ep = p->devep;
+    ep = p->ep->nr;
     if (p->pid == USB_TOKEN_IN) {
         ep |= USB_DIR_IN;
     }
@@ -780,6 +787,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
 static void usbredir_open_close_bh(void *opaque)
 {
     USBRedirDevice *dev = opaque;
+    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
 
     usbredir_device_disconnect(dev);
 
@@ -810,7 +818,9 @@ static void usbredir_open_close_bh(void *opaque)
         dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
         dev->read_buf = NULL;
         dev->read_buf_size = 0;
-        usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
+
+        usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+        usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
         usbredirparser_do_write(dev->parser);
     }
 }
@@ -880,6 +890,17 @@ static int usbredir_initfn(USBDevice *udev)
         return -1;
     }
 
+    if (dev->filter_str) {
+        i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
+                                           &dev->filter_rules,
+                                           &dev->filter_rules_count);
+        if (i) {
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
+                          "a usb device filter string");
+            return -1;
+        }
+    }
+
     dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
 
@@ -929,6 +950,44 @@ static void usbredir_handle_destroy(USBDevice *udev)
     if (dev->parser) {
         usbredirparser_destroy(dev->parser);
     }
+
+    free(dev->filter_rules);
+}
+
+static int usbredir_check_filter(USBRedirDevice *dev)
+{
+    if (dev->interface_info.interface_count == 0) {
+        ERROR("No interface info for device\n");
+        return -1;
+    }
+
+    if (dev->filter_rules) {
+        if (!usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_connect_device_version)) {
+            ERROR("Device filter specified and peer does not have the "
+                  "connect_device_version capability\n");
+            return -1;
+        }
+
+        if (usbredirfilter_check(
+                dev->filter_rules,
+                dev->filter_rules_count,
+                dev->device_info.device_class,
+                dev->device_info.device_subclass,
+                dev->device_info.device_protocol,
+                dev->interface_info.interface_class,
+                dev->interface_info.interface_subclass,
+                dev->interface_info.interface_protocol,
+                dev->interface_info.interface_count,
+                dev->device_info.vendor_id,
+                dev->device_info.product_id,
+                dev->device_info.device_version_bcd,
+                0) != 0) {
+            return -1;
+        }
+    }
+
+    return 0;
 }
 
 /*
@@ -957,6 +1016,7 @@ static void usbredir_device_connect(void *priv,
     struct usb_redir_device_connect_header *device_connect)
 {
     USBRedirDevice *dev = priv;
+    const char *speed;
 
     if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
         ERROR("Received device connect while already connected\n");
@@ -965,26 +1025,48 @@ static void usbredir_device_connect(void *priv,
 
     switch (device_connect->speed) {
     case usb_redir_speed_low:
-        DPRINTF("attaching low speed device\n");
+        speed = "low speed";
         dev->dev.speed = USB_SPEED_LOW;
         break;
     case usb_redir_speed_full:
-        DPRINTF("attaching full speed device\n");
+        speed = "full speed";
         dev->dev.speed = USB_SPEED_FULL;
         break;
     case usb_redir_speed_high:
-        DPRINTF("attaching high speed device\n");
+        speed = "high speed";
         dev->dev.speed = USB_SPEED_HIGH;
         break;
     case usb_redir_speed_super:
-        DPRINTF("attaching super speed device\n");
+        speed = "super speed";
         dev->dev.speed = USB_SPEED_SUPER;
         break;
     default:
-        DPRINTF("attaching unknown speed device, assuming full speed\n");
+        speed = "unknown speed";
         dev->dev.speed = USB_SPEED_FULL;
     }
+
+    if (usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_connect_device_version)) {
+        INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
+             speed, device_connect->vendor_id, device_connect->product_id,
+             device_connect->device_version_bcd >> 8,
+             device_connect->device_version_bcd & 0xff,
+             device_connect->device_class);
+    } else {
+        INFO("attaching %s device %04x:%04x class %02x\n", speed,
+             device_connect->vendor_id, device_connect->product_id,
+             device_connect->device_class);
+    }
+
     dev->dev.speedmask = (1 << dev->dev.speed);
+    dev->device_info = *device_connect;
+
+    if (usbredir_check_filter(dev)) {
+        WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
+                device_connect->vendor_id, device_connect->product_id);
+        return;
+    }
+
     qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
 }
 
@@ -1011,15 +1093,27 @@ static void usbredir_device_disconnect(void *priv)
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         QTAILQ_INIT(&dev->endpoint[i].bufpq);
     }
+    dev->interface_info.interface_count = 0;
 }
 
 static void usbredir_interface_info(void *priv,
     struct usb_redir_interface_info_header *interface_info)
 {
-    /* The intention is to allow specifying acceptable interface classes
-       for redirection on the cmdline and in the future verify this here,
-       and disconnect (or never connect) the device if a not accepted
-       interface class is detected */
+    USBRedirDevice *dev = priv;
+
+    dev->interface_info = *interface_info;
+
+    /*
+     * If we receive interface info after the device has already been
+     * connected (ie on a set_config), re-check the filter.
+     */
+    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+        if (usbredir_check_filter(dev)) {
+            ERROR("Device no longer matches filter after interface info "
+                  "change, disconnecting!\n");
+            usbredir_device_disconnect(dev);
+        }
+    }
 }
 
 static void usbredir_ep_info(void *priv,
@@ -1318,6 +1412,7 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id,
 static Property usbredir_properties[] = {
     DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
     DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
+    DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -1329,7 +1424,6 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
     uc->init           = usbredir_initfn;
     uc->product_desc   = "USB Redirection Device";
     uc->handle_destroy = usbredir_handle_destroy;
-    uc->handle_packet  = usb_generic_handle_packet;
     uc->cancel_packet  = usbredir_cancel_packet;
     uc->handle_reset   = usbredir_handle_reset;
     uc->handle_data    = usbredir_handle_data;
@@ -1344,8 +1438,9 @@ static TypeInfo usbredir_dev_info = {
     .class_init    = usbredir_class_initfn,
 };
 
-static void usbredir_register_devices(void)
+static void usbredir_register_types(void)
 {
     type_register_static(&usbredir_dev_info);
 }
-device_init(usbredir_register_devices);
+
+type_init(usbredir_register_types)
diff --git a/vl.c b/vl.c
index 63dd7252164489fd8915e6d2d90a2ad43103217c..0e8425e35ee1e6d2bf6b1bc0327f8fd0af44d846 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -2529,6 +2529,14 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+#ifdef CONFIG_LIBISCSI
+            case QEMU_OPTION_iscsi:
+                opts = qemu_opts_parse(qemu_find_opts("iscsi"), optarg, 0);
+                if (!opts) {
+                    exit(1);
+                }
+                break;
+#endif
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
                 legacy_tftp_prefix = optarg;
@@ -3361,7 +3369,7 @@ int main(int argc, char **argv, char **envp)
     if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
         exit(1);
 
-    module_call_init(MODULE_INIT_DEVICE);
+    module_call_init(MODULE_INIT_QOM);
 
     /* must be after qdev registration but before machine init */
     if (vga_model) {