2 * USB UHCI controller emulation
4 * Copyright (c) 2005 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
27 //#define DEBUG_PACKET
29 #define UHCI_CMD_GRESET (1 << 2)
30 #define UHCI_CMD_HCRESET (1 << 1)
31 #define UHCI_CMD_RS (1 << 0)
33 #define UHCI_STS_HCHALTED (1 << 5)
34 #define UHCI_STS_HCPERR (1 << 4)
35 #define UHCI_STS_HSERR (1 << 3)
36 #define UHCI_STS_RD (1 << 2)
37 #define UHCI_STS_USBERR (1 << 1)
38 #define UHCI_STS_USBINT (1 << 0)
40 #define TD_CTRL_SPD (1 << 29)
41 #define TD_CTRL_ERROR_SHIFT 27
42 #define TD_CTRL_IOS (1 << 25)
43 #define TD_CTRL_IOC (1 << 24)
44 #define TD_CTRL_ACTIVE (1 << 23)
45 #define TD_CTRL_STALL (1 << 22)
46 #define TD_CTRL_BABBLE (1 << 20)
47 #define TD_CTRL_NAK (1 << 19)
48 #define TD_CTRL_TIMEOUT (1 << 18)
50 #define UHCI_PORT_RESET (1 << 9)
51 #define UHCI_PORT_LSDA (1 << 8)
52 #define UHCI_PORT_ENC (1 << 3)
53 #define UHCI_PORT_EN (1 << 2)
54 #define UHCI_PORT_CSC (1 << 1)
55 #define UHCI_PORT_CCS (1 << 0)
57 #define FRAME_TIMER_FREQ 1000
59 #define FRAME_MAX_LOOPS 100
63 typedef struct UHCIPort
{
68 typedef struct UHCIState
{
70 uint16_t cmd
; /* cmd register */
72 uint16_t intr
; /* interrupt enable register */
73 uint16_t frnum
; /* frame number */
74 uint32_t fl_base_addr
; /* frame list base address */
76 uint8_t status2
; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
77 QEMUTimer
*frame_timer
;
78 UHCIPort ports
[NB_PORTS
];
81 typedef struct UHCI_TD
{
83 uint32_t ctrl
; /* see TD_CTRL_xxx */
88 typedef struct UHCI_QH
{
93 static void uhci_attach(USBPort
*port1
, USBDevice
*dev
);
95 static void uhci_update_irq(UHCIState
*s
)
98 if (((s
->status2
& 1) && (s
->intr
& (1 << 2))) ||
99 ((s
->status2
& 2) && (s
->intr
& (1 << 3))) ||
100 ((s
->status
& UHCI_STS_USBERR
) && (s
->intr
& (1 << 0))) ||
101 ((s
->status
& UHCI_STS_RD
) && (s
->intr
& (1 << 1))) ||
102 (s
->status
& UHCI_STS_HSERR
) ||
103 (s
->status
& UHCI_STS_HCPERR
)) {
108 pci_set_irq(&s
->dev
, 3, level
);
111 static void uhci_reset(UHCIState
*s
)
117 pci_conf
= s
->dev
.config
;
119 pci_conf
[0x6a] = 0x01; /* usb clock */
120 pci_conf
[0x6b] = 0x00;
127 for(i
= 0; i
< NB_PORTS
; i
++) {
131 uhci_attach(&port
->port
, port
->port
.dev
);
135 static void uhci_ioport_writeb(void *opaque
, uint32_t addr
, uint32_t val
)
137 UHCIState
*s
= opaque
;
147 static uint32_t uhci_ioport_readb(void *opaque
, uint32_t addr
)
149 UHCIState
*s
= opaque
;
164 static void uhci_ioport_writew(void *opaque
, uint32_t addr
, uint32_t val
)
166 UHCIState
*s
= opaque
;
170 printf("uhci writew port=0x%04x val=0x%04x\n", addr
, val
);
174 if ((val
& UHCI_CMD_RS
) && !(s
->cmd
& UHCI_CMD_RS
)) {
175 /* start frame processing */
176 qemu_mod_timer(s
->frame_timer
, qemu_get_clock(vm_clock
));
178 if (val
& UHCI_CMD_GRESET
) {
183 /* send reset on the USB bus */
184 for(i
= 0; i
< NB_PORTS
; i
++) {
186 dev
= port
->port
.dev
;
188 dev
->handle_packet(dev
,
189 USB_MSG_RESET
, 0, 0, NULL
, 0);
195 if (val
& UHCI_CMD_HCRESET
) {
203 /* XXX: the chip spec is not coherent, so we add a hidden
204 register to distinguish between IOC and SPD */
205 if (val
& UHCI_STS_USBINT
)
214 if (s
->status
& UHCI_STS_HCHALTED
)
215 s
->frnum
= val
& 0x7ff;
227 dev
= port
->port
.dev
;
230 if ( (val
& UHCI_PORT_RESET
) &&
231 !(port
->ctrl
& UHCI_PORT_RESET
) ) {
232 dev
->handle_packet(dev
,
233 USB_MSG_RESET
, 0, 0, NULL
, 0);
236 port
->ctrl
= (port
->ctrl
& 0x01fb) | (val
& ~0x01fb);
237 /* some bits are reset when a '1' is written to them */
238 port
->ctrl
&= ~(val
& 0x000a);
244 static uint32_t uhci_ioport_readw(void *opaque
, uint32_t addr
)
246 UHCIState
*s
= opaque
;
276 val
= 0xff7f; /* disabled port */
280 printf("uhci readw port=0x%04x val=0x%04x\n", addr
, val
);
285 static void uhci_ioport_writel(void *opaque
, uint32_t addr
, uint32_t val
)
287 UHCIState
*s
= opaque
;
291 printf("uhci writel port=0x%04x val=0x%08x\n", addr
, val
);
295 s
->fl_base_addr
= val
& ~0xfff;
300 static uint32_t uhci_ioport_readl(void *opaque
, uint32_t addr
)
302 UHCIState
*s
= opaque
;
308 val
= s
->fl_base_addr
;
317 static void uhci_attach(USBPort
*port1
, USBDevice
*dev
)
319 UHCIState
*s
= port1
->opaque
;
320 UHCIPort
*port
= &s
->ports
[port1
->index
];
323 if (port
->port
.dev
) {
324 usb_attach(port1
, NULL
);
326 /* set connect status */
327 if (!(port
->ctrl
& UHCI_PORT_CCS
)) {
328 port
->ctrl
|= UHCI_PORT_CCS
| UHCI_PORT_CSC
;
331 if (dev
->speed
== USB_SPEED_LOW
)
332 port
->ctrl
|= UHCI_PORT_LSDA
;
334 port
->ctrl
&= ~UHCI_PORT_LSDA
;
335 port
->port
.dev
= dev
;
336 /* send the attach message */
337 dev
->handle_packet(dev
,
338 USB_MSG_ATTACH
, 0, 0, NULL
, 0);
340 /* set connect status */
341 if (!(port
->ctrl
& UHCI_PORT_CCS
)) {
342 port
->ctrl
|= UHCI_PORT_CCS
| UHCI_PORT_CSC
;
345 if (port
->ctrl
& UHCI_PORT_EN
) {
346 port
->ctrl
&= ~UHCI_PORT_EN
;
347 port
->ctrl
|= UHCI_PORT_ENC
;
349 dev
= port
->port
.dev
;
351 /* send the detach message */
352 dev
->handle_packet(dev
,
353 USB_MSG_DETACH
, 0, 0, NULL
, 0);
355 port
->port
.dev
= NULL
;
359 static int uhci_broadcast_packet(UHCIState
*s
, uint8_t pid
,
360 uint8_t devaddr
, uint8_t devep
,
361 uint8_t *data
, int len
)
371 case USB_TOKEN_SETUP
: pidstr
= "SETUP"; break;
372 case USB_TOKEN_IN
: pidstr
= "IN"; break;
373 case USB_TOKEN_OUT
: pidstr
= "OUT"; break;
374 default: pidstr
= "?"; break;
376 printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
377 s
->frnum
, pidstr
, devaddr
, devep
, len
);
378 if (pid
!= USB_TOKEN_IN
) {
379 printf(" data_out=");
380 for(i
= 0; i
< len
; i
++) {
381 printf(" %02x", data
[i
]);
387 for(i
= 0; i
< NB_PORTS
; i
++) {
389 dev
= port
->port
.dev
;
390 if (dev
&& (port
->ctrl
& UHCI_PORT_EN
)) {
391 ret
= dev
->handle_packet(dev
, pid
,
394 if (ret
!= USB_RET_NODEV
) {
397 printf(" ret=%d ", ret
);
398 if (pid
== USB_TOKEN_IN
&& ret
> 0) {
400 for(i
= 0; i
< ret
; i
++) {
401 printf(" %02x", data
[i
]);
411 return USB_RET_NODEV
;
414 /* return -1 if fatal error (frame must be stopped)
416 1 if TD unsuccessful or inactive
418 static int uhci_handle_td(UHCIState
*s
, UHCI_TD
*td
, int *int_mask
)
422 int len
, max_len
, err
, ret
;
424 if (td
->ctrl
& TD_CTRL_IOC
) {
428 if (!(td
->ctrl
& TD_CTRL_ACTIVE
))
432 max_len
= ((td
->token
>> 21) + 1) & 0x7ff;
433 pid
= td
->token
& 0xff;
436 case USB_TOKEN_SETUP
:
437 cpu_physical_memory_read(td
->buffer
, buf
, max_len
);
438 ret
= uhci_broadcast_packet(s
, pid
,
439 (td
->token
>> 8) & 0x7f,
440 (td
->token
>> 15) & 0xf,
445 ret
= uhci_broadcast_packet(s
, pid
,
446 (td
->token
>> 8) & 0x7f,
447 (td
->token
>> 15) & 0xf,
453 ret
= USB_RET_BABBLE
;
456 /* write the data back */
457 cpu_physical_memory_write(td
->buffer
, buf
, len
);
464 /* invalid pid : frame interrupted */
465 s
->status
|= UHCI_STS_HCPERR
;
469 if (td
->ctrl
& TD_CTRL_IOS
)
470 td
->ctrl
&= ~TD_CTRL_ACTIVE
;
472 td
->ctrl
= (td
->ctrl
& ~0x7ff) | ((len
- 1) & 0x7ff);
473 td
->ctrl
&= ~TD_CTRL_ACTIVE
;
474 if (pid
== USB_TOKEN_IN
&&
475 (td
->ctrl
& TD_CTRL_SPD
) &&
478 /* short packet: do not update QH */
489 td
->ctrl
|= TD_CTRL_TIMEOUT
;
490 err
= (td
->ctrl
>> TD_CTRL_ERROR_SHIFT
) & 3;
494 td
->ctrl
&= ~TD_CTRL_ACTIVE
;
495 s
->status
|= UHCI_STS_USBERR
;
499 td
->ctrl
= (td
->ctrl
& ~(3 << TD_CTRL_ERROR_SHIFT
)) |
500 (err
<< TD_CTRL_ERROR_SHIFT
);
503 td
->ctrl
|= TD_CTRL_NAK
;
504 if (pid
== USB_TOKEN_SETUP
)
508 td
->ctrl
|= TD_CTRL_STALL
;
509 td
->ctrl
&= ~TD_CTRL_ACTIVE
;
512 td
->ctrl
|= TD_CTRL_BABBLE
| TD_CTRL_STALL
;
513 td
->ctrl
&= ~TD_CTRL_ACTIVE
;
514 /* frame interrupted */
520 static void uhci_frame_timer(void *opaque
)
522 UHCIState
*s
= opaque
;
524 uint32_t frame_addr
, link
, old_td_ctrl
, val
;
525 int int_mask
, cnt
, ret
;
529 if (!(s
->cmd
& UHCI_CMD_RS
)) {
530 qemu_del_timer(s
->frame_timer
);
533 frame_addr
= s
->fl_base_addr
+ ((s
->frnum
& 0x3ff) << 2);
534 cpu_physical_memory_read(frame_addr
, (uint8_t *)&link
, 4);
537 cnt
= FRAME_MAX_LOOPS
;
538 while ((link
& 1) == 0) {
544 cpu_physical_memory_read(link
& ~0xf, (uint8_t *)&qh
, sizeof(qh
));
545 le32_to_cpus(&qh
.link
);
546 le32_to_cpus(&qh
.el_link
);
548 if (qh
.el_link
& 1) {
549 /* no element : go to next entry */
551 } else if (qh
.el_link
& 2) {
558 cpu_physical_memory_read(qh
.el_link
& ~0xf,
559 (uint8_t *)&td
, sizeof(td
));
560 le32_to_cpus(&td
.link
);
561 le32_to_cpus(&td
.ctrl
);
562 le32_to_cpus(&td
.token
);
563 le32_to_cpus(&td
.buffer
);
564 old_td_ctrl
= td
.ctrl
;
565 ret
= uhci_handle_td(s
, &td
, &int_mask
);
566 /* update the status bits of the TD */
567 if (old_td_ctrl
!= td
.ctrl
) {
568 val
= cpu_to_le32(td
.ctrl
);
569 cpu_physical_memory_write((qh
.el_link
& ~0xf) + 4,
570 (const uint8_t *)&val
,
574 break; /* interrupted frame */
576 /* update qh element link */
577 qh
.el_link
= td
.link
;
578 val
= cpu_to_le32(qh
.el_link
);
579 cpu_physical_memory_write((link
& ~0xf) + 4,
580 (const uint8_t *)&val
,
582 if (qh
.el_link
& 4) {
587 /* go to next entry */
592 cpu_physical_memory_read(link
& ~0xf, (uint8_t *)&td
, sizeof(td
));
593 le32_to_cpus(&td
.link
);
594 le32_to_cpus(&td
.ctrl
);
595 le32_to_cpus(&td
.token
);
596 le32_to_cpus(&td
.buffer
);
597 old_td_ctrl
= td
.ctrl
;
598 ret
= uhci_handle_td(s
, &td
, &int_mask
);
599 /* update the status bits of the TD */
600 if (old_td_ctrl
!= td
.ctrl
) {
601 val
= cpu_to_le32(td
.ctrl
);
602 cpu_physical_memory_write((link
& ~0xf) + 4,
603 (const uint8_t *)&val
,
607 break; /* interrupted frame */
611 s
->frnum
= (s
->frnum
+ 1) & 0x7ff;
613 s
->status2
|= int_mask
;
614 s
->status
|= UHCI_STS_USBINT
;
617 /* prepare the timer for the next frame */
618 expire_time
= qemu_get_clock(vm_clock
) +
619 (ticks_per_sec
/ FRAME_TIMER_FREQ
);
620 qemu_mod_timer(s
->frame_timer
, expire_time
);
623 static void uhci_map(PCIDevice
*pci_dev
, int region_num
,
624 uint32_t addr
, uint32_t size
, int type
)
626 UHCIState
*s
= (UHCIState
*)pci_dev
;
628 register_ioport_write(addr
, 32, 2, uhci_ioport_writew
, s
);
629 register_ioport_read(addr
, 32, 2, uhci_ioport_readw
, s
);
630 register_ioport_write(addr
, 32, 4, uhci_ioport_writel
, s
);
631 register_ioport_read(addr
, 32, 4, uhci_ioport_readl
, s
);
632 register_ioport_write(addr
, 32, 1, uhci_ioport_writeb
, s
);
633 register_ioport_read(addr
, 32, 1, uhci_ioport_readb
, s
);
636 void usb_uhci_init(PCIBus
*bus
, USBPort
**usb_ports
)
643 s
= (UHCIState
*)pci_register_device(bus
,
644 "USB-UHCI", sizeof(UHCIState
),
645 ((PCIDevice
*)piix3_state
)->devfn
+ 2,
647 pci_conf
= s
->dev
.config
;
648 pci_conf
[0x00] = 0x86;
649 pci_conf
[0x01] = 0x80;
650 pci_conf
[0x02] = 0x20;
651 pci_conf
[0x03] = 0x70;
652 pci_conf
[0x08] = 0x01; // revision number
653 pci_conf
[0x09] = 0x00;
654 pci_conf
[0x0a] = 0x03;
655 pci_conf
[0x0b] = 0x0c;
656 pci_conf
[0x0e] = 0x00; // header_type
657 pci_conf
[0x3d] = 4; // interrupt pin 3
658 pci_conf
[0x60] = 0x10; // release number
660 for(i
= 0; i
< NB_PORTS
; i
++) {
662 port
->port
.opaque
= s
;
663 port
->port
.index
= i
;
664 port
->port
.attach
= uhci_attach
;
665 usb_ports
[i
] = &port
->port
;
667 s
->frame_timer
= qemu_new_timer(vm_clock
, uhci_frame_timer
, s
);
671 /* Use region 4 for consistency with real hardware. BSD guests seem
673 pci_register_io_region(&s
->dev
, 4, 0x20,
674 PCI_ADDRESS_SPACE_IO
, uhci_map
);