Statistics
| Branch: | Revision:

root / hw / usb-uhci.c @ ee0ea1d0

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