[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) {
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_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
return (now - xhci->mfindex_start) / 125000;
}
int64_t now;
if ((xhci->usbcmd & bits) == bits) {
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
mfindex = ((now - xhci->mfindex_start) / 125000) & 0x3fff;
left = 0x4000 - mfindex;
- qemu_mod_timer(xhci->mfwrap_timer, now + left * 125000);
+ timer_mod(xhci->mfwrap_timer, now + left * 125000);
} else {
- qemu_del_timer(xhci->mfwrap_timer);
+ timer_del(xhci->mfwrap_timer);
}
}
{
trace_usb_xhci_run();
xhci->usbsts &= ~USBSTS_HCH;
- xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
+ xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static void xhci_stop(XHCIState *xhci)
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;
}
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;
}
for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
usb_packet_init(&epctx->transfers[i].packet);
}
- epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx);
+ epctx->kick_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_ep_kick_timer, epctx);
return epctx;
}
XHCIEPContext *epctx = t->xhci->slots[t->slotid-1].eps[t->epid-1];
if (epctx) {
epctx->retry = NULL;
- qemu_del_timer(epctx->kick_timer);
+ timer_del(epctx->kick_timer);
}
t->running_retry = 0;
}
xhci_set_ep_state(xhci, epctx, NULL, EP_DISABLED);
- qemu_free_timer(epctx->kick_timer);
+ timer_free(epctx->kick_timer);
g_free(epctx);
slot->eps[epid-1] = NULL;
{
XHCISlot *slot;
XHCIEPContext *epctx;
- USBDevice *dev;
trace_usb_xhci_ep_reset(slotid, epid);
assert(slotid >= 1 && slotid <= xhci->numslots);
ep |= 0x80;
}
- dev = xhci->slots[slotid-1].uport->dev;
- if (!dev) {
+ if (!xhci->slots[slotid-1].uport ||
+ !xhci->slots[slotid-1].uport->dev) {
return CC_USB_TRANSACTION_ERROR;
}
trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
switch (xfer->packet.status) {
case USB_RET_NODEV:
+ case USB_RET_IOERROR:
xfer->status = CC_USB_TRANSACTION_ERROR;
xhci_xfer_report(xfer);
xhci_stall_ep(xfer);
XHCIEPContext *epctx, uint64_t mfindex)
{
if (xfer->mfindex_kick > mfindex) {
- qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(xfer->mfindex_kick - mfindex) * 125000);
xfer->running_retry = 1;
} else {
epctx->mfindex_last = xfer->mfindex_kick;
- qemu_del_timer(epctx->kick_timer);
+ timer_del(epctx->kick_timer);
xfer->running_retry = 0;
}
}
xhci_port_notify(port, PORTSC_CSC);
}
-static void xhci_port_reset(XHCIPort *port)
+static void xhci_port_reset(XHCIPort *port, bool warm_reset)
{
trace_usb_xhci_port_reset(port->portnr);
usb_device_reset(port->uport->dev);
switch (port->uport->dev->speed) {
+ case USB_SPEED_SUPER:
+ if (warm_reset) {
+ port->portsc |= PORTSC_WRC;
+ }
+ /* fall through */
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
xhci->intr[i].ev_buffer_get = 0;
}
- xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
+ xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
xhci_mfwrap_update(xhci);
}
switch (reg) {
case 0x00: /* PORTSC */
/* write-1-to-start bits */
+ if (val & PORTSC_WPR) {
+ xhci_port_reset(port, true);
+ break;
+ }
if (val & PORTSC_PR) {
- xhci_port_reset(port);
+ xhci_port_reset(port, false);
break;
}
xhci->numslots = 1;
}
- xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci);
+ xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
xhci->irq = dev->irq[0];
epctx->state = state;
if (state == EP_RUNNING) {
/* kick endpoint after vmload is finished */
- qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock));
+ timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
}
}
dc->vmsd = &vmstate_xhci;
dc->props = xhci_properties;
dc->reset = xhci_reset;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
k->init = usb_xhci_initfn;
k->vendor_id = PCI_VENDOR_ID_NEC;
k->device_id = PCI_DEVICE_ID_NEC_UPD720200;