diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 752e30c305..11bcfae48e 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -477,13 +477,6 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) unsigned int status; uint8_t buf[4]; int i, n; - n = DIV_ROUND_UP(NUM_PORTS + 1, 8); - if (p->iov.size == 1) { /* FreeBSD workaround */ - n = 1; - } else if (n > p->iov.size) { - p->status = USB_RET_BABBLE; - return; - } status = 0; for(i = 0; i < NUM_PORTS; i++) { port = &s->ports[i]; @@ -491,6 +484,13 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) status |= (1 << (i + 1)); } if (status != 0) { + n = DIV_ROUND_UP(NUM_PORTS + 1, 8); + if (p->iov.size == 1) { /* FreeBSD workaround */ + n = 1; + } else if (n > p->iov.size) { + p->status = USB_RET_BABBLE; + return; + } 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/hcd-ohci.c b/hw/usb/hcd-ohci.c index d4c0293db5..fa07bd452c 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1102,17 +1102,19 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } } + if (ret >= 0) { + if ((td.cbp & 0xfff) + ret > 0xfff) { + td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); + } else { + td.cbp += ret; + } + } + /* Writeback */ if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { /* Transmission succeeded. */ if (ret == len) { td.cbp = 0; - } else { - if ((td.cbp & 0xfff) + ret > 0xfff) { - td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); - } else { - td.cbp += ret; - } } td.flags |= OHCI_TD_T1; td.flags ^= OHCI_TD_T0; @@ -1168,6 +1170,8 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) i = OHCI_BM(td.flags, TD_DI); if (i < ohci->done_count) ohci->done_count = i; + if (OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR) + ohci->done_count = 0; exit_no_retire: if (ohci_put_td(ohci, addr, &td)) { ohci_die(ohci);