]> git.proxmox.com Git - qemu.git/blame - hw/usb-uhci.c
sd.c build fix.
[qemu.git] / hw / usb-uhci.c
CommitLineData
bb36d470
FB
1/*
2 * USB UHCI controller emulation
5fafdf24 3 *
bb36d470 4 * Copyright (c) 2005 Fabrice Bellard
5fafdf24 5 *
bb36d470
FB
6 * 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
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include "vl.h"
25
26//#define DEBUG
27//#define DEBUG_PACKET
b9dc033c 28//#define DEBUG_ISOCH
bb36d470 29
96217e31
TS
30#define UHCI_CMD_FGR (1 << 4)
31#define UHCI_CMD_EGSM (1 << 3)
bb36d470
FB
32#define UHCI_CMD_GRESET (1 << 2)
33#define UHCI_CMD_HCRESET (1 << 1)
34#define UHCI_CMD_RS (1 << 0)
35
36#define UHCI_STS_HCHALTED (1 << 5)
37#define UHCI_STS_HCPERR (1 << 4)
38#define UHCI_STS_HSERR (1 << 3)
39#define UHCI_STS_RD (1 << 2)
40#define UHCI_STS_USBERR (1 << 1)
41#define UHCI_STS_USBINT (1 << 0)
42
43#define TD_CTRL_SPD (1 << 29)
44#define TD_CTRL_ERROR_SHIFT 27
45#define TD_CTRL_IOS (1 << 25)
46#define TD_CTRL_IOC (1 << 24)
47#define TD_CTRL_ACTIVE (1 << 23)
48#define TD_CTRL_STALL (1 << 22)
49#define TD_CTRL_BABBLE (1 << 20)
50#define TD_CTRL_NAK (1 << 19)
51#define TD_CTRL_TIMEOUT (1 << 18)
52
53#define UHCI_PORT_RESET (1 << 9)
54#define UHCI_PORT_LSDA (1 << 8)
55#define UHCI_PORT_ENC (1 << 3)
56#define UHCI_PORT_EN (1 << 2)
57#define UHCI_PORT_CSC (1 << 1)
58#define UHCI_PORT_CCS (1 << 0)
59
60#define FRAME_TIMER_FREQ 1000
61
62#define FRAME_MAX_LOOPS 100
63
64#define NB_PORTS 2
65
66typedef struct UHCIPort {
67 USBPort port;
68 uint16_t ctrl;
bb36d470
FB
69} UHCIPort;
70
71typedef struct UHCIState {
72 PCIDevice dev;
73 uint16_t cmd; /* cmd register */
74 uint16_t status;
75 uint16_t intr; /* interrupt enable register */
76 uint16_t frnum; /* frame number */
77 uint32_t fl_base_addr; /* frame list base address */
78 uint8_t sof_timing;
79 uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
80 QEMUTimer *frame_timer;
81 UHCIPort ports[NB_PORTS];
4d611c9a
PB
82
83 /* Interrupts that should be raised at the end of the current frame. */
84 uint32_t pending_int_mask;
85 /* For simplicity of implementation we only allow a single pending USB
86 request. This means all usb traffic on this controller is effectively
87 suspended until that transfer completes. When the transfer completes
5fafdf24 88 the next transfer from that queue will be processed. However
4d611c9a
PB
89 other queues will not be processed until the next frame. The solution
90 is to allow multiple pending requests. */
91 uint32_t async_qh;
b9dc033c 92 uint32_t async_frame_addr;
4d611c9a 93 USBPacket usb_packet;
81822663 94 uint8_t usb_buf[2048];
bb36d470
FB
95} UHCIState;
96
97typedef struct UHCI_TD {
98 uint32_t link;
99 uint32_t ctrl; /* see TD_CTRL_xxx */
100 uint32_t token;
101 uint32_t buffer;
102} UHCI_TD;
103
104typedef struct UHCI_QH {
105 uint32_t link;
106 uint32_t el_link;
107} UHCI_QH;
108
109static void uhci_attach(USBPort *port1, USBDevice *dev);
110
111static void uhci_update_irq(UHCIState *s)
112{
113 int level;
114 if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
115 ((s->status2 & 2) && (s->intr & (1 << 3))) ||
116 ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
117 ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
118 (s->status & UHCI_STS_HSERR) ||
119 (s->status & UHCI_STS_HCPERR)) {
120 level = 1;
121 } else {
122 level = 0;
123 }
d537cf6c 124 qemu_set_irq(s->dev.irq[3], level);
bb36d470
FB
125}
126
127static void uhci_reset(UHCIState *s)
128{
129 uint8_t *pci_conf;
130 int i;
131 UHCIPort *port;
132
133 pci_conf = s->dev.config;
134
135 pci_conf[0x6a] = 0x01; /* usb clock */
136 pci_conf[0x6b] = 0x00;
137 s->cmd = 0;
138 s->status = 0;
139 s->status2 = 0;
140 s->intr = 0;
141 s->fl_base_addr = 0;
142 s->sof_timing = 64;
143 for(i = 0; i < NB_PORTS; i++) {
144 port = &s->ports[i];
145 port->ctrl = 0x0080;
a594cfbf
FB
146 if (port->port.dev)
147 uhci_attach(&port->port, port->port.dev);
bb36d470
FB
148 }
149}
150
1e414679 151#if 0
b9dc033c
AZ
152static void uhci_save(QEMUFile *f, void *opaque)
153{
154 UHCIState *s = opaque;
155 uint8_t num_ports = NB_PORTS;
156 int i;
157
158 pci_device_save(&s->dev, f);
159
160 qemu_put_8s(f, &num_ports);
161 for (i = 0; i < num_ports; ++i)
162 qemu_put_be16s(f, &s->ports[i].ctrl);
163 qemu_put_be16s(f, &s->cmd);
164 qemu_put_be16s(f, &s->status);
165 qemu_put_be16s(f, &s->intr);
166 qemu_put_be16s(f, &s->frnum);
167 qemu_put_be32s(f, &s->fl_base_addr);
168 qemu_put_8s(f, &s->sof_timing);
169 qemu_put_8s(f, &s->status2);
170 qemu_put_timer(f, s->frame_timer);
171}
172
173static int uhci_load(QEMUFile *f, void *opaque, int version_id)
174{
175 UHCIState *s = opaque;
176 uint8_t num_ports;
177 int i, ret;
178
179 if (version_id > 1)
180 return -EINVAL;
181
182 ret = pci_device_load(&s->dev, f);
183 if (ret < 0)
184 return ret;
185
186 qemu_get_8s(f, &num_ports);
187 if (num_ports != NB_PORTS)
188 return -EINVAL;
189
190 for (i = 0; i < num_ports; ++i)
191 qemu_get_be16s(f, &s->ports[i].ctrl);
192 qemu_get_be16s(f, &s->cmd);
193 qemu_get_be16s(f, &s->status);
194 qemu_get_be16s(f, &s->intr);
195 qemu_get_be16s(f, &s->frnum);
196 qemu_get_be32s(f, &s->fl_base_addr);
197 qemu_get_8s(f, &s->sof_timing);
198 qemu_get_8s(f, &s->status2);
199 qemu_get_timer(f, s->frame_timer);
200
201 return 0;
202}
1e414679 203#endif
b9dc033c 204
bb36d470
FB
205static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
206{
207 UHCIState *s = opaque;
3b46e624 208
bb36d470
FB
209 addr &= 0x1f;
210 switch(addr) {
211 case 0x0c:
212 s->sof_timing = val;
213 break;
214 }
215}
216
217static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
218{
219 UHCIState *s = opaque;
220 uint32_t val;
221
222 addr &= 0x1f;
223 switch(addr) {
224 case 0x0c:
225 val = s->sof_timing;
d80cfb3f 226 break;
bb36d470
FB
227 default:
228 val = 0xff;
229 break;
230 }
231 return val;
232}
233
234static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
235{
236 UHCIState *s = opaque;
3b46e624 237
bb36d470
FB
238 addr &= 0x1f;
239#ifdef DEBUG
240 printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);
241#endif
242 switch(addr) {
243 case 0x00:
244 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
245 /* start frame processing */
246 qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
52328140 247 s->status &= ~UHCI_STS_HCHALTED;
467d409f 248 } else if (!(val & UHCI_CMD_RS)) {
52328140 249 s->status |= UHCI_STS_HCHALTED;
bb36d470
FB
250 }
251 if (val & UHCI_CMD_GRESET) {
252 UHCIPort *port;
253 USBDevice *dev;
254 int i;
255
256 /* send reset on the USB bus */
257 for(i = 0; i < NB_PORTS; i++) {
258 port = &s->ports[i];
a594cfbf 259 dev = port->port.dev;
bb36d470 260 if (dev) {
4d611c9a 261 usb_send_msg(dev, USB_MSG_RESET);
bb36d470
FB
262 }
263 }
264 uhci_reset(s);
265 return;
266 }
5e9ab4c4 267 if (val & UHCI_CMD_HCRESET) {
bb36d470
FB
268 uhci_reset(s);
269 return;
270 }
271 s->cmd = val;
272 break;
273 case 0x02:
274 s->status &= ~val;
275 /* XXX: the chip spec is not coherent, so we add a hidden
276 register to distinguish between IOC and SPD */
277 if (val & UHCI_STS_USBINT)
278 s->status2 = 0;
279 uhci_update_irq(s);
280 break;
281 case 0x04:
282 s->intr = val;
283 uhci_update_irq(s);
284 break;
285 case 0x06:
286 if (s->status & UHCI_STS_HCHALTED)
287 s->frnum = val & 0x7ff;
288 break;
289 case 0x10 ... 0x1f:
290 {
291 UHCIPort *port;
292 USBDevice *dev;
293 int n;
294
295 n = (addr >> 1) & 7;
296 if (n >= NB_PORTS)
297 return;
298 port = &s->ports[n];
a594cfbf 299 dev = port->port.dev;
bb36d470
FB
300 if (dev) {
301 /* port reset */
5fafdf24 302 if ( (val & UHCI_PORT_RESET) &&
bb36d470 303 !(port->ctrl & UHCI_PORT_RESET) ) {
4d611c9a 304 usb_send_msg(dev, USB_MSG_RESET);
bb36d470
FB
305 }
306 }
307 port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
308 /* some bits are reset when a '1' is written to them */
309 port->ctrl &= ~(val & 0x000a);
310 }
311 break;
312 }
313}
314
315static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
316{
317 UHCIState *s = opaque;
318 uint32_t val;
319
320 addr &= 0x1f;
321 switch(addr) {
322 case 0x00:
323 val = s->cmd;
324 break;
325 case 0x02:
326 val = s->status;
327 break;
328 case 0x04:
329 val = s->intr;
330 break;
331 case 0x06:
332 val = s->frnum;
333 break;
334 case 0x10 ... 0x1f:
335 {
336 UHCIPort *port;
337 int n;
338 n = (addr >> 1) & 7;
5fafdf24 339 if (n >= NB_PORTS)
bb36d470
FB
340 goto read_default;
341 port = &s->ports[n];
342 val = port->ctrl;
343 }
344 break;
345 default:
346 read_default:
347 val = 0xff7f; /* disabled port */
348 break;
349 }
350#ifdef DEBUG
351 printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);
352#endif
353 return val;
354}
355
356static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
357{
358 UHCIState *s = opaque;
359
360 addr &= 0x1f;
361#ifdef DEBUG
362 printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);
363#endif
364 switch(addr) {
365 case 0x08:
366 s->fl_base_addr = val & ~0xfff;
367 break;
368 }
369}
370
371static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
372{
373 UHCIState *s = opaque;
374 uint32_t val;
375
376 addr &= 0x1f;
377 switch(addr) {
378 case 0x08:
379 val = s->fl_base_addr;
380 break;
381 default:
382 val = 0xffffffff;
383 break;
384 }
385 return val;
386}
387
96217e31
TS
388/* signal resume if controller suspended */
389static void uhci_resume (void *opaque)
390{
391 UHCIState *s = (UHCIState *)opaque;
392
393 if (!s)
394 return;
395
396 if (s->cmd & UHCI_CMD_EGSM) {
397 s->cmd |= UHCI_CMD_FGR;
398 s->status |= UHCI_STS_RD;
399 uhci_update_irq(s);
400 }
401}
402
bb36d470
FB
403static void uhci_attach(USBPort *port1, USBDevice *dev)
404{
405 UHCIState *s = port1->opaque;
406 UHCIPort *port = &s->ports[port1->index];
407
408 if (dev) {
a594cfbf 409 if (port->port.dev) {
bb36d470
FB
410 usb_attach(port1, NULL);
411 }
412 /* set connect status */
61064870
PB
413 port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
414
bb36d470
FB
415 /* update speed */
416 if (dev->speed == USB_SPEED_LOW)
417 port->ctrl |= UHCI_PORT_LSDA;
418 else
419 port->ctrl &= ~UHCI_PORT_LSDA;
96217e31
TS
420
421 uhci_resume(s);
422
a594cfbf 423 port->port.dev = dev;
bb36d470 424 /* send the attach message */
4d611c9a 425 usb_send_msg(dev, USB_MSG_ATTACH);
bb36d470
FB
426 } else {
427 /* set connect status */
61064870
PB
428 if (port->ctrl & UHCI_PORT_CCS) {
429 port->ctrl &= ~UHCI_PORT_CCS;
430 port->ctrl |= UHCI_PORT_CSC;
bb36d470
FB
431 }
432 /* disable port */
433 if (port->ctrl & UHCI_PORT_EN) {
434 port->ctrl &= ~UHCI_PORT_EN;
435 port->ctrl |= UHCI_PORT_ENC;
436 }
96217e31
TS
437
438 uhci_resume(s);
439
a594cfbf 440 dev = port->port.dev;
bb36d470
FB
441 if (dev) {
442 /* send the detach message */
4d611c9a 443 usb_send_msg(dev, USB_MSG_DETACH);
bb36d470 444 }
a594cfbf 445 port->port.dev = NULL;
bb36d470
FB
446 }
447}
448
4d611c9a 449static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
bb36d470
FB
450{
451 UHCIPort *port;
452 USBDevice *dev;
453 int i, ret;
454
455#ifdef DEBUG_PACKET
456 {
457 const char *pidstr;
4d611c9a 458 switch(p->pid) {
bb36d470
FB
459 case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
460 case USB_TOKEN_IN: pidstr = "IN"; break;
461 case USB_TOKEN_OUT: pidstr = "OUT"; break;
462 default: pidstr = "?"; break;
463 }
464 printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
4d611c9a
PB
465 s->frnum, pidstr, p->devaddr, p->devep, p->len);
466 if (p->pid != USB_TOKEN_IN) {
bb36d470 467 printf(" data_out=");
4d611c9a
PB
468 for(i = 0; i < p->len; i++) {
469 printf(" %02x", p->data[i]);
bb36d470
FB
470 }
471 printf("\n");
472 }
473 }
474#endif
475 for(i = 0; i < NB_PORTS; i++) {
476 port = &s->ports[i];
a594cfbf 477 dev = port->port.dev;
bb36d470 478 if (dev && (port->ctrl & UHCI_PORT_EN)) {
4d611c9a 479 ret = dev->handle_packet(dev, p);
bb36d470
FB
480 if (ret != USB_RET_NODEV) {
481#ifdef DEBUG_PACKET
4d611c9a
PB
482 if (ret == USB_RET_ASYNC) {
483 printf("usb-uhci: Async packet\n");
484 } else {
bb36d470 485 printf(" ret=%d ", ret);
4d611c9a 486 if (p->pid == USB_TOKEN_IN && ret > 0) {
bb36d470
FB
487 printf("data_in=");
488 for(i = 0; i < ret; i++) {
4d611c9a 489 printf(" %02x", p->data[i]);
bb36d470
FB
490 }
491 }
492 printf("\n");
493 }
494#endif
495 return ret;
496 }
497 }
498 }
499 return USB_RET_NODEV;
500}
501
4d611c9a
PB
502static void uhci_async_complete_packet(USBPacket * packet, void *opaque);
503
bb36d470
FB
504/* return -1 if fatal error (frame must be stopped)
505 0 if TD successful
506 1 if TD unsuccessful or inactive
507*/
b9dc033c
AZ
508static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask,
509 int completion)
bb36d470
FB
510{
511 uint8_t pid;
b9dc033c 512 int len = 0, max_len, err, ret = 0;
bb36d470 513
4d611c9a 514 /* ??? This is wrong for async completion. */
bb36d470
FB
515 if (td->ctrl & TD_CTRL_IOC) {
516 *int_mask |= 0x01;
517 }
3b46e624 518
bb36d470
FB
519 if (!(td->ctrl & TD_CTRL_ACTIVE))
520 return 1;
521
522 /* TD is active */
523 max_len = ((td->token >> 21) + 1) & 0x7ff;
524 pid = td->token & 0xff;
b9dc033c
AZ
525
526 if (completion && (s->async_qh || s->async_frame_addr)) {
4d611c9a 527 ret = s->usb_packet.len;
bb36d470
FB
528 if (ret >= 0) {
529 len = ret;
530 if (len > max_len) {
531 len = max_len;
532 ret = USB_RET_BABBLE;
533 }
534 if (len > 0) {
535 /* write the data back */
4d611c9a 536 cpu_physical_memory_write(td->buffer, s->usb_buf, len);
bb36d470
FB
537 }
538 } else {
539 len = 0;
540 }
4d611c9a 541 s->async_qh = 0;
b9dc033c
AZ
542 s->async_frame_addr = 0;
543 } else if (!completion) {
4d611c9a
PB
544 s->usb_packet.pid = pid;
545 s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
546 s->usb_packet.devep = (td->token >> 15) & 0xf;
547 s->usb_packet.data = s->usb_buf;
548 s->usb_packet.len = max_len;
549 s->usb_packet.complete_cb = uhci_async_complete_packet;
550 s->usb_packet.complete_opaque = s;
551 switch(pid) {
552 case USB_TOKEN_OUT:
553 case USB_TOKEN_SETUP:
554 cpu_physical_memory_read(td->buffer, s->usb_buf, max_len);
555 ret = uhci_broadcast_packet(s, &s->usb_packet);
556 len = max_len;
557 break;
558 case USB_TOKEN_IN:
559 ret = uhci_broadcast_packet(s, &s->usb_packet);
560 if (ret >= 0) {
561 len = ret;
562 if (len > max_len) {
563 len = max_len;
564 ret = USB_RET_BABBLE;
565 }
566 if (len > 0) {
567 /* write the data back */
568 cpu_physical_memory_write(td->buffer, s->usb_buf, len);
569 }
570 } else {
571 len = 0;
572 }
573 break;
574 default:
575 /* invalid pid : frame interrupted */
576 s->status |= UHCI_STS_HCPERR;
577 uhci_update_irq(s);
578 return -1;
579 }
580 }
b9dc033c 581
4d611c9a
PB
582 if (ret == USB_RET_ASYNC) {
583 return 2;
bb36d470
FB
584 }
585 if (td->ctrl & TD_CTRL_IOS)
586 td->ctrl &= ~TD_CTRL_ACTIVE;
587 if (ret >= 0) {
588 td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
117b3ae6
PB
589 /* The NAK bit may have been set by a previous frame, so clear it
590 here. The docs are somewhat unclear, but win2k relies on this
591 behavior. */
592 td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
5fafdf24 593 if (pid == USB_TOKEN_IN &&
bb36d470
FB
594 (td->ctrl & TD_CTRL_SPD) &&
595 len < max_len) {
596 *int_mask |= 0x02;
597 /* short packet: do not update QH */
598 return 1;
599 } else {
600 /* success */
601 return 0;
602 }
603 } else {
604 switch(ret) {
605 default:
606 case USB_RET_NODEV:
607 do_timeout:
608 td->ctrl |= TD_CTRL_TIMEOUT;
609 err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
610 if (err != 0) {
611 err--;
612 if (err == 0) {
613 td->ctrl &= ~TD_CTRL_ACTIVE;
614 s->status |= UHCI_STS_USBERR;
615 uhci_update_irq(s);
616 }
617 }
5fafdf24 618 td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
bb36d470
FB
619 (err << TD_CTRL_ERROR_SHIFT);
620 return 1;
621 case USB_RET_NAK:
622 td->ctrl |= TD_CTRL_NAK;
623 if (pid == USB_TOKEN_SETUP)
624 goto do_timeout;
625 return 1;
626 case USB_RET_STALL:
627 td->ctrl |= TD_CTRL_STALL;
628 td->ctrl &= ~TD_CTRL_ACTIVE;
629 return 1;
630 case USB_RET_BABBLE:
631 td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
632 td->ctrl &= ~TD_CTRL_ACTIVE;
633 /* frame interrupted */
634 return -1;
635 }
636 }
637}
638
4d611c9a
PB
639static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
640{
641 UHCIState *s = opaque;
642 UHCI_QH qh;
643 UHCI_TD td;
644 uint32_t link;
645 uint32_t old_td_ctrl;
646 uint32_t val;
b9dc033c 647 uint32_t frame_addr;
4d611c9a
PB
648 int ret;
649
b9dc033c
AZ
650 /* Handle async isochronous packet completion */
651 frame_addr = s->async_frame_addr;
652 if (frame_addr) {
653 cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
654 le32_to_cpus(&link);
655
656 cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
657 le32_to_cpus(&td.link);
658 le32_to_cpus(&td.ctrl);
659 le32_to_cpus(&td.token);
660 le32_to_cpus(&td.buffer);
661 old_td_ctrl = td.ctrl;
662 ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
663
664 /* update the status bits of the TD */
665 if (old_td_ctrl != td.ctrl) {
666 val = cpu_to_le32(td.ctrl);
667 cpu_physical_memory_write((link & ~0xf) + 4,
668 (const uint8_t *)&val,
669 sizeof(val));
670 }
671 if (ret == 2) {
672 s->async_frame_addr = frame_addr;
673 } else if (ret == 0) {
674 /* update qh element link */
675 val = cpu_to_le32(td.link);
676 cpu_physical_memory_write(frame_addr,
677 (const uint8_t *)&val,
678 sizeof(val));
679 }
680 return;
681 }
682
4d611c9a
PB
683 link = s->async_qh;
684 if (!link) {
685 /* This should never happen. It means a TD somehow got removed
686 without cancelling the associated async IO request. */
687 return;
688 }
689 cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
690 le32_to_cpus(&qh.link);
691 le32_to_cpus(&qh.el_link);
692 /* Re-process the queue containing the async packet. */
693 while (1) {
5fafdf24 694 cpu_physical_memory_read(qh.el_link & ~0xf,
4d611c9a
PB
695 (uint8_t *)&td, sizeof(td));
696 le32_to_cpus(&td.link);
697 le32_to_cpus(&td.ctrl);
698 le32_to_cpus(&td.token);
699 le32_to_cpus(&td.buffer);
700 old_td_ctrl = td.ctrl;
b9dc033c
AZ
701 ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
702
4d611c9a
PB
703 /* update the status bits of the TD */
704 if (old_td_ctrl != td.ctrl) {
705 val = cpu_to_le32(td.ctrl);
5fafdf24
TS
706 cpu_physical_memory_write((qh.el_link & ~0xf) + 4,
707 (const uint8_t *)&val,
4d611c9a
PB
708 sizeof(val));
709 }
710 if (ret < 0)
711 break; /* interrupted frame */
712 if (ret == 2) {
713 s->async_qh = link;
714 break;
715 } else if (ret == 0) {
716 /* update qh element link */
717 qh.el_link = td.link;
718 val = cpu_to_le32(qh.el_link);
5fafdf24
TS
719 cpu_physical_memory_write((link & ~0xf) + 4,
720 (const uint8_t *)&val,
4d611c9a
PB
721 sizeof(val));
722 if (!(qh.el_link & 4))
723 break;
724 }
725 break;
726 }
727}
728
bb36d470
FB
729static void uhci_frame_timer(void *opaque)
730{
731 UHCIState *s = opaque;
732 int64_t expire_time;
733 uint32_t frame_addr, link, old_td_ctrl, val;
734 int int_mask, cnt, ret;
735 UHCI_TD td;
736 UHCI_QH qh;
4d611c9a 737 uint32_t old_async_qh;
bb36d470
FB
738
739 if (!(s->cmd & UHCI_CMD_RS)) {
740 qemu_del_timer(s->frame_timer);
52328140
FB
741 /* set hchalted bit in status - UHCI11D 2.1.2 */
742 s->status |= UHCI_STS_HCHALTED;
bb36d470
FB
743 return;
744 }
4d611c9a
PB
745 /* Complete the previous frame. */
746 s->frnum = (s->frnum + 1) & 0x7ff;
747 if (s->pending_int_mask) {
748 s->status2 |= s->pending_int_mask;
749 s->status |= UHCI_STS_USBINT;
750 uhci_update_irq(s);
751 }
752 old_async_qh = s->async_qh;
bb36d470
FB
753 frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
754 cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
755 le32_to_cpus(&link);
756 int_mask = 0;
757 cnt = FRAME_MAX_LOOPS;
758 while ((link & 1) == 0) {
759 if (--cnt == 0)
760 break;
761 /* valid frame */
762 if (link & 2) {
763 /* QH */
4d611c9a
PB
764 if (link == s->async_qh) {
765 /* We've found a previously issues packet.
766 Nothing else to do. */
767 old_async_qh = 0;
768 break;
769 }
bb36d470
FB
770 cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
771 le32_to_cpus(&qh.link);
772 le32_to_cpus(&qh.el_link);
773 depth_first:
774 if (qh.el_link & 1) {
775 /* no element : go to next entry */
776 link = qh.link;
777 } else if (qh.el_link & 2) {
778 /* QH */
779 link = qh.el_link;
4d611c9a
PB
780 } else if (s->async_qh) {
781 /* We can only cope with one pending packet. Keep looking
782 for the previously issued packet. */
783 link = qh.link;
bb36d470
FB
784 } else {
785 /* TD */
786 if (--cnt == 0)
787 break;
5fafdf24 788 cpu_physical_memory_read(qh.el_link & ~0xf,
bb36d470
FB
789 (uint8_t *)&td, sizeof(td));
790 le32_to_cpus(&td.link);
791 le32_to_cpus(&td.ctrl);
792 le32_to_cpus(&td.token);
793 le32_to_cpus(&td.buffer);
794 old_td_ctrl = td.ctrl;
b9dc033c
AZ
795 ret = uhci_handle_td(s, &td, &int_mask, 0);
796
bb36d470
FB
797 /* update the status bits of the TD */
798 if (old_td_ctrl != td.ctrl) {
799 val = cpu_to_le32(td.ctrl);
5fafdf24
TS
800 cpu_physical_memory_write((qh.el_link & ~0xf) + 4,
801 (const uint8_t *)&val,
bb36d470
FB
802 sizeof(val));
803 }
804 if (ret < 0)
805 break; /* interrupted frame */
4d611c9a
PB
806 if (ret == 2) {
807 s->async_qh = link;
808 } else if (ret == 0) {
bb36d470
FB
809 /* update qh element link */
810 qh.el_link = td.link;
811 val = cpu_to_le32(qh.el_link);
5fafdf24
TS
812 cpu_physical_memory_write((link & ~0xf) + 4,
813 (const uint8_t *)&val,
bb36d470
FB
814 sizeof(val));
815 if (qh.el_link & 4) {
816 /* depth first */
817 goto depth_first;
818 }
819 }
820 /* go to next entry */
821 link = qh.link;
822 }
823 } else {
824 /* TD */
825 cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
826 le32_to_cpus(&td.link);
827 le32_to_cpus(&td.ctrl);
828 le32_to_cpus(&td.token);
829 le32_to_cpus(&td.buffer);
b9dc033c
AZ
830
831 /* Handle isochonous transfer. */
832 /* FIXME: might be more than one isoc in frame */
833 old_td_ctrl = td.ctrl;
834 ret = uhci_handle_td(s, &td, &int_mask, 0);
835
836 /* update the status bits of the TD */
837 if (old_td_ctrl != td.ctrl) {
838 val = cpu_to_le32(td.ctrl);
839 cpu_physical_memory_write((link & ~0xf) + 4,
840 (const uint8_t *)&val,
841 sizeof(val));
842 }
843 if (ret < 0)
844 break; /* interrupted frame */
845 if (ret == 2) {
846 s->async_frame_addr = frame_addr;
bb36d470 847 }
bb36d470
FB
848 link = td.link;
849 }
850 }
4d611c9a
PB
851 s->pending_int_mask = int_mask;
852 if (old_async_qh) {
853 /* A previously started transfer has disappeared from the transfer
854 list. There's nothing useful we can do with it now, so just
855 discard the packet and hope it wasn't too important. */
856#ifdef DEBUG
857 printf("Discarding USB packet\n");
858#endif
859 usb_cancel_packet(&s->usb_packet);
860 s->async_qh = 0;
bb36d470 861 }
b9dc033c 862
bb36d470 863 /* prepare the timer for the next frame */
5fafdf24 864 expire_time = qemu_get_clock(vm_clock) +
bb36d470
FB
865 (ticks_per_sec / FRAME_TIMER_FREQ);
866 qemu_mod_timer(s->frame_timer, expire_time);
867}
868
5fafdf24 869static void uhci_map(PCIDevice *pci_dev, int region_num,
bb36d470
FB
870 uint32_t addr, uint32_t size, int type)
871{
872 UHCIState *s = (UHCIState *)pci_dev;
873
874 register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
875 register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
876 register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
877 register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
878 register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
879 register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
880}
881
afcc3cdf 882void usb_uhci_piix3_init(PCIBus *bus, int devfn)
bb36d470
FB
883{
884 UHCIState *s;
885 uint8_t *pci_conf;
bb36d470
FB
886 int i;
887
888 s = (UHCIState *)pci_register_device(bus,
889 "USB-UHCI", sizeof(UHCIState),
502a5395 890 devfn, NULL, NULL);
bb36d470
FB
891 pci_conf = s->dev.config;
892 pci_conf[0x00] = 0x86;
893 pci_conf[0x01] = 0x80;
894 pci_conf[0x02] = 0x20;
895 pci_conf[0x03] = 0x70;
896 pci_conf[0x08] = 0x01; // revision number
897 pci_conf[0x09] = 0x00;
898 pci_conf[0x0a] = 0x03;
899 pci_conf[0x0b] = 0x0c;
900 pci_conf[0x0e] = 0x00; // header_type
f04308e4 901 pci_conf[0x3d] = 4; // interrupt pin 3
38ca0f6d 902 pci_conf[0x60] = 0x10; // release number
3b46e624 903
bb36d470 904 for(i = 0; i < NB_PORTS; i++) {
0d92ed30 905 qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
bb36d470
FB
906 }
907 s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
908
909 uhci_reset(s);
910
38ca0f6d
PB
911 /* Use region 4 for consistency with real hardware. BSD guests seem
912 to rely on this. */
5fafdf24 913 pci_register_io_region(&s->dev, 4, 0x20,
bb36d470
FB
914 PCI_ADDRESS_SPACE_IO, uhci_map);
915}
afcc3cdf
TS
916
917void usb_uhci_piix4_init(PCIBus *bus, int devfn)
918{
919 UHCIState *s;
920 uint8_t *pci_conf;
921 int i;
922
923 s = (UHCIState *)pci_register_device(bus,
924 "USB-UHCI", sizeof(UHCIState),
925 devfn, NULL, NULL);
926 pci_conf = s->dev.config;
927 pci_conf[0x00] = 0x86;
928 pci_conf[0x01] = 0x80;
929 pci_conf[0x02] = 0x12;
930 pci_conf[0x03] = 0x71;
931 pci_conf[0x08] = 0x01; // revision number
932 pci_conf[0x09] = 0x00;
933 pci_conf[0x0a] = 0x03;
934 pci_conf[0x0b] = 0x0c;
935 pci_conf[0x0e] = 0x00; // header_type
936 pci_conf[0x3d] = 4; // interrupt pin 3
937 pci_conf[0x60] = 0x10; // release number
938
939 for(i = 0; i < NB_PORTS; i++) {
940 qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
941 }
942 s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
943
944 uhci_reset(s);
945
946 /* Use region 4 for consistency with real hardware. BSD guests seem
947 to rely on this. */
948 pci_register_io_region(&s->dev, 4, 0x20,
949 PCI_ADDRESS_SPACE_IO, uhci_map);
950}