diff options
Diffstat (limited to 'hw/usb')
| -rw-r--r-- | hw/usb/bus.c | 5 | ||||
| -rw-r--r-- | hw/usb/core.c | 7 | ||||
| -rw-r--r-- | hw/usb/dev-hid.c | 2 | ||||
| -rw-r--r-- | hw/usb/dev-hub.c | 7 | ||||
| -rw-r--r-- | hw/usb/dev-smartcard-reader.c | 3 | ||||
| -rw-r--r-- | hw/usb/dev-storage.c | 6 | ||||
| -rw-r--r-- | hw/usb/dev-uas.c | 18 | ||||
| -rw-r--r-- | hw/usb/hcd-ehci.c | 2 | ||||
| -rw-r--r-- | hw/usb/hcd-musb.c | 2 | ||||
| -rw-r--r-- | hw/usb/hcd-ohci.c | 2 | ||||
| -rw-r--r-- | hw/usb/hcd-uhci.c | 2 | ||||
| -rw-r--r-- | hw/usb/hcd-xhci.c | 72 |
12 files changed, 94 insertions, 34 deletions
diff --git a/hw/usb/bus.c b/hw/usb/bus.c index f83d1de6cd..82ca6a13e8 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -67,9 +67,10 @@ const VMStateDescription vmstate_usb_device = { } }; -void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host) +void usb_bus_new(USBBus *bus, size_t bus_size, + USBBusOps *ops, DeviceState *host) { - qbus_create_inplace(&bus->qbus, TYPE_USB_BUS, host, NULL); + qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL); bus->ops = ops; bus->busnr = next_usb_bus++; bus->qbus.allow_hotplug = 1; /* Yes, we can */ diff --git a/hw/usb/core.c b/hw/usb/core.c index 05948ca9a4..31960c28a8 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -403,7 +403,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p) p->ep->halted = false; } - if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { + if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline || p->stream) { usb_process_one(p); if (p->status == USB_RET_ASYNC) { /* hcd drivers cannot handle async for isoc */ @@ -420,7 +420,8 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p) * When pipelining is enabled usb-devices must always return async, * otherwise packets can complete out of order! */ - assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue)); + assert(p->stream || !p->ep->pipeline || + QTAILQ_EMPTY(&p->ep->queue)); if (p->status != USB_RET_NAK) { usb_packet_set_state(p, USB_PACKET_COMPLETE); } @@ -434,7 +435,7 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p) { USBEndpoint *ep = p->ep; - assert(QTAILQ_FIRST(&ep->queue) == p); + assert(p->stream || QTAILQ_FIRST(&ep->queue) == p); assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK); if (p->status != USB_RET_SUCCESS || diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 66c63317d6..59567200ae 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -658,7 +658,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) uc->product_desc = "QEMU USB Tablet"; dc->vmsd = &vmstate_usb_ptr; dc->props = usb_tablet_properties; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo usb_tablet_info = { diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index e865a98751..58647b4859 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -33,7 +33,6 @@ typedef struct USBHubPort { USBPort port; uint16_t wPortStatus; uint16_t wPortChange; - uint16_t wPortChange_reported; } USBHubPort; typedef struct USBHubState { @@ -468,13 +467,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) status = 0; for(i = 0; i < NUM_PORTS; i++) { port = &s->ports[i]; - if (port->wPortChange && - port->wPortChange_reported != port->wPortChange) { + if (port->wPortChange) status |= (1 << (i + 1)); - } - port->wPortChange_reported = port->wPortChange; } if (status != 0) { + trace_usb_hub_status_report(s->dev.addr, status); for(i = 0; i < n; i++) { buf[i] = status >> (8 * i); } diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 2233c548fa..8c7a61ebe1 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1309,7 +1309,8 @@ static int ccid_initfn(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL); + qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), + NULL); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); s->bus.qbus.allow_hotplug = 1; s->card = NULL; diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index a8dc2fa960..1d81ac2a6b 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -618,7 +618,8 @@ static int usb_msd_initfn_storage(USBDevice *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_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_storage, NULL); scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, s->conf.bootindex, dev->serial, &err); @@ -646,7 +647,8 @@ static int usb_msd_initfn_bot(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_bot, NULL); s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 63ad12ea6b..70ed2d1dbd 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -113,6 +113,9 @@ struct UASDevice { QTAILQ_HEAD(, UASStatus) results; QTAILQ_HEAD(, UASRequest) requests; + /* properties */ + uint32_t requestlog; + /* usb 2.0 only */ USBPacket *status2; UASRequest *datain2; @@ -692,9 +695,9 @@ static void usb_uas_command(UASDevice *uas, uas_ui *ui) req->req = scsi_req_new(req->dev, req->tag, usb_uas_get_lun(req->lun), ui->command.cdb, req); -#if 1 - scsi_req_print(req->req); -#endif + if (uas->requestlog) { + scsi_req_print(req->req); + } len = scsi_req_enqueue(req->req); if (len) { req->data_size = len; @@ -888,7 +891,8 @@ static int usb_uas_init(USBDevice *dev) QTAILQ_INIT(&uas->requests); uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas); - scsi_bus_new(&uas->bus, &uas->dev.qdev, &usb_uas_scsi_info, NULL); + scsi_bus_new(&uas->bus, sizeof(uas->bus), DEVICE(dev), + &usb_uas_scsi_info, NULL); return 0; } @@ -902,6 +906,11 @@ static const VMStateDescription vmstate_usb_uas = { } }; +static Property uas_properties[] = { + DEFINE_PROP_UINT32("log-scsi-req", UASDevice, requestlog, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void usb_uas_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -919,6 +928,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->fw_name = "storage"; dc->vmsd = &vmstate_usb_uas; + dc->props = uas_properties; } static const TypeInfo uas_info = { diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index e5523d54e0..137e200202 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2520,7 +2520,7 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) return; } - usb_bus_new(&s->bus, &ehci_bus_ops, dev); + usb_bus_new(&s->bus, sizeof(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); diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index f91aa5580b..66bc61ae1e 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -383,7 +383,7 @@ struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base) musb_reset(s); - usb_bus_new(&s->bus, &musb_bus_ops, parent_device); + usb_bus_new(&s->bus, sizeof(s->bus), &musb_bus_ops, parent_device); usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 39a25a72e1..35f0878409 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1881,7 +1881,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, return -1; } } else { - usb_bus_new(&ohci->bus, &ohci_bus_ops, dev); + usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev); for (i = 0; i < num_ports; i++) { usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops, diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 578b949c92..becc7faec1 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1254,7 +1254,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev) return -1; } } else { - usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev); + usb_bus_new(&s->bus, sizeof(s->bus), &uhci_bus_ops, DEVICE(dev)); for (i = 0; i < NB_PORTS; i++) { usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index be6b86e2ba..f02231dc87 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -355,6 +355,7 @@ typedef struct XHCITransfer { unsigned int streamid; bool in_xfer; bool iso_xfer; + bool timed_xfer; unsigned int trb_count; unsigned int trb_alloced; @@ -586,6 +587,14 @@ static const char *TRBCCode_names[] = { [CC_SPLIT_TRANSACTION_ERROR] = "CC_SPLIT_TRANSACTION_ERROR", }; +static const char *ep_state_names[] = { + [EP_DISABLED] = "disabled", + [EP_RUNNING] = "running", + [EP_HALTED] = "halted", + [EP_STOPPED] = "stopped", + [EP_ERROR] = "error", +}; + static const char *lookup_name(uint32_t index, const char **list, uint32_t llen) { if (index >= llen || list[index] == NULL) { @@ -606,6 +615,12 @@ static const char *event_name(XHCIEvent *event) ARRAY_SIZE(TRBCCode_names)); } +static const char *ep_state_name(uint32_t state) +{ + return lookup_name(state, ep_state_names, + ARRAY_SIZE(ep_state_names)); +} + static uint64_t xhci_mfindex_get(XHCIState *xhci) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -1164,8 +1179,6 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx, if (sctx->sct == -1) { xhci_dma_read_u32s(epctx->xhci, sctx->pctx, ctx, sizeof(ctx)); - fprintf(stderr, "%s: init sctx #%d @ " DMA_ADDR_FMT ": %08x %08x\n", - __func__, streamid, sctx->pctx, ctx[0], ctx[1]); sct = (ctx[0] >> 1) & 0x07; if (epctx->lsa && sct != 1) { *cc_error = CC_INVALID_STREAM_TYPE_ERROR; @@ -1205,6 +1218,11 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, } xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); + if (epctx->state != state) { + trace_usb_xhci_ep_state(epctx->slotid, epctx->epid, + ep_state_name(epctx->state), + ep_state_name(state)); + } epctx->state = state; } @@ -1257,7 +1275,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx, epctx->ring.ccs = ctx[2] & 1; } - epctx->interval = 1 << (ctx[0] >> 16) & 0xff; + epctx->interval = 1 << ((ctx[0] >> 16) & 0xff); } static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, @@ -1803,6 +1821,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) xfer->in_xfer = bmRequestType & USB_DIR_IN; xfer->iso_xfer = false; + xfer->timed_xfer = false; if (xhci_setup_packet(xfer) < 0) { return -1; @@ -1818,6 +1837,17 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) return 0; } +static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) +{ + uint64_t asap = ((mfindex + epctx->interval - 1) & + ~(epctx->interval-1)); + uint64_t kick = epctx->mfindex_last + epctx->interval; + + assert(epctx->interval != 0); + xfer->mfindex_kick = MAX(asap, kick); +} + static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx, uint64_t mfindex) { @@ -1840,8 +1870,8 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, } } -static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, - XHCIEPContext *epctx, uint64_t mfindex) +static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) { if (xfer->mfindex_kick > mfindex) { timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + @@ -1866,18 +1896,30 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx switch(epctx->type) { case ET_INTR_OUT: case ET_INTR_IN: + xfer->pkts = 0; + xfer->iso_xfer = false; + xfer->timed_xfer = true; + mfindex = xhci_mfindex_get(xhci); + xhci_calc_intr_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return -1; + } + break; case ET_BULK_OUT: case ET_BULK_IN: xfer->pkts = 0; xfer->iso_xfer = false; + xfer->timed_xfer = false; break; case ET_ISO_OUT: case ET_ISO_IN: xfer->pkts = 1; xfer->iso_xfer = true; + xfer->timed_xfer = true; mfindex = xhci_mfindex_get(xhci); xhci_calc_iso_kick(xhci, xfer, epctx, mfindex); - xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); if (xfer->running_retry) { return -1; } @@ -1938,13 +1980,18 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); - if (xfer->iso_xfer) { - /* retry delayed iso transfer */ + if (xfer->timed_xfer) { + /* time to kick the transfer? */ mfindex = xhci_mfindex_get(xhci); - xhci_check_iso_kick(xhci, xfer, epctx, mfindex); + xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); if (xfer->running_retry) { return; } + xfer->timed_xfer = 0; + xfer->running_retry = 1; + } + if (xfer->iso_xfer) { + /* retry iso transfer */ if (xhci_setup_packet(xfer) < 0) { return; } @@ -2030,7 +2077,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; ep = xfer->packet.ep; } else { - if (!xfer->iso_xfer) { + if (!xfer->timed_xfer) { fprintf(stderr, "xhci: error firing data transfer\n"); } } @@ -2076,6 +2123,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) xhci->slots[slotid-1].enabled = 0; xhci->slots[slotid-1].addressed = 0; + xhci->slots[slotid-1].uport = NULL; return CC_SUCCESS; } @@ -2118,7 +2166,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, int i; TRBCCode res; - trace_usb_xhci_slot_address(slotid); assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); @@ -2151,6 +2198,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, fprintf(stderr, "xhci: port not found\n"); return CC_TRB_ERROR; } + trace_usb_xhci_slot_address(slotid, uport->path); dev = uport->dev; if (!dev) { @@ -3309,7 +3357,7 @@ static void usb_xhci_init(XHCIState *xhci) usbports = MAX(xhci->numports_2, xhci->numports_3); xhci->numports = xhci->numports_2 + xhci->numports_3; - usb_bus_new(&xhci->bus, &xhci_bus_ops, dev); + usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, dev); for (i = 0; i < usbports; i++) { speedmask = 0; |