diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/block/nand.c | 33 | ||||
| -rw-r--r-- | hw/char/cadence_uart.c | 4 | ||||
| -rw-r--r-- | hw/display/qxl.c | 1 | ||||
| -rw-r--r-- | hw/i386/kvm/pci-assign.c | 1 | ||||
| -rw-r--r-- | hw/i386/pc_piix.c | 12 | ||||
| -rw-r--r-- | hw/sd/milkymist-memcard.c | 2 | ||||
| -rw-r--r-- | hw/sd/omap_mmc.c | 4 | ||||
| -rw-r--r-- | hw/sd/pl181.c | 2 | ||||
| -rw-r--r-- | hw/sd/pxa2xx_mmci.c | 2 | ||||
| -rw-r--r-- | hw/sd/sdhci.c | 2 | ||||
| -rw-r--r-- | hw/sd/ssi-sd.c | 2 | ||||
| -rw-r--r-- | hw/usb/bus.c | 1 | ||||
| -rw-r--r-- | hw/usb/desc.c | 6 | ||||
| -rw-r--r-- | hw/usb/dev-hid.c | 3 | ||||
| -rw-r--r-- | hw/usb/dev-storage.c | 13 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci-pci.c | 23 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci-sysbus.c | 121 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci.c | 50 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci.h | 28 | ||||
| -rw-r--r-- | hw/usb/host-libusb.c | 5 |
20 files changed, 239 insertions, 76 deletions
diff --git a/hw/block/nand.c b/hw/block/nand.c index 087ca14ed1..43401a0b1b 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -298,10 +298,8 @@ static void nand_command(NANDFlashState *s) case NAND_CMD_BLOCKERASE2: s->addr &= (1ull << s->addrlen * 8) - 1; - if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) - s->addr <<= 16; - else - s->addr <<= 8; + s->addr <<= nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP ? + 16 : 8; if (s->wp) { s->blk_erase(s); @@ -464,10 +462,11 @@ void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, s->ce = ce; s->wp = wp; s->gnd = gnd; - if (wp) + if (wp) { s->status |= NAND_IOSTATUS_UNPROTCT; - else + } else { s->status &= ~NAND_IOSTATUS_UNPROTCT; + } } void nand_getpins(DeviceState *dev, int *rb) @@ -489,13 +488,12 @@ void nand_setio(DeviceState *dev, uint32_t value) return; } } - if (value == NAND_CMD_READ0) + if (value == NAND_CMD_READ0) { s->offset = 0; - else if (value == NAND_CMD_READ1) { + } else if (value == NAND_CMD_READ1) { s->offset = 0x100; value = NAND_CMD_READ0; - } - else if (value == NAND_CMD_READ2) { + } else if (value == NAND_CMD_READ2) { s->offset = 1 << s->page_shift; value = NAND_CMD_READ0; } @@ -508,8 +506,9 @@ void nand_setio(DeviceState *dev, uint32_t value) s->cmd == NAND_CMD_BLOCKERASE2 || s->cmd == NAND_CMD_NOSERIALREAD2 || s->cmd == NAND_CMD_RANDOMREAD2 || - s->cmd == NAND_CMD_RESET) + s->cmd == NAND_CMD_RESET) { nand_command(s); + } if (s->cmd != NAND_CMD_RANDOMREAD2) { s->addrlen = 0; @@ -596,8 +595,9 @@ uint32_t nand_getio(DeviceState *dev) s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset; } - if (s->ce || s->iolen <= 0) + if (s->ce || s->iolen <= 0) { return 0; + } for (offset = s->buswidth; offset--;) { x |= s->ioaddr[offset] << (offset << 3); @@ -696,8 +696,9 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, }; addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1); - if (PAGE(addr) >= s->pages) + if (PAGE(addr) >= s->pages) { return; + } if (!s->bdrv) { memset(s->storage + PAGE_START(addr), @@ -725,11 +726,12 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) memset(iobuf, 0xff, 0x200); i = (addr & ~0x1ff) + 0x200; for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; - i < addr; i += 0x200) + i < addr; i += 0x200) { if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) < 0) { printf("%s: write error in sector %" PRIu64 "\n", __func__, i >> 9); } + } page = i >> 9; if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) { @@ -745,8 +747,9 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, uint64_t addr, int offset) { - if (PAGE(addr) >= s->pages) + if (PAGE(addr) >= s->pages) { return; + } if (s->bdrv) { if (s->mem_oob) { diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index c2a783430b..205e125de9 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -297,9 +297,7 @@ static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size) return; } - while (size) { - size -= qemu_chr_fe_write(s->chr, buf, size); - } + qemu_chr_fe_write_all(s->chr, buf, size); } static void uart_receive(void *opaque, const uint8_t *buf, int size) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index c475cb10dc..937a402b2e 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -387,6 +387,7 @@ static void init_qxl_ram(PCIQXLDevice *d) d->ram->int_pending = cpu_to_le32(0); d->ram->int_mask = cpu_to_le32(0); d->ram->update_surface = 0; + d->ram->monitors_config = 0; SPICE_RING_INIT(&d->ram->cmd_ring); SPICE_RING_INIT(&d->ram->cursor_ring); SPICE_RING_INIT(&d->ram->release_ring); diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index ff855904ba..1fb7ad44ab 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -548,6 +548,7 @@ static int get_real_id(const char *devpath, const char *idname, uint16_t *val) if (fscanf(f, "%li\n", &id) == 1) { *val = id; } else { + fclose(f); return -1; } fclose(f); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 97362f2c26..7972443374 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -622,6 +622,18 @@ static QEMUMachine pc_machine_v0_13 = { .driver = "virtio-serial-pci",\ .property = "vectors",\ .value = stringify(0),\ + },{\ + .driver = "usb-mouse",\ + .property = "serial",\ + .value = "1",\ + },{\ + .driver = "usb-tablet",\ + .property = "serial",\ + .value = "1",\ + },{\ + .driver = "usb-kbd",\ + .property = "serial",\ + .value = "1",\ } static QEMUMachine pc_machine_v0_12 = { diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index d5944bca69..61a8aadddd 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -250,7 +250,7 @@ static int milkymist_memcard_init(SysBusDevice *dev) DriveInfo *dinfo; dinfo = drive_get_next(IF_SD); - s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0); + s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false); s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0; memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s, diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index d4079cde0b..ba9f4b3098 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -592,7 +592,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base, memory_region_add_subregion(sysmem, base, &s->iomem); /* Instantiate the storage */ - s->card = sd_init(bd, 0); + s->card = sd_init(bd, false); return s; } @@ -617,7 +617,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, omap_l4_attach(ta, 0, &s->iomem); /* Instantiate the storage */ - s->card = sd_init(bd, 0); + s->card = sd_init(bd, false); s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0]; sd_set_cb(s->card, NULL, s->cdet); diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 2527296776..e08fd04e7e 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -485,7 +485,7 @@ static int pl181_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[1]); qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2); dinfo = drive_get_next(IF_SD); - s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0); + s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false); return 0; } diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 2db1cabb7a..0574d6b26d 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -538,7 +538,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, memory_region_add_subregion(sysmem, base, &s->iomem); /* Instantiate the actual storage */ - s->card = sd_init(bd, 0); + s->card = sd_init(bd, false); register_savevm(NULL, "pxa2xx_mmci", 0, 0, pxa2xx_mmci_save, pxa2xx_mmci_load, s); diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 00650674bd..b9dd4bebc1 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1165,7 +1165,7 @@ static void sdhci_initfn(Object *obj) DriveInfo *di; di = drive_get_next(IF_SD); - s->card = sd_init(di ? di->bdrv : NULL, 0); + s->card = sd_init(di ? di->bdrv : NULL, false); s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0]; s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0]; sd_set_cb(s->card, s->ro_cb, s->eject_cb); diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 4d3c4f6445..d47e2377f9 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -245,7 +245,7 @@ static int ssi_sd_init(SSISlave *dev) s->mode = SSI_SD_CMD; dinfo = drive_get_next(IF_SD); - s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, 1); + s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, true); register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); return 0; } diff --git a/hw/usb/bus.c b/hw/usb/bus.c index d1827be101..f83d1de6cd 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -13,6 +13,7 @@ static int usb_qdev_exit(DeviceState *qdev); static Property usb_props[] = { DEFINE_PROP_STRING("port", USBDevice, port_path), + DEFINE_PROP_STRING("serial", USBDevice, serial), DEFINE_PROP_BIT("full-path", USBDevice, flags, USB_DEV_FLAG_FULL_PATH, true), DEFINE_PROP_END_OF_LIST() diff --git a/hw/usb/desc.c b/hw/usb/desc.c index fce303e9c8..bf6c522682 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -566,6 +566,12 @@ void usb_desc_create_serial(USBDevice *dev) char *path; int dst; + if (dev->serial) { + /* 'serial' usb bus property has priority if present */ + usb_desc_set_string(dev, index, dev->serial); + return; + } + assert(index != 0 && desc->str[index] != NULL); dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]); path = qdev_get_dev_path(hcd); diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index b48899d500..31f3cdef42 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -560,6 +560,9 @@ static int usb_hid_initfn(USBDevice *dev, int kind) { USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + if (dev->serial) { + usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial); + } usb_desc_init(dev); us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); hid_init(&us->hid, kind, usb_hid_changed); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 1073901af1..fe914ab005 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -58,7 +58,6 @@ typedef struct { USBPacket *packet; /* usb-storage only */ BlockConf conf; - char *serial; uint32_t removable; } MSDState; @@ -602,7 +601,7 @@ static int usb_msd_initfn_storage(USBDevice *dev) return -1; } - blkconf_serial(&s->conf, &s->serial); + blkconf_serial(&s->conf, &dev->serial); /* * Hack alert: this pretends to be a block device, but it's really @@ -616,16 +615,11 @@ static int usb_msd_initfn_storage(USBDevice *dev) bdrv_detach_dev(bs, &s->dev.qdev); s->conf.bs = NULL; - if (s->serial) { - usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial); - } else { - usb_desc_create_serial(dev); - } - + usb_desc_create_serial(dev); usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL); scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, - s->conf.bootindex, s->serial); + s->conf.bootindex, dev->serial); if (!scsi_dev) { return -1; } @@ -734,7 +728,6 @@ static const VMStateDescription vmstate_usb_msd = { static Property msd_properties[] = { DEFINE_BLOCK_PROPERTIES(MSDState, conf), - DEFINE_PROP_STRING("serial", MSDState, serial), DEFINE_PROP_BIT("removable", MSDState, removable, 0, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index f1b5f5d29c..5d229bc792 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -60,20 +60,30 @@ static int usb_ehci_pci_initfn(PCIDevice *dev) pci_conf[0x6e] = 0x00; pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ - s->caps[0x09] = 0x68; /* EECP */ - s->irq = dev->irq[3]; s->as = pci_get_address_space(dev); - s->capsbase = 0x00; - s->opregbase = 0x20; - - usb_ehci_initfn(s, DEVICE(dev)); + usb_ehci_realize(s, DEVICE(dev), NULL); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); return 0; } +static void usb_ehci_pci_init(Object *obj) +{ + EHCIPCIState *i = PCI_EHCI(obj); + EHCIState *s = &i->ehci; + + s->caps[0x09] = 0x68; /* EECP */ + + s->capsbase = 0x00; + s->opregbase = 0x20; + s->portscbase = 0x44; + s->portnr = NB_PORTS; + + usb_ehci_init(s, DEVICE(obj)); +} + static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int l) { @@ -122,6 +132,7 @@ static const TypeInfo ehci_pci_type_info = { .name = TYPE_PCI_EHCI, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(EHCIPCIState), + .instance_init = usb_ehci_pci_init, .abstract = true, .class_init = ehci_class_init, }; diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index f9e4fd3474..e7d4f74b82 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -32,28 +32,42 @@ static Property ehci_sysbus_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static int usb_ehci_sysbus_initfn(SysBusDevice *dev) +static void usb_ehci_sysbus_realize(DeviceState *dev, Error **errp) { + SysBusDevice *d = SYS_BUS_DEVICE(dev); EHCISysBusState *i = SYS_BUS_EHCI(dev); - SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(dev); + EHCIState *s = &i->ehci; + + usb_ehci_realize(s, dev, errp); + sysbus_init_irq(d, &s->irq); +} + +static void ehci_sysbus_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + EHCISysBusState *i = SYS_BUS_EHCI(obj); + SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(obj); EHCIState *s = &i->ehci; s->capsbase = sec->capsbase; s->opregbase = sec->opregbase; + s->portscbase = sec->portscbase; + s->portnr = sec->portnr; s->as = &address_space_memory; - usb_ehci_initfn(s, DEVICE(dev)); - sysbus_init_irq(dev, &s->irq); - sysbus_init_mmio(dev, &s->mem); - return 0; + usb_ehci_init(s, DEVICE(obj)); + sysbus_init_mmio(d, &s->mem); } static void ehci_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass); + + sec->portscbase = 0x44; + sec->portnr = NB_PORTS; - k->init = usb_ehci_sysbus_initfn; + dc->realize = usb_ehci_sysbus_realize; dc->vmsd = &vmstate_ehci_sysbus; dc->props = ehci_sysbus_properties; } @@ -62,6 +76,7 @@ static const TypeInfo ehci_type_info = { .name = TYPE_SYS_BUS_EHCI, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(EHCISysBusState), + .instance_init = ehci_sysbus_init, .abstract = true, .class_init = ehci_sysbus_class_init, .class_size = sizeof(SysBusEHCIClass), @@ -95,11 +110,101 @@ static const TypeInfo ehci_exynos4210_type_info = { .class_init = ehci_exynos4210_class_init, }; +static void ehci_tegra2_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + + sec->capsbase = 0x100; + sec->opregbase = 0x140; +} + +static const TypeInfo ehci_tegra2_type_info = { + .name = TYPE_TEGRA2_EHCI, + .parent = TYPE_SYS_BUS_EHCI, + .class_init = ehci_tegra2_class_init, +}; + +/* + * Faraday FUSBH200 USB 2.0 EHCI + */ + +/** + * FUSBH200EHCIRegs: + * @FUSBH200_REG_EOF_ASTR: EOF/Async. Sleep Timer Register + * @FUSBH200_REG_BMCSR: Bus Monitor Control/Status Register + */ +enum FUSBH200EHCIRegs { + FUSBH200_REG_EOF_ASTR = 0x34, + FUSBH200_REG_BMCSR = 0x40, +}; + +static uint64_t fusbh200_ehci_read(void *opaque, hwaddr addr, unsigned size) +{ + EHCIState *s = opaque; + hwaddr off = s->opregbase + s->portscbase + 4 * s->portnr + addr; + + switch (off) { + case FUSBH200_REG_EOF_ASTR: + return 0x00000041; + case FUSBH200_REG_BMCSR: + /* High-Speed, VBUS valid, interrupt level-high active */ + return (2 << 9) | (1 << 8) | (1 << 3); + } + + return 0; +} + +static void fusbh200_ehci_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ +} + +static const MemoryRegionOps fusbh200_ehci_mmio_ops = { + .read = fusbh200_ehci_read, + .write = fusbh200_ehci_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void fusbh200_ehci_init(Object *obj) +{ + EHCISysBusState *i = SYS_BUS_EHCI(obj); + FUSBH200EHCIState *f = FUSBH200_EHCI(obj); + EHCIState *s = &i->ehci; + + memory_region_init_io(&f->mem_vendor, &fusbh200_ehci_mmio_ops, s, + "fusbh200", 0x4c); + memory_region_add_subregion(&s->mem, + s->opregbase + s->portscbase + 4 * s->portnr, + &f->mem_vendor); +} + +static void fusbh200_ehci_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); + + sec->capsbase = 0x0; + sec->opregbase = 0x10; + sec->portscbase = 0x20; + sec->portnr = 1; +} + +static const TypeInfo ehci_fusbh200_type_info = { + .name = TYPE_FUSBH200_EHCI, + .parent = TYPE_SYS_BUS_EHCI, + .instance_size = sizeof(FUSBH200EHCIState), + .instance_init = fusbh200_ehci_init, + .class_init = fusbh200_ehci_class_init, +}; + static void ehci_sysbus_register_types(void) { type_register_static(&ehci_type_info); type_register_static(&ehci_xlnx_type_info); type_register_static(&ehci_exynos4210_type_info); + type_register_static(&ehci_tegra2_type_info); + type_register_static(&ehci_fusbh200_type_info); } type_init(ehci_sysbus_register_types) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 1ad215931e..16d6356fa9 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -995,7 +995,7 @@ static uint64_t ehci_port_read(void *ptr, hwaddr addr, uint32_t val; val = s->portsc[addr >> 2]; - trace_usb_ehci_portsc_read(addr + PORTSC_BEGIN, addr >> 2, val); + trace_usb_ehci_portsc_read(addr + s->portscbase, addr >> 2, val); return val; } @@ -1036,7 +1036,7 @@ static void ehci_port_write(void *ptr, hwaddr addr, uint32_t old = *portsc; USBDevice *dev = s->ports[port].dev; - trace_usb_ehci_portsc_write(addr + PORTSC_BEGIN, addr >> 2, val); + trace_usb_ehci_portsc_write(addr + s->portscbase, addr >> 2, val); /* Clear rwc bits */ *portsc &= ~(val & PORTSC_RWC_MASK); @@ -1069,7 +1069,7 @@ static void ehci_port_write(void *ptr, hwaddr addr, *portsc &= ~PORTSC_RO_MASK; *portsc |= val; - trace_usb_ehci_portsc_change(addr + PORTSC_BEGIN, addr >> 2, *portsc, old); + trace_usb_ehci_portsc_change(addr + s->portscbase, addr >> 2, *portsc, old); } static void ehci_opreg_write(void *ptr, hwaddr addr, @@ -2508,16 +2508,38 @@ const VMStateDescription vmstate_ehci = { } }; -void usb_ehci_initfn(EHCIState *s, DeviceState *dev) +void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) { int i; + if (s->portnr > NB_PORTS) { + error_setg(errp, "Too many ports! Max. port number is %d.", + NB_PORTS); + return; + } + + usb_bus_new(&s->bus, &ehci_bus_ops, dev); + for (i = 0; i < s->portnr; i++) { + usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, + USB_SPEED_MASK_HIGH); + s->ports[i].dev = 0; + } + + s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s); + s->async_bh = qemu_bh_new(ehci_frame_timer, s); + + qemu_register_reset(ehci_reset, s); + qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); +} + +void usb_ehci_init(EHCIState *s, DeviceState *dev) +{ /* 2.2 host controller interface version */ s->caps[0x00] = (uint8_t)(s->opregbase - s->capsbase); s->caps[0x01] = 0x00; s->caps[0x02] = 0x00; s->caps[0x03] = 0x01; /* HC version */ - s->caps[0x04] = NB_PORTS; /* Number of downstream ports */ + s->caps[0x04] = s->portnr; /* Number of downstream ports */ s->caps[0x05] = 0x00; /* No companion ports at present */ s->caps[0x06] = 0x00; s->caps[0x07] = 0x00; @@ -2525,33 +2547,21 @@ void usb_ehci_initfn(EHCIState *s, DeviceState *dev) s->caps[0x0a] = 0x00; s->caps[0x0b] = 0x00; - usb_bus_new(&s->bus, &ehci_bus_ops, dev); - for(i = 0; i < NB_PORTS; i++) { - usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, - USB_SPEED_MASK_HIGH); - s->ports[i].dev = 0; - } - - s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s); - s->async_bh = qemu_bh_new(ehci_frame_timer, s); QTAILQ_INIT(&s->aqueues); QTAILQ_INIT(&s->pqueues); usb_packet_init(&s->ipacket); - qemu_register_reset(ehci_reset, s); - qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); - memory_region_init(&s->mem, "ehci", MMIO_SIZE); memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, "capabilities", CAPA_SIZE); memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s, - "operational", PORTSC_BEGIN); + "operational", s->portscbase); memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s, - "ports", PORTSC_END - PORTSC_BEGIN); + "ports", 4 * s->portnr); memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps); memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg); - memory_region_add_subregion(&s->mem, s->opregbase + PORTSC_BEGIN, + memory_region_add_subregion(&s->mem, s->opregbase + s->portscbase, &s->mem_ports); } diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 2fcb92f12b..15a28e8b31 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -40,11 +40,7 @@ #define MMIO_SIZE 0x1000 #define CAPA_SIZE 0x10 -#define PORTSC 0x0044 -#define PORTSC_BEGIN PORTSC -#define PORTSC_END (PORTSC + 4 * NB_PORTS) - -#define NB_PORTS 6 /* Number of downstream ports */ +#define NB_PORTS 6 /* Max. Number of downstream ports */ typedef struct EHCIPacket EHCIPacket; typedef struct EHCIQueue EHCIQueue; @@ -268,6 +264,8 @@ struct EHCIState { int companion_count; uint16_t capsbase; uint16_t opregbase; + uint16_t portscbase; + uint16_t portnr; /* properties */ uint32_t maxframes; @@ -278,7 +276,7 @@ struct EHCIState { */ uint8_t caps[CAPA_SIZE]; union { - uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; + uint32_t opreg[0x44/sizeof(uint32_t)]; struct { uint32_t usbcmd; uint32_t usbsts; @@ -322,7 +320,8 @@ struct EHCIState { extern const VMStateDescription vmstate_ehci; -void usb_ehci_initfn(EHCIState *s, DeviceState *dev); +void usb_ehci_init(EHCIState *s, DeviceState *dev); +void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp); #define TYPE_PCI_EHCI "pci-ehci-usb" #define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI) @@ -338,6 +337,8 @@ typedef struct EHCIPCIState { #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb" +#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb" +#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb" #define SYS_BUS_EHCI(obj) \ OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI) @@ -361,6 +362,19 @@ typedef struct SysBusEHCIClass { uint16_t capsbase; uint16_t opregbase; + uint16_t portscbase; + uint16_t portnr; } SysBusEHCIClass; +#define FUSBH200_EHCI(obj) \ + OBJECT_CHECK(FUSBH200EHCIState, (obj), TYPE_FUSBH200_EHCI) + +typedef struct FUSBH200EHCIState { + /*< private >*/ + EHCISysBusState parent_obj; + /*< public >*/ + + MemoryRegion mem_vendor; +} FUSBH200EHCIState; + #endif diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 3a582c526d..e2f3cc8ade 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -241,7 +241,11 @@ static int usb_host_get_port(libusb_device *dev, char *port, size_t len) size_t off; int rc, i; +#if LIBUSBX_API_VERSION >= 0x01000102 + rc = libusb_get_port_numbers(dev, path, 7); +#else rc = libusb_get_port_path(ctx, dev, path, 7); +#endif if (rc < 0) { return 0; } @@ -891,6 +895,7 @@ static int usb_host_initfn(USBDevice *udev) USBHostDevice *s = USB_HOST_DEVICE(udev); loglevel = s->loglevel; + udev->flags |= (1 << USB_DEV_FLAG_IS_HOST); udev->auto_attach = 0; QTAILQ_INIT(&s->requests); QTAILQ_INIT(&s->isorings); |