Commit 54f254f973a1b2ed0f3571390f4de060adfe23e8

Authored by aliguori
1 parent 89b9b79f

uhci: rewrite UHCI emulator, fully async operation with multiple outstanding tra…

…nsactions (Max Krasnyansky)

This is esentially a re-write of the QEMU UHCI layer. My initial goal
was to support fully async operation with multiple outstanding async
transactions. Along the way I realized that I can greatly simplify
and cleanup the overall logic. There was a lot of duplicate and confusing
code in the UHCI data structure parsing and other places.
We were actually violating UHCI spec in handling async ISOC transaction
(host controller is not supposed to write into the frame pointer).

The reason I wanted to support fully async operation is because current
synchronous version is unusable with most devices exported from host
(via usb-linux.c). Transactions take a long time and the whole VM becomes
slow as hell.

Current async support is very rudimentory and for the most part
non-functional. Single transaction at a time is simply not enough. I have
a device for which XP driver submits both IN and OUT packets at the same
time. IN packet always times out unless OUT packet makes it to the device.
Hence we must be able to process both in order for that device to work.

The new code is backwards compatible and was first tested agains original
synchronous usb-linux.c and builtin usb devices like tablet which is also
synchronous. Rewrite of the usb-linux.c is coming up next.

Async support was tested against various XP versions (ie XP, SP2, SP3) and
a bunch of different USB devices: serial port controllers, mice, keyboard,
JTAG dongles (from Xilinx and Altera).

ISOC support was only lighly tested and needs more work. It's not any worse
than current code though.

UHCI parser changes are probably somewhat hard to review without the
understanding of the UHCI spec.
The async design should be fairly easy to follow. Basically we have a list
of async objects for each pending transfer. Async objects are tagged with
the original TD (transfer descriptor) address and token. We now support
unlimited number of outstanding isoc and one outstanding bulk/intr/ctrl
transfer per QH (queue head). UHCI spec does not have a clear protocol for
the cancelation of the trasfer requests. Driver can yank out TDs on any
frame boundary. In oder to handle that I added somewhat fancy TD validation
logic logic to avoid unnecessary cancelations.

Signed-off-by: Max Krasnyansky <maxk@kernel.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5050 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 533 additions and 364 deletions
hw/usb-uhci.c
@@ -3,6 +3,10 @@ @@ -3,6 +3,10 @@
3 * 3 *
4 * Copyright (c) 2005 Fabrice Bellard 4 * Copyright (c) 2005 Fabrice Bellard
5 * 5 *
  6 + * Copyright (c) 2008 Max Krasnyansky
  7 + * Magor rewrite of the UHCI data structures parser and frame processor
  8 + * Support for fully async operation and multiple outstanding transactions
  9 + *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal 11 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 12 * in the Software without restriction, including without limitation the rights
@@ -27,8 +31,7 @@ @@ -27,8 +31,7 @@
27 #include "qemu-timer.h" 31 #include "qemu-timer.h"
28 32
29 //#define DEBUG 33 //#define DEBUG
30 -//#define DEBUG_PACKET  
31 -//#define DEBUG_ISOCH 34 +//#define DEBUG_DUMP_DATA
32 35
33 #define UHCI_CMD_FGR (1 << 4) 36 #define UHCI_CMD_FGR (1 << 4)
34 #define UHCI_CMD_EGSM (1 << 3) 37 #define UHCI_CMD_EGSM (1 << 3)
@@ -66,6 +69,52 @@ @@ -66,6 +69,52 @@
66 69
67 #define NB_PORTS 2 70 #define NB_PORTS 2
68 71
  72 +#ifdef DEBUG
  73 +#define dprintf printf
  74 +
  75 +const char *pid2str(int pid)
  76 +{
  77 + switch (pid) {
  78 + case USB_TOKEN_SETUP: return "SETUP";
  79 + case USB_TOKEN_IN: return "IN";
  80 + case USB_TOKEN_OUT: return "OUT";
  81 + }
  82 + return "?";
  83 +}
  84 +
  85 +#else
  86 +#define dprintf(...)
  87 +#endif
  88 +
  89 +#ifdef DEBUG_DUMP_DATA
  90 +static void dump_data(const uint8_t *data, int len)
  91 +{
  92 + int i;
  93 +
  94 + printf("uhci: data: ");
  95 + for(i = 0; i < len; i++)
  96 + printf(" %02x", data[i]);
  97 + printf("\n");
  98 +}
  99 +#else
  100 +static void dump_data(const uint8_t *data, int len) {}
  101 +#endif
  102 +
  103 +/*
  104 + * Pending async transaction.
  105 + * 'packet' must be the first field because completion
  106 + * handler does "(UHCIAsync *) pkt" cast.
  107 + */
  108 +typedef struct UHCIAsync {
  109 + USBPacket packet;
  110 + struct UHCIAsync *next;
  111 + uint32_t td;
  112 + uint32_t token;
  113 + int8_t valid;
  114 + uint8_t done;
  115 + uint8_t buffer[2048];
  116 +} UHCIAsync;
  117 +
69 typedef struct UHCIPort { 118 typedef struct UHCIPort {
70 USBPort port; 119 USBPort port;
71 uint16_t ctrl; 120 uint16_t ctrl;
@@ -85,16 +134,10 @@ typedef struct UHCIState { @@ -85,16 +134,10 @@ typedef struct UHCIState {
85 134
86 /* Interrupts that should be raised at the end of the current frame. */ 135 /* Interrupts that should be raised at the end of the current frame. */
87 uint32_t pending_int_mask; 136 uint32_t pending_int_mask;
88 - /* For simplicity of implementation we only allow a single pending USB  
89 - request. This means all usb traffic on this controller is effectively  
90 - suspended until that transfer completes. When the transfer completes  
91 - the next transfer from that queue will be processed. However  
92 - other queues will not be processed until the next frame. The solution  
93 - is to allow multiple pending requests. */  
94 - uint32_t async_qh;  
95 - uint32_t async_frame_addr;  
96 - USBPacket usb_packet;  
97 - uint8_t usb_buf[2048]; 137 +
  138 + /* Active packets */
  139 + UHCIAsync *async_pending;
  140 + UHCIAsync *async_pool;
98 } UHCIState; 141 } UHCIState;
99 142
100 typedef struct UHCI_TD { 143 typedef struct UHCI_TD {
@@ -109,6 +152,140 @@ typedef struct UHCI_QH { @@ -109,6 +152,140 @@ typedef struct UHCI_QH {
109 uint32_t el_link; 152 uint32_t el_link;
110 } UHCI_QH; 153 } UHCI_QH;
111 154
  155 +static UHCIAsync *uhci_async_alloc(UHCIState *s)
  156 +{
  157 + UHCIAsync *async = qemu_malloc(sizeof(UHCIAsync));
  158 + if (async) {
  159 + memset(&async->packet, 0, sizeof(async->packet));
  160 + async->valid = 0;
  161 + async->td = 0;
  162 + async->token = 0;
  163 + async->done = 0;
  164 + async->next = NULL;
  165 + }
  166 +
  167 + return async;
  168 +}
  169 +
  170 +static void uhci_async_free(UHCIState *s, UHCIAsync *async)
  171 +{
  172 + qemu_free(async);
  173 +}
  174 +
  175 +static void uhci_async_link(UHCIState *s, UHCIAsync *async)
  176 +{
  177 + async->next = s->async_pending;
  178 + s->async_pending = async;
  179 +}
  180 +
  181 +static void uhci_async_unlink(UHCIState *s, UHCIAsync *async)
  182 +{
  183 + UHCIAsync *curr = s->async_pending;
  184 + UHCIAsync **prev = &s->async_pending;
  185 +
  186 + while (curr) {
  187 + if (curr == async) {
  188 + *prev = curr->next;
  189 + return;
  190 + }
  191 +
  192 + prev = &curr->next;
  193 + curr = curr->next;
  194 + }
  195 +}
  196 +
  197 +static void uhci_async_cancel(UHCIState *s, UHCIAsync *async)
  198 +{
  199 + dprintf("uhci: cancel td 0x%x token 0x%x done %u\n",
  200 + async->td, async->token, async->done);
  201 +
  202 + if (!async->done)
  203 + usb_cancel_packet(&async->packet);
  204 + uhci_async_free(s, async);
  205 +}
  206 +
  207 +/*
  208 + * Mark all outstanding async packets as invalid.
  209 + * This is used for canceling them when TDs are removed by the HCD.
  210 + */
  211 +static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
  212 +{
  213 + UHCIAsync *async = s->async_pending;
  214 +
  215 + while (async) {
  216 + async->valid--;
  217 + async = async->next;
  218 + }
  219 + return NULL;
  220 +}
  221 +
  222 +/*
  223 + * Cancel async packets that are no longer valid
  224 + */
  225 +static void uhci_async_validate_end(UHCIState *s)
  226 +{
  227 + UHCIAsync *curr = s->async_pending;
  228 + UHCIAsync **prev = &s->async_pending;
  229 + UHCIAsync *next;
  230 +
  231 + while (curr) {
  232 + if (curr->valid > 0) {
  233 + prev = &curr->next;
  234 + curr = curr->next;
  235 + continue;
  236 + }
  237 +
  238 + next = curr->next;
  239 +
  240 + /* Unlink */
  241 + *prev = next;
  242 +
  243 + uhci_async_cancel(s, curr);
  244 +
  245 + curr = next;
  246 + }
  247 +}
  248 +
  249 +static void uhci_async_cancel_all(UHCIState *s)
  250 +{
  251 + UHCIAsync *curr = s->async_pending;
  252 + UHCIAsync *next;
  253 +
  254 + while (curr) {
  255 + next = curr->next;
  256 +
  257 + uhci_async_cancel(s, curr);
  258 +
  259 + curr = next;
  260 + }
  261 +
  262 + s->async_pending = NULL;
  263 +}
  264 +
  265 +static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token)
  266 +{
  267 + UHCIAsync *async = s->async_pending;
  268 +
  269 + while (async) {
  270 + if (async->td == addr) {
  271 + if (async->token == token)
  272 + return async;
  273 +
  274 + /*
  275 + * TD was reused for a different transfer.
  276 + * Invalidate the original one asap.
  277 + */
  278 + if (async->valid > 0) {
  279 + async->valid = 0;
  280 + dprintf("husb: bad reuse. td 0x%x\n", async->td);
  281 + }
  282 + }
  283 +
  284 + async = async->next;
  285 + }
  286 + return NULL;
  287 +}
  288 +
112 static void uhci_attach(USBPort *port1, USBDevice *dev); 289 static void uhci_attach(USBPort *port1, USBDevice *dev);
113 290
114 static void uhci_update_irq(UHCIState *s) 291 static void uhci_update_irq(UHCIState *s)
@@ -143,15 +320,18 @@ static void uhci_reset(UHCIState *s) @@ -143,15 +320,18 @@ static void uhci_reset(UHCIState *s)
143 s->intr = 0; 320 s->intr = 0;
144 s->fl_base_addr = 0; 321 s->fl_base_addr = 0;
145 s->sof_timing = 64; 322 s->sof_timing = 64;
  323 +
146 for(i = 0; i < NB_PORTS; i++) { 324 for(i = 0; i < NB_PORTS; i++) {
147 port = &s->ports[i]; 325 port = &s->ports[i];
148 port->ctrl = 0x0080; 326 port->ctrl = 0x0080;
149 if (port->port.dev) 327 if (port->port.dev)
150 uhci_attach(&port->port, port->port.dev); 328 uhci_attach(&port->port, port->port.dev);
151 } 329 }
  330 +
  331 + uhci_async_cancel_all(s);
152 } 332 }
153 333
154 -#if 0 334 +#if 1
155 static void uhci_save(QEMUFile *f, void *opaque) 335 static void uhci_save(QEMUFile *f, void *opaque)
156 { 336 {
157 UHCIState *s = opaque; 337 UHCIState *s = opaque;
@@ -239,9 +419,8 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) @@ -239,9 +419,8 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
239 UHCIState *s = opaque; 419 UHCIState *s = opaque;
240 420
241 addr &= 0x1f; 421 addr &= 0x1f;
242 -#ifdef DEBUG  
243 - printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);  
244 -#endif 422 + dprintf("uhci: writew port=0x%04x val=0x%04x\n", addr, val);
  423 +
245 switch(addr) { 424 switch(addr) {
246 case 0x00: 425 case 0x00:
247 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) { 426 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
@@ -350,9 +529,9 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr) @@ -350,9 +529,9 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
350 val = 0xff7f; /* disabled port */ 529 val = 0xff7f; /* disabled port */
351 break; 530 break;
352 } 531 }
353 -#ifdef DEBUG  
354 - printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);  
355 -#endif 532 +
  533 + dprintf("uhci: readw port=0x%04x val=0x%04x\n", addr, val);
  534 +
356 return val; 535 return val;
357 } 536 }
358 537
@@ -361,9 +540,8 @@ static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val) @@ -361,9 +540,8 @@ static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
361 UHCIState *s = opaque; 540 UHCIState *s = opaque;
362 541
363 addr &= 0x1f; 542 addr &= 0x1f;
364 -#ifdef DEBUG  
365 - printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);  
366 -#endif 543 + dprintf("uhci: writel port=0x%04x val=0x%08x\n", addr, val);
  544 +
367 switch(addr) { 545 switch(addr) {
368 case 0x08: 546 case 0x08:
369 s->fl_base_addr = val & ~0xfff; 547 s->fl_base_addr = val & ~0xfff;
@@ -451,417 +629,406 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -451,417 +629,406 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
451 629
452 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p) 630 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
453 { 631 {
454 - UHCIPort *port;  
455 - USBDevice *dev;  
456 int i, ret; 632 int i, ret;
457 633
458 -#ifdef DEBUG_PACKET  
459 - {  
460 - const char *pidstr;  
461 - switch(p->pid) {  
462 - case USB_TOKEN_SETUP: pidstr = "SETUP"; break;  
463 - case USB_TOKEN_IN: pidstr = "IN"; break;  
464 - case USB_TOKEN_OUT: pidstr = "OUT"; break;  
465 - default: pidstr = "?"; break;  
466 - }  
467 - printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",  
468 - s->frnum, pidstr, p->devaddr, p->devep, p->len);  
469 - if (p->pid != USB_TOKEN_IN) {  
470 - printf(" data_out=");  
471 - for(i = 0; i < p->len; i++) {  
472 - printf(" %02x", p->data[i]);  
473 - }  
474 - printf("\n");  
475 - }  
476 - }  
477 -#endif  
478 - for(i = 0; i < NB_PORTS; i++) {  
479 - port = &s->ports[i];  
480 - dev = port->port.dev;  
481 - if (dev && (port->ctrl & UHCI_PORT_EN)) { 634 + dprintf("uhci: packet enter. pid %s addr 0x%02x ep %d len %d\n",
  635 + pid2str(p->pid), p->devaddr, p->devep, p->len);
  636 + if (p->pid == USB_TOKEN_OUT)
  637 + dump_data(p->data, p->len);
  638 +
  639 + ret = USB_RET_NODEV;
  640 + for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) {
  641 + UHCIPort *port = &s->ports[i];
  642 + USBDevice *dev = port->port.dev;
  643 +
  644 + if (dev && (port->ctrl & UHCI_PORT_EN))
482 ret = dev->handle_packet(dev, p); 645 ret = dev->handle_packet(dev, p);
483 - if (ret != USB_RET_NODEV) {  
484 -#ifdef DEBUG_PACKET  
485 - if (ret == USB_RET_ASYNC) {  
486 - printf("usb-uhci: Async packet\n");  
487 - } else {  
488 - printf(" ret=%d ", ret);  
489 - if (p->pid == USB_TOKEN_IN && ret > 0) {  
490 - printf("data_in=");  
491 - for(i = 0; i < ret; i++) {  
492 - printf(" %02x", p->data[i]);  
493 - }  
494 - }  
495 - printf("\n");  
496 - }  
497 -#endif  
498 - return ret;  
499 - }  
500 - }  
501 } 646 }
502 - return USB_RET_NODEV; 647 +
  648 + dprintf("uhci: packet exit. ret %d len %d\n", ret, p->len);
  649 + if (p->pid == USB_TOKEN_IN && ret > 0)
  650 + dump_data(p->data, ret);
  651 +
  652 + return ret;
503 } 653 }
504 654
505 -static void uhci_async_complete_packet(USBPacket * packet, void *opaque); 655 +static void uhci_async_complete(USBPacket * packet, void *opaque);
  656 +static void uhci_process_frame(UHCIState *s);
506 657
507 /* return -1 if fatal error (frame must be stopped) 658 /* return -1 if fatal error (frame must be stopped)
508 0 if TD successful 659 0 if TD successful
509 1 if TD unsuccessful or inactive 660 1 if TD unsuccessful or inactive
510 */ 661 */
511 -static int uhci_handle_td(UHCIState *s, UHCI_TD *td, uint32_t *int_mask,  
512 - int completion) 662 +static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
513 { 663 {
  664 + int len = 0, max_len, err, ret;
514 uint8_t pid; 665 uint8_t pid;
515 - int len = 0, max_len, err, ret = 0;  
516 666
517 - /* ??? This is wrong for async completion. */  
518 - if (td->ctrl & TD_CTRL_IOC) { 667 + max_len = ((td->token >> 21) + 1) & 0x7ff;
  668 + pid = td->token & 0xff;
  669 +
  670 + ret = async->packet.len;
  671 +
  672 + if (td->ctrl & TD_CTRL_IOC)
519 *int_mask |= 0x01; 673 *int_mask |= 0x01;
520 - }  
521 674
522 - if (!(td->ctrl & TD_CTRL_ACTIVE))  
523 - return 1; 675 + if (td->ctrl & TD_CTRL_IOS)
  676 + td->ctrl &= ~TD_CTRL_ACTIVE;
524 677
525 - /* TD is active */  
526 - max_len = ((td->token >> 21) + 1) & 0x7ff;  
527 - pid = td->token & 0xff; 678 + if (ret < 0)
  679 + goto out;
528 680
529 - if (completion && (s->async_qh || s->async_frame_addr)) {  
530 - ret = s->usb_packet.len;  
531 - if (ret >= 0) {  
532 - len = ret;  
533 - if (len > max_len) {  
534 - len = max_len;  
535 - ret = USB_RET_BABBLE;  
536 - }  
537 - if (len > 0) {  
538 - /* write the data back */  
539 - cpu_physical_memory_write(td->buffer, s->usb_buf, len);  
540 - }  
541 - } else {  
542 - len = 0;  
543 - }  
544 - s->async_qh = 0;  
545 - s->async_frame_addr = 0;  
546 - } else if (!completion) {  
547 - s->usb_packet.pid = pid;  
548 - s->usb_packet.devaddr = (td->token >> 8) & 0x7f;  
549 - s->usb_packet.devep = (td->token >> 15) & 0xf;  
550 - s->usb_packet.data = s->usb_buf;  
551 - s->usb_packet.len = max_len;  
552 - s->usb_packet.complete_cb = uhci_async_complete_packet;  
553 - s->usb_packet.complete_opaque = s;  
554 - switch(pid) {  
555 - case USB_TOKEN_OUT:  
556 - case USB_TOKEN_SETUP:  
557 - cpu_physical_memory_read(td->buffer, s->usb_buf, max_len);  
558 - ret = uhci_broadcast_packet(s, &s->usb_packet); 681 + len = async->packet.len;
  682 + td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
  683 +
  684 + /* The NAK bit may have been set by a previous frame, so clear it
  685 + here. The docs are somewhat unclear, but win2k relies on this
  686 + behavior. */
  687 + td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
  688 +
  689 + if (pid == USB_TOKEN_IN) {
  690 + if (len > max_len) {
559 len = max_len; 691 len = max_len;
560 - break;  
561 - case USB_TOKEN_IN:  
562 - ret = uhci_broadcast_packet(s, &s->usb_packet);  
563 - if (ret >= 0) {  
564 - len = ret;  
565 - if (len > max_len) {  
566 - len = max_len;  
567 - ret = USB_RET_BABBLE;  
568 - }  
569 - if (len > 0) {  
570 - /* write the data back */  
571 - cpu_physical_memory_write(td->buffer, s->usb_buf, len);  
572 - }  
573 - } else {  
574 - len = 0;  
575 - }  
576 - break;  
577 - default:  
578 - /* invalid pid : frame interrupted */  
579 - s->status |= UHCI_STS_HCPERR;  
580 - uhci_update_irq(s);  
581 - return -1; 692 + ret = USB_RET_BABBLE;
  693 + goto out;
582 } 694 }
583 - }  
584 695
585 - if (ret == USB_RET_ASYNC) {  
586 - return 2;  
587 - }  
588 - if (td->ctrl & TD_CTRL_IOS)  
589 - td->ctrl &= ~TD_CTRL_ACTIVE;  
590 - if (ret >= 0) {  
591 - td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);  
592 - /* The NAK bit may have been set by a previous frame, so clear it  
593 - here. The docs are somewhat unclear, but win2k relies on this  
594 - behavior. */  
595 - td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);  
596 - if (pid == USB_TOKEN_IN &&  
597 - (td->ctrl & TD_CTRL_SPD) &&  
598 - len < max_len) { 696 + if (len > 0) {
  697 + /* write the data back */
  698 + cpu_physical_memory_write(td->buffer, async->buffer, len);
  699 + }
  700 +
  701 + if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
599 *int_mask |= 0x02; 702 *int_mask |= 0x02;
600 /* short packet: do not update QH */ 703 /* short packet: do not update QH */
  704 + dprintf("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
601 return 1; 705 return 1;
602 - } else {  
603 - /* success */  
604 - return 0;  
605 } 706 }
606 - } else {  
607 - switch(ret) {  
608 - default:  
609 - case USB_RET_NODEV:  
610 - do_timeout:  
611 - td->ctrl |= TD_CTRL_TIMEOUT;  
612 - err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;  
613 - if (err != 0) {  
614 - err--;  
615 - if (err == 0) {  
616 - td->ctrl &= ~TD_CTRL_ACTIVE;  
617 - s->status |= UHCI_STS_USBERR;  
618 - uhci_update_irq(s);  
619 - }  
620 - }  
621 - td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |  
622 - (err << TD_CTRL_ERROR_SHIFT);  
623 - return 1;  
624 - case USB_RET_NAK:  
625 - td->ctrl |= TD_CTRL_NAK;  
626 - if (pid == USB_TOKEN_SETUP)  
627 - goto do_timeout;  
628 - return 1;  
629 - case USB_RET_STALL:  
630 - td->ctrl |= TD_CTRL_STALL;  
631 - td->ctrl &= ~TD_CTRL_ACTIVE;  
632 - return 1;  
633 - case USB_RET_BABBLE:  
634 - td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; 707 + }
  708 +
  709 + /* success */
  710 + return 0;
  711 +
  712 +out:
  713 + switch(ret) {
  714 + case USB_RET_STALL:
  715 + td->ctrl |= TD_CTRL_STALL;
  716 + td->ctrl &= ~TD_CTRL_ACTIVE;
  717 + return 1;
  718 +
  719 + case USB_RET_BABBLE:
  720 + td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
  721 + td->ctrl &= ~TD_CTRL_ACTIVE;
  722 + /* frame interrupted */
  723 + return -1;
  724 +
  725 + case USB_RET_NAK:
  726 + td->ctrl |= TD_CTRL_NAK;
  727 + if (pid == USB_TOKEN_SETUP)
  728 + break;
  729 + return 1;
  730 +
  731 + case USB_RET_NODEV:
  732 + default:
  733 + break;
  734 + }
  735 +
  736 + /* Retry the TD if error count is not zero */
  737 +
  738 + td->ctrl |= TD_CTRL_TIMEOUT;
  739 + err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
  740 + if (err != 0) {
  741 + err--;
  742 + if (err == 0) {
635 td->ctrl &= ~TD_CTRL_ACTIVE; 743 td->ctrl &= ~TD_CTRL_ACTIVE;
636 - /* frame interrupted */  
637 - return -1; 744 + s->status |= UHCI_STS_USBERR;
  745 + uhci_update_irq(s);
638 } 746 }
639 } 747 }
  748 + td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
  749 + (err << TD_CTRL_ERROR_SHIFT);
  750 + return 1;
640 } 751 }
641 752
642 -static void uhci_async_complete_packet(USBPacket * packet, void *opaque) 753 +static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
  754 +{
  755 + UHCIAsync *async;
  756 + int len = 0, max_len, ret = 0;
  757 + uint8_t pid;
  758 +
  759 + /* Is active ? */
  760 + if (!(td->ctrl & TD_CTRL_ACTIVE))
  761 + return 1;
  762 +
  763 + async = uhci_async_find_td(s, addr, td->token);
  764 + if (async) {
  765 + /* Already submitted */
  766 + async->valid = 10;
  767 +
  768 + if (!async->done)
  769 + return 1;
  770 +
  771 + uhci_async_unlink(s, async);
  772 + goto done;
  773 + }
  774 +
  775 + /* Allocate new packet */
  776 + async = uhci_async_alloc(s);
  777 + if (!async)
  778 + return 1;
  779 +
  780 + async->valid = 10;
  781 + async->td = addr;
  782 + async->token = td->token;
  783 +
  784 + max_len = ((td->token >> 21) + 1) & 0x7ff;
  785 + pid = td->token & 0xff;
  786 +
  787 + async->packet.pid = pid;
  788 + async->packet.devaddr = (td->token >> 8) & 0x7f;
  789 + async->packet.devep = (td->token >> 15) & 0xf;
  790 + async->packet.data = async->buffer;
  791 + async->packet.len = max_len;
  792 + async->packet.complete_cb = uhci_async_complete;
  793 + async->packet.complete_opaque = s;
  794 +
  795 + switch(pid) {
  796 + case USB_TOKEN_OUT:
  797 + case USB_TOKEN_SETUP:
  798 + cpu_physical_memory_read(td->buffer, async->buffer, max_len);
  799 + ret = uhci_broadcast_packet(s, &async->packet);
  800 + len = max_len;
  801 + break;
  802 +
  803 + case USB_TOKEN_IN:
  804 + ret = uhci_broadcast_packet(s, &async->packet);
  805 + break;
  806 +
  807 + default:
  808 + /* invalid pid : frame interrupted */
  809 + uhci_async_free(s, async);
  810 + s->status |= UHCI_STS_HCPERR;
  811 + uhci_update_irq(s);
  812 + return -1;
  813 + }
  814 +
  815 + if (ret == USB_RET_ASYNC) {
  816 + uhci_async_link(s, async);
  817 + return 2;
  818 + }
  819 +
  820 + async->packet.len = ret;
  821 +
  822 +done:
  823 + ret = uhci_complete_td(s, td, async, int_mask);
  824 + uhci_async_free(s, async);
  825 + return ret;
  826 +}
  827 +
  828 +static void uhci_async_complete(USBPacket *packet, void *opaque)
643 { 829 {
644 UHCIState *s = opaque; 830 UHCIState *s = opaque;
645 - UHCI_QH qh; 831 + UHCIAsync *async = (UHCIAsync *) packet;
  832 +
  833 + dprintf("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
  834 +
  835 + async->done = 1;
  836 +
  837 + uhci_process_frame(s);
  838 +}
  839 +
  840 +static int is_valid(uint32_t link)
  841 +{
  842 + return (link & 1) == 0;
  843 +}
  844 +
  845 +static int is_qh(uint32_t link)
  846 +{
  847 + return (link & 2) != 0;
  848 +}
  849 +
  850 +static int depth_first(uint32_t link)
  851 +{
  852 + return (link & 4) != 0;
  853 +}
  854 +
  855 +/* QH DB used for detecting QH loops */
  856 +#define UHCI_MAX_QUEUES 128
  857 +typedef struct {
  858 + uint32_t addr[UHCI_MAX_QUEUES];
  859 + int count;
  860 +} QhDb;
  861 +
  862 +static void qhdb_reset(QhDb *db)
  863 +{
  864 + db->count = 0;
  865 +}
  866 +
  867 +/* Add QH to DB. Returns 1 if already present or DB is full. */
  868 +static int qhdb_insert(QhDb *db, uint32_t addr)
  869 +{
  870 + int i;
  871 + for (i = 0; i < db->count; i++)
  872 + if (db->addr[i] == addr)
  873 + return 1;
  874 +
  875 + if (db->count >= UHCI_MAX_QUEUES)
  876 + return 1;
  877 +
  878 + db->addr[db->count++] = addr;
  879 + return 0;
  880 +}
  881 +
  882 +static void uhci_process_frame(UHCIState *s)
  883 +{
  884 + uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
  885 + uint32_t curr_qh;
  886 + int cnt, ret;
646 UHCI_TD td; 887 UHCI_TD td;
647 - uint32_t link;  
648 - uint32_t old_td_ctrl;  
649 - uint32_t val;  
650 - uint32_t frame_addr;  
651 - int ret; 888 + UHCI_QH qh;
  889 + QhDb qhdb;
652 890
653 - /* Handle async isochronous packet completion */  
654 - frame_addr = s->async_frame_addr;  
655 - if (frame_addr) {  
656 - cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);  
657 - le32_to_cpus(&link); 891 + frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
  892 +
  893 + dprintf("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
  894 +
  895 + cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
  896 + le32_to_cpus(&link);
658 897
659 - cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td)); 898 + int_mask = 0;
  899 + curr_qh = 0;
  900 +
  901 + qhdb_reset(&qhdb);
  902 +
  903 + for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
  904 + if (is_qh(link)) {
  905 + /* QH */
  906 +
  907 + if (qhdb_insert(&qhdb, link)) {
  908 + /*
  909 + * We're going in circles. Which is not a bug because
  910 + * HCD is allowed to do that as part of the BW management.
  911 + * In our case though it makes no sense to spin here. Sync transations
  912 + * are already done, and async completion handler will re-process
  913 + * the frame when something is ready.
  914 + */
  915 + dprintf("uhci: detected loop. qh 0x%x\n", link);
  916 + break;
  917 + }
  918 +
  919 + cpu_physical_memory_read(link & ~0xf, (uint8_t *) &qh, sizeof(qh));
  920 + le32_to_cpus(&qh.link);
  921 + le32_to_cpus(&qh.el_link);
  922 +
  923 + dprintf("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
  924 + link, qh.link, qh.el_link);
  925 +
  926 + if (!is_valid(qh.el_link)) {
  927 + /* QH w/o elements */
  928 + curr_qh = 0;
  929 + link = qh.link;
  930 + } else {
  931 + /* QH with elements */
  932 + curr_qh = link;
  933 + link = qh.el_link;
  934 + }
  935 + continue;
  936 + }
  937 +
  938 + /* TD */
  939 + cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
660 le32_to_cpus(&td.link); 940 le32_to_cpus(&td.link);
661 le32_to_cpus(&td.ctrl); 941 le32_to_cpus(&td.ctrl);
662 le32_to_cpus(&td.token); 942 le32_to_cpus(&td.token);
663 le32_to_cpus(&td.buffer); 943 le32_to_cpus(&td.buffer);
664 - old_td_ctrl = td.ctrl;  
665 - ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);  
666 944
667 - /* update the status bits of the TD */ 945 + dprintf("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
  946 + link, td.link, td.ctrl, td.token, curr_qh);
  947 +
  948 + old_td_ctrl = td.ctrl;
  949 + ret = uhci_handle_td(s, link, &td, &int_mask);
668 if (old_td_ctrl != td.ctrl) { 950 if (old_td_ctrl != td.ctrl) {
  951 + /* update the status bits of the TD */
669 val = cpu_to_le32(td.ctrl); 952 val = cpu_to_le32(td.ctrl);
670 cpu_physical_memory_write((link & ~0xf) + 4, 953 cpu_physical_memory_write((link & ~0xf) + 4,
671 - (const uint8_t *)&val,  
672 - sizeof(val)); 954 + (const uint8_t *)&val, sizeof(val));
673 } 955 }
674 - if (ret == 2) {  
675 - s->async_frame_addr = frame_addr;  
676 - } else if (ret == 0) {  
677 - /* update qh element link */  
678 - val = cpu_to_le32(td.link);  
679 - cpu_physical_memory_write(frame_addr,  
680 - (const uint8_t *)&val,  
681 - sizeof(val)); 956 +
  957 + if (ret < 0) {
  958 + /* interrupted frame */
  959 + break;
682 } 960 }
683 - return;  
684 - }  
685 961
686 - link = s->async_qh;  
687 - if (!link) {  
688 - /* This should never happen. It means a TD somehow got removed  
689 - without cancelling the associated async IO request. */  
690 - return;  
691 - }  
692 - cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));  
693 - le32_to_cpus(&qh.link);  
694 - le32_to_cpus(&qh.el_link);  
695 - /* Re-process the queue containing the async packet. */  
696 - while (1) {  
697 - cpu_physical_memory_read(qh.el_link & ~0xf,  
698 - (uint8_t *)&td, sizeof(td));  
699 - le32_to_cpus(&td.link);  
700 - le32_to_cpus(&td.ctrl);  
701 - le32_to_cpus(&td.token);  
702 - le32_to_cpus(&td.buffer);  
703 - old_td_ctrl = td.ctrl;  
704 - ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1); 962 + if (ret == 2 || ret == 1) {
  963 + dprintf("uhci: TD 0x%x %s. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
  964 + link, ret == 2 ? "pend" : "skip",
  965 + td.link, td.ctrl, td.token, curr_qh);
705 966
706 - /* update the status bits of the TD */  
707 - if (old_td_ctrl != td.ctrl) {  
708 - val = cpu_to_le32(td.ctrl);  
709 - cpu_physical_memory_write((qh.el_link & ~0xf) + 4,  
710 - (const uint8_t *)&val,  
711 - sizeof(val)); 967 + link = curr_qh ? qh.link : td.link;
  968 + continue;
712 } 969 }
713 - if (ret < 0)  
714 - break; /* interrupted frame */  
715 - if (ret == 2) {  
716 - s->async_qh = link;  
717 - break;  
718 - } else if (ret == 0) {  
719 - /* update qh element link */  
720 - qh.el_link = td.link; 970 +
  971 + /* completed TD */
  972 +
  973 + dprintf("uhci: TD 0x%x done. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
  974 + link, td.link, td.ctrl, td.token, curr_qh);
  975 +
  976 + link = td.link;
  977 +
  978 + if (curr_qh) {
  979 + /* update QH element link */
  980 + qh.el_link = link;
721 val = cpu_to_le32(qh.el_link); 981 val = cpu_to_le32(qh.el_link);
722 - cpu_physical_memory_write((link & ~0xf) + 4,  
723 - (const uint8_t *)&val,  
724 - sizeof(val));  
725 - if (!(qh.el_link & 4))  
726 - break; 982 + cpu_physical_memory_write((curr_qh & ~0xf) + 4,
  983 + (const uint8_t *)&val, sizeof(val));
  984 +
  985 + if (!depth_first(link)) {
  986 + /* done with this QH */
  987 +
  988 + dprintf("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
  989 + curr_qh, qh.link, qh.el_link);
  990 +
  991 + curr_qh = 0;
  992 + link = qh.link;
  993 + }
727 } 994 }
728 - break; 995 +
  996 + /* go to the next entry */
729 } 997 }
  998 +
  999 + s->pending_int_mask = int_mask;
730 } 1000 }
731 1001
732 static void uhci_frame_timer(void *opaque) 1002 static void uhci_frame_timer(void *opaque)
733 { 1003 {
734 UHCIState *s = opaque; 1004 UHCIState *s = opaque;
735 int64_t expire_time; 1005 int64_t expire_time;
736 - uint32_t frame_addr, link, old_td_ctrl, val, int_mask;  
737 - int cnt, ret;  
738 - UHCI_TD td;  
739 - UHCI_QH qh;  
740 - uint32_t old_async_qh;  
741 1006
742 if (!(s->cmd & UHCI_CMD_RS)) { 1007 if (!(s->cmd & UHCI_CMD_RS)) {
  1008 + /* Full stop */
743 qemu_del_timer(s->frame_timer); 1009 qemu_del_timer(s->frame_timer);
744 /* set hchalted bit in status - UHCI11D 2.1.2 */ 1010 /* set hchalted bit in status - UHCI11D 2.1.2 */
745 s->status |= UHCI_STS_HCHALTED; 1011 s->status |= UHCI_STS_HCHALTED;
746 return; 1012 return;
747 } 1013 }
748 - /* Complete the previous frame. */  
749 - s->frnum = (s->frnum + 1) & 0x7ff; 1014 +
  1015 + /* Complete the previous frame */
750 if (s->pending_int_mask) { 1016 if (s->pending_int_mask) {
751 s->status2 |= s->pending_int_mask; 1017 s->status2 |= s->pending_int_mask;
752 - s->status |= UHCI_STS_USBINT; 1018 + s->status |= UHCI_STS_USBINT;
753 uhci_update_irq(s); 1019 uhci_update_irq(s);
754 } 1020 }
755 - old_async_qh = s->async_qh;  
756 - frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);  
757 - cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);  
758 - le32_to_cpus(&link);  
759 - int_mask = 0;  
760 - cnt = FRAME_MAX_LOOPS;  
761 - while ((link & 1) == 0) {  
762 - if (--cnt == 0)  
763 - break;  
764 - /* valid frame */  
765 - if (link & 2) {  
766 - /* QH */  
767 - if (link == s->async_qh) {  
768 - /* We've found a previously issues packet.  
769 - Nothing else to do. */  
770 - old_async_qh = 0;  
771 - break;  
772 - }  
773 - cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));  
774 - le32_to_cpus(&qh.link);  
775 - le32_to_cpus(&qh.el_link);  
776 - depth_first:  
777 - if (qh.el_link & 1) {  
778 - /* no element : go to next entry */  
779 - link = qh.link;  
780 - } else if (qh.el_link & 2) {  
781 - /* QH */  
782 - link = qh.el_link;  
783 - } else if (s->async_qh) {  
784 - /* We can only cope with one pending packet. Keep looking  
785 - for the previously issued packet. */  
786 - link = qh.link;  
787 - } else {  
788 - /* TD */  
789 - if (--cnt == 0)  
790 - break;  
791 - cpu_physical_memory_read(qh.el_link & ~0xf,  
792 - (uint8_t *)&td, sizeof(td));  
793 - le32_to_cpus(&td.link);  
794 - le32_to_cpus(&td.ctrl);  
795 - le32_to_cpus(&td.token);  
796 - le32_to_cpus(&td.buffer);  
797 - old_td_ctrl = td.ctrl;  
798 - ret = uhci_handle_td(s, &td, &int_mask, 0);  
799 -  
800 - /* update the status bits of the TD */  
801 - if (old_td_ctrl != td.ctrl) {  
802 - val = cpu_to_le32(td.ctrl);  
803 - cpu_physical_memory_write((qh.el_link & ~0xf) + 4,  
804 - (const uint8_t *)&val,  
805 - sizeof(val));  
806 - }  
807 - if (ret < 0)  
808 - break; /* interrupted frame */  
809 - if (ret == 2) {  
810 - s->async_qh = link;  
811 - } else if (ret == 0) {  
812 - /* update qh element link */  
813 - qh.el_link = td.link;  
814 - val = cpu_to_le32(qh.el_link);  
815 - cpu_physical_memory_write((link & ~0xf) + 4,  
816 - (const uint8_t *)&val,  
817 - sizeof(val));  
818 - if (qh.el_link & 4) {  
819 - /* depth first */  
820 - goto depth_first;  
821 - }  
822 - }  
823 - /* go to next entry */  
824 - link = qh.link;  
825 - }  
826 - } else {  
827 - /* TD */  
828 - cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));  
829 - le32_to_cpus(&td.link);  
830 - le32_to_cpus(&td.ctrl);  
831 - le32_to_cpus(&td.token);  
832 - le32_to_cpus(&td.buffer);  
833 -  
834 - /* Handle isochonous transfer. */  
835 - /* FIXME: might be more than one isoc in frame */  
836 - old_td_ctrl = td.ctrl;  
837 - ret = uhci_handle_td(s, &td, &int_mask, 0);  
838 1021
839 - /* update the status bits of the TD */  
840 - if (old_td_ctrl != td.ctrl) {  
841 - val = cpu_to_le32(td.ctrl);  
842 - cpu_physical_memory_write((link & ~0xf) + 4,  
843 - (const uint8_t *)&val,  
844 - sizeof(val));  
845 - }  
846 - if (ret < 0)  
847 - break; /* interrupted frame */  
848 - if (ret == 2) {  
849 - s->async_frame_addr = frame_addr;  
850 - }  
851 - link = td.link;  
852 - }  
853 - }  
854 - s->pending_int_mask = int_mask;  
855 - if (old_async_qh) {  
856 - /* A previously started transfer has disappeared from the transfer  
857 - list. There's nothing useful we can do with it now, so just  
858 - discard the packet and hope it wasn't too important. */  
859 -#ifdef DEBUG  
860 - printf("Discarding USB packet\n");  
861 -#endif  
862 - usb_cancel_packet(&s->usb_packet);  
863 - s->async_qh = 0;  
864 - } 1022 + /* Start new frame */
  1023 + s->frnum = (s->frnum + 1) & 0x7ff;
  1024 +
  1025 + dprintf("uhci: new frame #%u\n" , s->frnum);
  1026 +
  1027 + uhci_async_validate_begin(s);
  1028 +
  1029 + uhci_process_frame(s);
  1030 +
  1031 + uhci_async_validate_end(s);
865 1032
866 /* prepare the timer for the next frame */ 1033 /* prepare the timer for the next frame */
867 expire_time = qemu_get_clock(vm_clock) + 1034 expire_time = qemu_get_clock(vm_clock) +
@@ -950,4 +1117,6 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn) @@ -950,4 +1117,6 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn)
950 to rely on this. */ 1117 to rely on this. */
951 pci_register_io_region(&s->dev, 4, 0x20, 1118 pci_register_io_region(&s->dev, 4, 0x20,
952 PCI_ADDRESS_SPACE_IO, uhci_map); 1119 PCI_ADDRESS_SPACE_IO, uhci_map);
  1120 +
  1121 + register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
953 } 1122 }