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 3 *
4 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 10 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 11 * of this software and associated documentation files (the "Software"), to deal
8 12 * in the Software without restriction, including without limitation the rights
... ... @@ -27,8 +31,7 @@
27 31 #include "qemu-timer.h"
28 32  
29 33 //#define DEBUG
30   -//#define DEBUG_PACKET
31   -//#define DEBUG_ISOCH
  34 +//#define DEBUG_DUMP_DATA
32 35  
33 36 #define UHCI_CMD_FGR (1 << 4)
34 37 #define UHCI_CMD_EGSM (1 << 3)
... ... @@ -66,6 +69,52 @@
66 69  
67 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 118 typedef struct UHCIPort {
70 119 USBPort port;
71 120 uint16_t ctrl;
... ... @@ -85,16 +134,10 @@ typedef struct UHCIState {
85 134  
86 135 /* Interrupts that should be raised at the end of the current frame. */
87 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 141 } UHCIState;
99 142  
100 143 typedef struct UHCI_TD {
... ... @@ -109,6 +152,140 @@ typedef struct UHCI_QH {
109 152 uint32_t el_link;
110 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 289 static void uhci_attach(USBPort *port1, USBDevice *dev);
113 290  
114 291 static void uhci_update_irq(UHCIState *s)
... ... @@ -143,15 +320,18 @@ static void uhci_reset(UHCIState *s)
143 320 s->intr = 0;
144 321 s->fl_base_addr = 0;
145 322 s->sof_timing = 64;
  323 +
146 324 for(i = 0; i < NB_PORTS; i++) {
147 325 port = &s->ports[i];
148 326 port->ctrl = 0x0080;
149 327 if (port->port.dev)
150 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 335 static void uhci_save(QEMUFile *f, void *opaque)
156 336 {
157 337 UHCIState *s = opaque;
... ... @@ -239,9 +419,8 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
239 419 UHCIState *s = opaque;
240 420  
241 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 424 switch(addr) {
246 425 case 0x00:
247 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 529 val = 0xff7f; /* disabled port */
351 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 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 540 UHCIState *s = opaque;
362 541  
363 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 545 switch(addr) {
368 546 case 0x08:
369 547 s->fl_base_addr = val & ~0xfff;
... ... @@ -451,417 +629,406 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
451 629  
452 630 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
453 631 {
454   - UHCIPort *port;
455   - USBDevice *dev;
456 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 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 658 /* return -1 if fatal error (frame must be stopped)
508 659 0 if TD successful
509 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 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 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 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 702 *int_mask |= 0x02;
600 703 /* short packet: do not update QH */
  704 + dprintf("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
601 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 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 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 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 940 le32_to_cpus(&td.link);
661 941 le32_to_cpus(&td.ctrl);
662 942 le32_to_cpus(&td.token);
663 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 950 if (old_td_ctrl != td.ctrl) {
  951 + /* update the status bits of the TD */
669 952 val = cpu_to_le32(td.ctrl);
670 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 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 1002 static void uhci_frame_timer(void *opaque)
733 1003 {
734 1004 UHCIState *s = opaque;
735 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 1007 if (!(s->cmd & UHCI_CMD_RS)) {
  1008 + /* Full stop */
743 1009 qemu_del_timer(s->frame_timer);
744 1010 /* set hchalted bit in status - UHCI11D 2.1.2 */
745 1011 s->status |= UHCI_STS_HCHALTED;
746 1012 return;
747 1013 }
748   - /* Complete the previous frame. */
749   - s->frnum = (s->frnum + 1) & 0x7ff;
  1014 +
  1015 + /* Complete the previous frame */
750 1016 if (s->pending_int_mask) {
751 1017 s->status2 |= s->pending_int_mask;
752   - s->status |= UHCI_STS_USBINT;
  1018 + s->status |= UHCI_STS_USBINT;
753 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 1033 /* prepare the timer for the next frame */
867 1034 expire_time = qemu_get_clock(vm_clock) +
... ... @@ -950,4 +1117,6 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn)
950 1117 to rely on this. */
951 1118 pci_register_io_region(&s->dev, 4, 0x20,
952 1119 PCI_ADDRESS_SPACE_IO, uhci_map);
  1120 +
  1121 + register_savevm("uhci", 0, 1, uhci_save, uhci_load, s);
953 1122 }
... ...