Loading hw/usb/hcd-ehci.c +77 −84 Original line number Diff line number Diff line Loading @@ -1126,16 +1126,16 @@ static int ehci_init_transfer(EHCIPacket *p) return 0; } static void ehci_finish_transfer(EHCIQueue *q, int status) static void ehci_finish_transfer(EHCIQueue *q, int len) { uint32_t cpage, offset; if (status > 0) { if (len > 0) { /* update cpage & offset */ cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; offset += status; offset += len; cpage += offset >> QTD_BUFPTR_SH; offset &= ~QTD_BUFPTR_MASK; Loading Loading @@ -1168,7 +1168,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) trace_usb_ehci_packet_action(p->queue, p, "wakeup"); p->async = EHCI_ASYNC_FINISHED; p->usb_status = packet->status ? packet->status : packet->actual_length; if (p->queue->async) { qemu_bh_schedule(p->queue->ehci->async_bh); Loading @@ -1178,17 +1177,21 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) static void ehci_execute_complete(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); uint32_t tbytes; assert(p != NULL); assert(p->qtdaddr == q->qtdaddr); assert(p->async == EHCI_ASYNC_INITIALIZED || p->async == EHCI_ASYNC_FINISHED); DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n", q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status); DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, " "status %d, actual_length %d\n", q->qhaddr, q->qh.next, q->qtdaddr, p->packet.status, p->packet.actual_length); if (p->usb_status < 0) { switch (p->usb_status) { switch (p->packet.status) { case USB_RET_SUCCESS: break; case USB_RET_IOERROR: case USB_RET_NODEV: q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); Loading @@ -1208,16 +1211,15 @@ static void ehci_execute_complete(EHCIQueue *q) break; default: /* should not be triggerable */ fprintf(stderr, "USB invalid response %d\n", p->usb_status); fprintf(stderr, "USB invalid response %d\n", p->packet.status); assert(0); break; } } else { // TODO check 4.12 for splits uint32_t tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); /* TODO check 4.12 for splits */ tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); if (tbytes && p->pid == USB_TOKEN_IN) { tbytes -= p->usb_status; tbytes -= p->packet.actual_length; if (tbytes) { /* 4.15.1.2 must raise int on a short input packet */ ehci_raise_irq(q->ehci, USBSTS_INT); Loading @@ -1225,11 +1227,10 @@ static void ehci_execute_complete(EHCIQueue *q) } else { tbytes = 0; } DPRINTF("updating tbytes to %d\n", tbytes); set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); } ehci_finish_transfer(q, p->usb_status); ehci_finish_transfer(q, p->packet.actual_length); usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); p->async = EHCI_ASYNC_NONE; Loading Loading @@ -1321,7 +1322,6 @@ static int ehci_process_itd(EHCIState *ehci, { USBDevice *dev; USBEndpoint *ep; int ret; uint32_t i, len, pid, dir, devaddr, endp; uint32_t pg, off, ptr1, ptr2, max, mult; Loading Loading @@ -1368,18 +1368,19 @@ static int ehci_process_itd(EHCIState *ehci, usb_packet_map(&ehci->ipacket, &ehci->isgl); usb_handle_packet(dev, &ehci->ipacket); usb_packet_unmap(&ehci->ipacket, &ehci->isgl); ret = (ehci->ipacket.status == USB_RET_SUCCESS) ? ehci->ipacket.actual_length : ehci->ipacket.status; } else { DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); ret = USB_RET_NAK; ehci->ipacket.status = USB_RET_NAK; ehci->ipacket.actual_length = 0; } qemu_sglist_destroy(&ehci->isgl); if (ret < 0) { switch (ret) { switch (ehci->ipacket.status) { case USB_RET_SUCCESS: break; default: fprintf(stderr, "Unexpected iso usb result: %d\n", ret); fprintf(stderr, "Unexpected iso usb result: %d\n", ehci->ipacket.status); /* Fall through */ case USB_RET_IOERROR: case USB_RET_NODEV: Loading @@ -1395,18 +1396,15 @@ static int ehci_process_itd(EHCIState *ehci, break; case USB_RET_NAK: /* no data for us, so do a zero-length transfer */ ret = 0; ehci->ipacket.actual_length = 0; break; } } if (ret >= 0) { if (!dir) { /* OUT */ set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH); set_field(&itd->transact[i], len - ehci->ipacket.actual_length, ITD_XACT_LENGTH); /* OUT */ } else { /* IN */ set_field(&itd->transact[i], ret, ITD_XACT_LENGTH); } set_field(&itd->transact[i], ehci->ipacket.actual_length, ITD_XACT_LENGTH); /* IN */ } if (itd->transact[i] & ITD_XACT_IOC) { ehci_raise_irq(ehci, USBSTS_INT); Loading Loading @@ -1862,11 +1860,6 @@ static int ehci_state_execute(EHCIQueue *q) } goto out; } if (p->packet.status == USB_RET_SUCCESS) { p->usb_status = p->packet.actual_length; } else { p->usb_status = p->packet.status; } ehci_set_state(q->ehci, q->async, EST_EXECUTING); again = 1; Loading @@ -1890,7 +1883,7 @@ static int ehci_state_executing(EHCIQueue *q) } /* 4.10.5 */ if (p->usb_status == USB_RET_NAK) { if (p->packet.status == USB_RET_NAK) { ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { ehci_set_state(q->ehci, q->async, EST_WRITEBACK); Loading hw/usb/hcd-ehci.h +0 −1 Original line number Diff line number Diff line Loading @@ -230,7 +230,6 @@ struct EHCIPacket { QEMUSGList sgl; int pid; enum async_state async; int usb_status; }; struct EHCIQueue { Loading Loading
hw/usb/hcd-ehci.c +77 −84 Original line number Diff line number Diff line Loading @@ -1126,16 +1126,16 @@ static int ehci_init_transfer(EHCIPacket *p) return 0; } static void ehci_finish_transfer(EHCIQueue *q, int status) static void ehci_finish_transfer(EHCIQueue *q, int len) { uint32_t cpage, offset; if (status > 0) { if (len > 0) { /* update cpage & offset */ cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; offset += status; offset += len; cpage += offset >> QTD_BUFPTR_SH; offset &= ~QTD_BUFPTR_MASK; Loading Loading @@ -1168,7 +1168,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) trace_usb_ehci_packet_action(p->queue, p, "wakeup"); p->async = EHCI_ASYNC_FINISHED; p->usb_status = packet->status ? packet->status : packet->actual_length; if (p->queue->async) { qemu_bh_schedule(p->queue->ehci->async_bh); Loading @@ -1178,17 +1177,21 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) static void ehci_execute_complete(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); uint32_t tbytes; assert(p != NULL); assert(p->qtdaddr == q->qtdaddr); assert(p->async == EHCI_ASYNC_INITIALIZED || p->async == EHCI_ASYNC_FINISHED); DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n", q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status); DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, " "status %d, actual_length %d\n", q->qhaddr, q->qh.next, q->qtdaddr, p->packet.status, p->packet.actual_length); if (p->usb_status < 0) { switch (p->usb_status) { switch (p->packet.status) { case USB_RET_SUCCESS: break; case USB_RET_IOERROR: case USB_RET_NODEV: q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); Loading @@ -1208,16 +1211,15 @@ static void ehci_execute_complete(EHCIQueue *q) break; default: /* should not be triggerable */ fprintf(stderr, "USB invalid response %d\n", p->usb_status); fprintf(stderr, "USB invalid response %d\n", p->packet.status); assert(0); break; } } else { // TODO check 4.12 for splits uint32_t tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); /* TODO check 4.12 for splits */ tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); if (tbytes && p->pid == USB_TOKEN_IN) { tbytes -= p->usb_status; tbytes -= p->packet.actual_length; if (tbytes) { /* 4.15.1.2 must raise int on a short input packet */ ehci_raise_irq(q->ehci, USBSTS_INT); Loading @@ -1225,11 +1227,10 @@ static void ehci_execute_complete(EHCIQueue *q) } else { tbytes = 0; } DPRINTF("updating tbytes to %d\n", tbytes); set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); } ehci_finish_transfer(q, p->usb_status); ehci_finish_transfer(q, p->packet.actual_length); usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); p->async = EHCI_ASYNC_NONE; Loading Loading @@ -1321,7 +1322,6 @@ static int ehci_process_itd(EHCIState *ehci, { USBDevice *dev; USBEndpoint *ep; int ret; uint32_t i, len, pid, dir, devaddr, endp; uint32_t pg, off, ptr1, ptr2, max, mult; Loading Loading @@ -1368,18 +1368,19 @@ static int ehci_process_itd(EHCIState *ehci, usb_packet_map(&ehci->ipacket, &ehci->isgl); usb_handle_packet(dev, &ehci->ipacket); usb_packet_unmap(&ehci->ipacket, &ehci->isgl); ret = (ehci->ipacket.status == USB_RET_SUCCESS) ? ehci->ipacket.actual_length : ehci->ipacket.status; } else { DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); ret = USB_RET_NAK; ehci->ipacket.status = USB_RET_NAK; ehci->ipacket.actual_length = 0; } qemu_sglist_destroy(&ehci->isgl); if (ret < 0) { switch (ret) { switch (ehci->ipacket.status) { case USB_RET_SUCCESS: break; default: fprintf(stderr, "Unexpected iso usb result: %d\n", ret); fprintf(stderr, "Unexpected iso usb result: %d\n", ehci->ipacket.status); /* Fall through */ case USB_RET_IOERROR: case USB_RET_NODEV: Loading @@ -1395,18 +1396,15 @@ static int ehci_process_itd(EHCIState *ehci, break; case USB_RET_NAK: /* no data for us, so do a zero-length transfer */ ret = 0; ehci->ipacket.actual_length = 0; break; } } if (ret >= 0) { if (!dir) { /* OUT */ set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH); set_field(&itd->transact[i], len - ehci->ipacket.actual_length, ITD_XACT_LENGTH); /* OUT */ } else { /* IN */ set_field(&itd->transact[i], ret, ITD_XACT_LENGTH); } set_field(&itd->transact[i], ehci->ipacket.actual_length, ITD_XACT_LENGTH); /* IN */ } if (itd->transact[i] & ITD_XACT_IOC) { ehci_raise_irq(ehci, USBSTS_INT); Loading Loading @@ -1862,11 +1860,6 @@ static int ehci_state_execute(EHCIQueue *q) } goto out; } if (p->packet.status == USB_RET_SUCCESS) { p->usb_status = p->packet.actual_length; } else { p->usb_status = p->packet.status; } ehci_set_state(q->ehci, q->async, EST_EXECUTING); again = 1; Loading @@ -1890,7 +1883,7 @@ static int ehci_state_executing(EHCIQueue *q) } /* 4.10.5 */ if (p->usb_status == USB_RET_NAK) { if (p->packet.status == USB_RET_NAK) { ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { ehci_set_state(q->ehci, q->async, EST_WRITEBACK); Loading
hw/usb/hcd-ehci.h +0 −1 Original line number Diff line number Diff line Loading @@ -230,7 +230,6 @@ struct EHCIPacket { QEMUSGList sgl; int pid; enum async_state async; int usb_status; }; struct EHCIQueue { Loading