Statistics
| Branch: | Revision:

root / hw / usb-uhci.c @ 5fafdf24

History | View | Annotate | Download (25.3 kB)

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