Statistics
| Branch: | Revision:

root / hw / usb-uhci.c @ d0dfae6e

History | View | Annotate | Download (24.1 kB)

1 bb36d470 bellard
/*
2 bb36d470 bellard
 * USB UHCI controller emulation
3 bb36d470 bellard
 * 
4 bb36d470 bellard
 * Copyright (c) 2005 Fabrice Bellard
5 bb36d470 bellard
 * 
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 4d611c9a pbrook
       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 bb36d470 bellard
    
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 bb36d470 bellard
    
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 bb36d470 bellard
                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 bb36d470 bellard
            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 bb36d470 bellard
    
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 bb36d470 bellard
        td->ctrl &= ~TD_CTRL_ACTIVE;
530 bb36d470 bellard
        if (pid == USB_TOKEN_IN && 
531 bb36d470 bellard
            (td->ctrl & TD_CTRL_SPD) &&
532 bb36d470 bellard
            len < max_len) {
533 bb36d470 bellard
            *int_mask |= 0x02;
534 bb36d470 bellard
            /* short packet: do not update QH */
535 bb36d470 bellard
            return 1;
536 bb36d470 bellard
        } else {
537 bb36d470 bellard
            /* success */
538 bb36d470 bellard
            return 0;
539 bb36d470 bellard
        }
540 bb36d470 bellard
    } else {
541 bb36d470 bellard
        switch(ret) {
542 bb36d470 bellard
        default:
543 bb36d470 bellard
        case USB_RET_NODEV:
544 bb36d470 bellard
        do_timeout:
545 bb36d470 bellard
            td->ctrl |= TD_CTRL_TIMEOUT;
546 bb36d470 bellard
            err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
547 bb36d470 bellard
            if (err != 0) {
548 bb36d470 bellard
                err--;
549 bb36d470 bellard
                if (err == 0) {
550 bb36d470 bellard
                    td->ctrl &= ~TD_CTRL_ACTIVE;
551 bb36d470 bellard
                    s->status |= UHCI_STS_USBERR;
552 bb36d470 bellard
                    uhci_update_irq(s);
553 bb36d470 bellard
                }
554 bb36d470 bellard
            }
555 bb36d470 bellard
            td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | 
556 bb36d470 bellard
                (err << TD_CTRL_ERROR_SHIFT);
557 bb36d470 bellard
            return 1;
558 bb36d470 bellard
        case USB_RET_NAK:
559 bb36d470 bellard
            td->ctrl |= TD_CTRL_NAK;
560 bb36d470 bellard
            if (pid == USB_TOKEN_SETUP)
561 bb36d470 bellard
                goto do_timeout;
562 bb36d470 bellard
            return 1;
563 bb36d470 bellard
        case USB_RET_STALL:
564 bb36d470 bellard
            td->ctrl |= TD_CTRL_STALL;
565 bb36d470 bellard
            td->ctrl &= ~TD_CTRL_ACTIVE;
566 bb36d470 bellard
            return 1;
567 bb36d470 bellard
        case USB_RET_BABBLE:
568 bb36d470 bellard
            td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
569 bb36d470 bellard
            td->ctrl &= ~TD_CTRL_ACTIVE;
570 bb36d470 bellard
            /* frame interrupted */
571 bb36d470 bellard
            return -1;
572 bb36d470 bellard
        }
573 bb36d470 bellard
    }
574 bb36d470 bellard
}
575 bb36d470 bellard
576 4d611c9a pbrook
static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
577 4d611c9a pbrook
{
578 4d611c9a pbrook
    UHCIState *s = opaque;
579 4d611c9a pbrook
    UHCI_QH qh;
580 4d611c9a pbrook
    UHCI_TD td;
581 4d611c9a pbrook
    uint32_t link;
582 4d611c9a pbrook
    uint32_t old_td_ctrl;
583 4d611c9a pbrook
    uint32_t val;
584 4d611c9a pbrook
    int ret;
585 4d611c9a pbrook
586 4d611c9a pbrook
    link = s->async_qh;
587 4d611c9a pbrook
    if (!link) {
588 4d611c9a pbrook
        /* This should never happen. It means a TD somehow got removed
589 4d611c9a pbrook
           without cancelling the associated async IO request.  */
590 4d611c9a pbrook
        return;
591 4d611c9a pbrook
    }
592 4d611c9a pbrook
    cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
593 4d611c9a pbrook
    le32_to_cpus(&qh.link);
594 4d611c9a pbrook
    le32_to_cpus(&qh.el_link);
595 4d611c9a pbrook
    /* Re-process the queue containing the async packet.  */
596 4d611c9a pbrook
    while (1) {
597 4d611c9a pbrook
        cpu_physical_memory_read(qh.el_link & ~0xf, 
598 4d611c9a pbrook
                                 (uint8_t *)&td, sizeof(td));
599 4d611c9a pbrook
        le32_to_cpus(&td.link);
600 4d611c9a pbrook
        le32_to_cpus(&td.ctrl);
601 4d611c9a pbrook
        le32_to_cpus(&td.token);
602 4d611c9a pbrook
        le32_to_cpus(&td.buffer);
603 4d611c9a pbrook
        old_td_ctrl = td.ctrl;
604 4d611c9a pbrook
        ret = uhci_handle_td(s, &td, &s->pending_int_mask);
605 4d611c9a pbrook
        /* update the status bits of the TD */
606 4d611c9a pbrook
        if (old_td_ctrl != td.ctrl) {
607 4d611c9a pbrook
            val = cpu_to_le32(td.ctrl);
608 4d611c9a pbrook
            cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
609 4d611c9a pbrook
                                      (const uint8_t *)&val, 
610 4d611c9a pbrook
                                      sizeof(val));
611 4d611c9a pbrook
        }
612 4d611c9a pbrook
        if (ret < 0)
613 4d611c9a pbrook
            break; /* interrupted frame */
614 4d611c9a pbrook
        if (ret == 2) {
615 4d611c9a pbrook
            s->async_qh = link;
616 4d611c9a pbrook
            break;
617 4d611c9a pbrook
        } else if (ret == 0) {
618 4d611c9a pbrook
            /* update qh element link */
619 4d611c9a pbrook
            qh.el_link = td.link;
620 4d611c9a pbrook
            val = cpu_to_le32(qh.el_link);
621 4d611c9a pbrook
            cpu_physical_memory_write((link & ~0xf) + 4, 
622 4d611c9a pbrook
                                      (const uint8_t *)&val, 
623 4d611c9a pbrook
                                      sizeof(val));
624 4d611c9a pbrook
            if (!(qh.el_link & 4))
625 4d611c9a pbrook
                break;
626 4d611c9a pbrook
        }
627 4d611c9a pbrook
        break;
628 4d611c9a pbrook
    }
629 4d611c9a pbrook
}
630 4d611c9a pbrook
631 bb36d470 bellard
static void uhci_frame_timer(void *opaque)
632 bb36d470 bellard
{
633 bb36d470 bellard
    UHCIState *s = opaque;
634 bb36d470 bellard
    int64_t expire_time;
635 bb36d470 bellard
    uint32_t frame_addr, link, old_td_ctrl, val;
636 bb36d470 bellard
    int int_mask, cnt, ret;
637 bb36d470 bellard
    UHCI_TD td;
638 bb36d470 bellard
    UHCI_QH qh;
639 4d611c9a pbrook
    uint32_t old_async_qh;
640 bb36d470 bellard
641 bb36d470 bellard
    if (!(s->cmd & UHCI_CMD_RS)) {
642 bb36d470 bellard
        qemu_del_timer(s->frame_timer);
643 52328140 bellard
        /* set hchalted bit in status - UHCI11D 2.1.2 */
644 52328140 bellard
        s->status |= UHCI_STS_HCHALTED;
645 bb36d470 bellard
        return;
646 bb36d470 bellard
    }
647 4d611c9a pbrook
    /* Complete the previous frame.  */
648 4d611c9a pbrook
    s->frnum = (s->frnum + 1) & 0x7ff;
649 4d611c9a pbrook
    if (s->pending_int_mask) {
650 4d611c9a pbrook
        s->status2 |= s->pending_int_mask;
651 4d611c9a pbrook
        s->status |= UHCI_STS_USBINT;
652 4d611c9a pbrook
        uhci_update_irq(s);
653 4d611c9a pbrook
    }
654 4d611c9a pbrook
    old_async_qh = s->async_qh;
655 bb36d470 bellard
    frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
656 bb36d470 bellard
    cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
657 bb36d470 bellard
    le32_to_cpus(&link);
658 bb36d470 bellard
    int_mask = 0;
659 bb36d470 bellard
    cnt = FRAME_MAX_LOOPS;
660 bb36d470 bellard
    while ((link & 1) == 0) {
661 bb36d470 bellard
        if (--cnt == 0)
662 bb36d470 bellard
            break;
663 bb36d470 bellard
        /* valid frame */
664 bb36d470 bellard
        if (link & 2) {
665 bb36d470 bellard
            /* QH */
666 4d611c9a pbrook
            if (link == s->async_qh) {
667 4d611c9a pbrook
                /* We've found a previously issues packet.
668 4d611c9a pbrook
                   Nothing else to do.  */
669 4d611c9a pbrook
                old_async_qh = 0;
670 4d611c9a pbrook
                break;
671 4d611c9a pbrook
            }
672 bb36d470 bellard
            cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
673 bb36d470 bellard
            le32_to_cpus(&qh.link);
674 bb36d470 bellard
            le32_to_cpus(&qh.el_link);
675 bb36d470 bellard
        depth_first:
676 bb36d470 bellard
            if (qh.el_link & 1) {
677 bb36d470 bellard
                /* no element : go to next entry */
678 bb36d470 bellard
                link = qh.link;
679 bb36d470 bellard
            } else if (qh.el_link & 2) {
680 bb36d470 bellard
                /* QH */
681 bb36d470 bellard
                link = qh.el_link;
682 4d611c9a pbrook
            } else if (s->async_qh) {
683 4d611c9a pbrook
                /* We can only cope with one pending packet.  Keep looking
684 4d611c9a pbrook
                   for the previously issued packet.  */
685 4d611c9a pbrook
                link = qh.link;
686 bb36d470 bellard
            } else {
687 bb36d470 bellard
                /* TD */
688 bb36d470 bellard
                if (--cnt == 0)
689 bb36d470 bellard
                    break;
690 bb36d470 bellard
                cpu_physical_memory_read(qh.el_link & ~0xf, 
691 bb36d470 bellard
                                         (uint8_t *)&td, sizeof(td));
692 bb36d470 bellard
                le32_to_cpus(&td.link);
693 bb36d470 bellard
                le32_to_cpus(&td.ctrl);
694 bb36d470 bellard
                le32_to_cpus(&td.token);
695 bb36d470 bellard
                le32_to_cpus(&td.buffer);
696 bb36d470 bellard
                old_td_ctrl = td.ctrl;
697 bb36d470 bellard
                ret = uhci_handle_td(s, &td, &int_mask);
698 bb36d470 bellard
                /* update the status bits of the TD */
699 bb36d470 bellard
                if (old_td_ctrl != td.ctrl) {
700 bb36d470 bellard
                    val = cpu_to_le32(td.ctrl);
701 bb36d470 bellard
                    cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
702 bb36d470 bellard
                                              (const uint8_t *)&val, 
703 bb36d470 bellard
                                              sizeof(val));
704 bb36d470 bellard
                }
705 bb36d470 bellard
                if (ret < 0)
706 bb36d470 bellard
                    break; /* interrupted frame */
707 4d611c9a pbrook
                if (ret == 2) {
708 4d611c9a pbrook
                    s->async_qh = link;
709 4d611c9a pbrook
                } else if (ret == 0) {
710 bb36d470 bellard
                    /* update qh element link */
711 bb36d470 bellard
                    qh.el_link = td.link;
712 bb36d470 bellard
                    val = cpu_to_le32(qh.el_link);
713 bb36d470 bellard
                    cpu_physical_memory_write((link & ~0xf) + 4, 
714 bb36d470 bellard
                                              (const uint8_t *)&val, 
715 bb36d470 bellard
                                              sizeof(val));
716 bb36d470 bellard
                    if (qh.el_link & 4) {
717 bb36d470 bellard
                        /* depth first */
718 bb36d470 bellard
                        goto depth_first;
719 bb36d470 bellard
                    }
720 bb36d470 bellard
                }
721 bb36d470 bellard
                /* go to next entry */
722 bb36d470 bellard
                link = qh.link;
723 bb36d470 bellard
            }
724 bb36d470 bellard
        } else {
725 bb36d470 bellard
            /* TD */
726 bb36d470 bellard
            cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
727 bb36d470 bellard
            le32_to_cpus(&td.link);
728 bb36d470 bellard
            le32_to_cpus(&td.ctrl);
729 bb36d470 bellard
            le32_to_cpus(&td.token);
730 bb36d470 bellard
            le32_to_cpus(&td.buffer);
731 4d611c9a pbrook
            /* Ignore isochonous transfers while there is an async packet
732 4d611c9a pbrook
               pending.  This is wrong, but we don't implement isochronous
733 4d611c9a pbrook
               transfers anyway.  */
734 4d611c9a pbrook
            if (s->async_qh == 0) {
735 4d611c9a pbrook
                old_td_ctrl = td.ctrl;
736 4d611c9a pbrook
                ret = uhci_handle_td(s, &td, &int_mask);
737 4d611c9a pbrook
                /* update the status bits of the TD */
738 4d611c9a pbrook
                if (old_td_ctrl != td.ctrl) {
739 4d611c9a pbrook
                    val = cpu_to_le32(td.ctrl);
740 4d611c9a pbrook
                    cpu_physical_memory_write((link & ~0xf) + 4, 
741 4d611c9a pbrook
                                              (const uint8_t *)&val, 
742 4d611c9a pbrook
                                              sizeof(val));
743 4d611c9a pbrook
                }
744 4d611c9a pbrook
                if (ret < 0)
745 4d611c9a pbrook
                    break; /* interrupted frame */
746 4d611c9a pbrook
                if (ret == 2) {
747 4d611c9a pbrook
                    /* We can't handle async isochronous transfers.
748 4d611c9a pbrook
                       Cancel The packet.  */
749 4d611c9a pbrook
                    fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
750 4d611c9a pbrook
                    usb_cancel_packet(&s->usb_packet);
751 4d611c9a pbrook
                }
752 bb36d470 bellard
            }
753 bb36d470 bellard
            link = td.link;
754 bb36d470 bellard
        }
755 bb36d470 bellard
    }
756 4d611c9a pbrook
    s->pending_int_mask = int_mask;
757 4d611c9a pbrook
    if (old_async_qh) {
758 4d611c9a pbrook
        /* A previously started transfer has disappeared from the transfer
759 4d611c9a pbrook
           list.  There's nothing useful we can do with it now, so just
760 4d611c9a pbrook
           discard the packet and hope it wasn't too important.  */
761 4d611c9a pbrook
#ifdef DEBUG
762 4d611c9a pbrook
        printf("Discarding USB packet\n");
763 4d611c9a pbrook
#endif
764 4d611c9a pbrook
        usb_cancel_packet(&s->usb_packet);
765 4d611c9a pbrook
        s->async_qh = 0;
766 bb36d470 bellard
    }
767 bb36d470 bellard
    /* prepare the timer for the next frame */
768 bb36d470 bellard
    expire_time = qemu_get_clock(vm_clock) + 
769 bb36d470 bellard
        (ticks_per_sec / FRAME_TIMER_FREQ);
770 bb36d470 bellard
    qemu_mod_timer(s->frame_timer, expire_time);
771 bb36d470 bellard
}
772 bb36d470 bellard
773 bb36d470 bellard
static void uhci_map(PCIDevice *pci_dev, int region_num, 
774 bb36d470 bellard
                    uint32_t addr, uint32_t size, int type)
775 bb36d470 bellard
{
776 bb36d470 bellard
    UHCIState *s = (UHCIState *)pci_dev;
777 bb36d470 bellard
778 bb36d470 bellard
    register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
779 bb36d470 bellard
    register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
780 bb36d470 bellard
    register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
781 bb36d470 bellard
    register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
782 bb36d470 bellard
    register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
783 bb36d470 bellard
    register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
784 bb36d470 bellard
}
785 bb36d470 bellard
786 0d92ed30 pbrook
void usb_uhci_init(PCIBus *bus, int devfn)
787 bb36d470 bellard
{
788 bb36d470 bellard
    UHCIState *s;
789 bb36d470 bellard
    uint8_t *pci_conf;
790 bb36d470 bellard
    int i;
791 bb36d470 bellard
792 bb36d470 bellard
    s = (UHCIState *)pci_register_device(bus,
793 bb36d470 bellard
                                        "USB-UHCI", sizeof(UHCIState),
794 502a5395 pbrook
                                        devfn, NULL, NULL);
795 bb36d470 bellard
    pci_conf = s->dev.config;
796 bb36d470 bellard
    pci_conf[0x00] = 0x86;
797 bb36d470 bellard
    pci_conf[0x01] = 0x80;
798 bb36d470 bellard
    pci_conf[0x02] = 0x20;
799 bb36d470 bellard
    pci_conf[0x03] = 0x70;
800 bb36d470 bellard
    pci_conf[0x08] = 0x01; // revision number
801 bb36d470 bellard
    pci_conf[0x09] = 0x00;
802 bb36d470 bellard
    pci_conf[0x0a] = 0x03;
803 bb36d470 bellard
    pci_conf[0x0b] = 0x0c;
804 bb36d470 bellard
    pci_conf[0x0e] = 0x00; // header_type
805 f04308e4 bellard
    pci_conf[0x3d] = 4; // interrupt pin 3
806 38ca0f6d pbrook
    pci_conf[0x60] = 0x10; // release number
807 bb36d470 bellard
    
808 bb36d470 bellard
    for(i = 0; i < NB_PORTS; i++) {
809 0d92ed30 pbrook
        qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
810 bb36d470 bellard
    }
811 bb36d470 bellard
    s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
812 bb36d470 bellard
813 bb36d470 bellard
    uhci_reset(s);
814 bb36d470 bellard
815 38ca0f6d pbrook
    /* Use region 4 for consistency with real hardware.  BSD guests seem
816 38ca0f6d pbrook
       to rely on this.  */
817 38ca0f6d pbrook
    pci_register_io_region(&s->dev, 4, 0x20, 
818 bb36d470 bellard
                           PCI_ADDRESS_SPACE_IO, uhci_map);
819 bb36d470 bellard
}