Statistics
| Branch: | Revision:

root / hw / usb / hcd-uhci.c @ 0b7ade1d

History | View | Annotate | Download (35.9 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 54f254f9 aliguori
 * Copyright (c) 2008 Max Krasnyansky
7 54f254f9 aliguori
 *     Magor rewrite of the UHCI data structures parser and frame processor
8 54f254f9 aliguori
 *     Support for fully async operation and multiple outstanding transactions
9 54f254f9 aliguori
 *
10 bb36d470 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 bb36d470 bellard
 * of this software and associated documentation files (the "Software"), to deal
12 bb36d470 bellard
 * in the Software without restriction, including without limitation the rights
13 bb36d470 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 bb36d470 bellard
 * copies of the Software, and to permit persons to whom the Software is
15 bb36d470 bellard
 * furnished to do so, subject to the following conditions:
16 bb36d470 bellard
 *
17 bb36d470 bellard
 * The above copyright notice and this permission notice shall be included in
18 bb36d470 bellard
 * all copies or substantial portions of the Software.
19 bb36d470 bellard
 *
20 bb36d470 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 bb36d470 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 bb36d470 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 bb36d470 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 bb36d470 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 bb36d470 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 bb36d470 bellard
 * THE SOFTWARE.
27 bb36d470 bellard
 */
28 f1ae32a1 Gerd Hoffmann
#include "hw/hw.h"
29 f1ae32a1 Gerd Hoffmann
#include "hw/usb.h"
30 f1ae32a1 Gerd Hoffmann
#include "hw/pci.h"
31 87ecb68b pbrook
#include "qemu-timer.h"
32 4f4321c1 Gerd Hoffmann
#include "iov.h"
33 df5e66ee Gerd Hoffmann
#include "dma.h"
34 50dcc0f8 Gerd Hoffmann
#include "trace.h"
35 bb36d470 bellard
36 bb36d470 bellard
//#define DEBUG
37 54f254f9 aliguori
//#define DEBUG_DUMP_DATA
38 bb36d470 bellard
39 96217e31 ths
#define UHCI_CMD_FGR      (1 << 4)
40 96217e31 ths
#define UHCI_CMD_EGSM     (1 << 3)
41 bb36d470 bellard
#define UHCI_CMD_GRESET   (1 << 2)
42 bb36d470 bellard
#define UHCI_CMD_HCRESET  (1 << 1)
43 bb36d470 bellard
#define UHCI_CMD_RS       (1 << 0)
44 bb36d470 bellard
45 bb36d470 bellard
#define UHCI_STS_HCHALTED (1 << 5)
46 bb36d470 bellard
#define UHCI_STS_HCPERR   (1 << 4)
47 bb36d470 bellard
#define UHCI_STS_HSERR    (1 << 3)
48 bb36d470 bellard
#define UHCI_STS_RD       (1 << 2)
49 bb36d470 bellard
#define UHCI_STS_USBERR   (1 << 1)
50 bb36d470 bellard
#define UHCI_STS_USBINT   (1 << 0)
51 bb36d470 bellard
52 bb36d470 bellard
#define TD_CTRL_SPD     (1 << 29)
53 bb36d470 bellard
#define TD_CTRL_ERROR_SHIFT  27
54 bb36d470 bellard
#define TD_CTRL_IOS     (1 << 25)
55 bb36d470 bellard
#define TD_CTRL_IOC     (1 << 24)
56 bb36d470 bellard
#define TD_CTRL_ACTIVE  (1 << 23)
57 bb36d470 bellard
#define TD_CTRL_STALL   (1 << 22)
58 bb36d470 bellard
#define TD_CTRL_BABBLE  (1 << 20)
59 bb36d470 bellard
#define TD_CTRL_NAK     (1 << 19)
60 bb36d470 bellard
#define TD_CTRL_TIMEOUT (1 << 18)
61 bb36d470 bellard
62 9159f679 Gerd Hoffmann
#define UHCI_PORT_SUSPEND (1 << 12)
63 bb36d470 bellard
#define UHCI_PORT_RESET (1 << 9)
64 bb36d470 bellard
#define UHCI_PORT_LSDA  (1 << 8)
65 9159f679 Gerd Hoffmann
#define UHCI_PORT_RD    (1 << 6)
66 bb36d470 bellard
#define UHCI_PORT_ENC   (1 << 3)
67 bb36d470 bellard
#define UHCI_PORT_EN    (1 << 2)
68 bb36d470 bellard
#define UHCI_PORT_CSC   (1 << 1)
69 bb36d470 bellard
#define UHCI_PORT_CCS   (1 << 0)
70 bb36d470 bellard
71 9159f679 Gerd Hoffmann
#define UHCI_PORT_READ_ONLY    (0x1bb)
72 9159f679 Gerd Hoffmann
#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
73 9159f679 Gerd Hoffmann
74 bb36d470 bellard
#define FRAME_TIMER_FREQ 1000
75 bb36d470 bellard
76 3200d108 Gerd Hoffmann
#define FRAME_MAX_LOOPS  256
77 bb36d470 bellard
78 bb36d470 bellard
#define NB_PORTS 2
79 bb36d470 bellard
80 60e1b2a6 Gerd Hoffmann
enum {
81 0cd178ca Gerd Hoffmann
    TD_RESULT_STOP_FRAME = 10,
82 0cd178ca Gerd Hoffmann
    TD_RESULT_COMPLETE,
83 0cd178ca Gerd Hoffmann
    TD_RESULT_NEXT_QH,
84 4efe4ef3 Gerd Hoffmann
    TD_RESULT_ASYNC_START,
85 4efe4ef3 Gerd Hoffmann
    TD_RESULT_ASYNC_CONT,
86 60e1b2a6 Gerd Hoffmann
};
87 60e1b2a6 Gerd Hoffmann
88 7b5a44c5 Gerd Hoffmann
typedef struct UHCIState UHCIState;
89 f8af1e88 Gerd Hoffmann
typedef struct UHCIAsync UHCIAsync;
90 f8af1e88 Gerd Hoffmann
typedef struct UHCIQueue UHCIQueue;
91 7b5a44c5 Gerd Hoffmann
92 54f254f9 aliguori
/* 
93 54f254f9 aliguori
 * Pending async transaction.
94 54f254f9 aliguori
 * 'packet' must be the first field because completion
95 54f254f9 aliguori
 * handler does "(UHCIAsync *) pkt" cast.
96 54f254f9 aliguori
 */
97 f8af1e88 Gerd Hoffmann
98 f8af1e88 Gerd Hoffmann
struct UHCIAsync {
99 54f254f9 aliguori
    USBPacket packet;
100 df5e66ee Gerd Hoffmann
    QEMUSGList sgl;
101 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
102 ddf6583f Gerd Hoffmann
    QTAILQ_ENTRY(UHCIAsync) next;
103 54f254f9 aliguori
    uint32_t  td;
104 8e65b7c0 David S. Ahern
    uint8_t   isoc;
105 54f254f9 aliguori
    uint8_t   done;
106 f8af1e88 Gerd Hoffmann
};
107 f8af1e88 Gerd Hoffmann
108 f8af1e88 Gerd Hoffmann
struct UHCIQueue {
109 f8af1e88 Gerd Hoffmann
    uint32_t  token;
110 f8af1e88 Gerd Hoffmann
    UHCIState *uhci;
111 f8af1e88 Gerd Hoffmann
    QTAILQ_ENTRY(UHCIQueue) next;
112 f8af1e88 Gerd Hoffmann
    QTAILQ_HEAD(, UHCIAsync) asyncs;
113 f8af1e88 Gerd Hoffmann
    int8_t    valid;
114 f8af1e88 Gerd Hoffmann
};
115 54f254f9 aliguori
116 bb36d470 bellard
typedef struct UHCIPort {
117 bb36d470 bellard
    USBPort port;
118 bb36d470 bellard
    uint16_t ctrl;
119 bb36d470 bellard
} UHCIPort;
120 bb36d470 bellard
121 7b5a44c5 Gerd Hoffmann
struct UHCIState {
122 bb36d470 bellard
    PCIDevice dev;
123 a03f66e4 Avi Kivity
    MemoryRegion io_bar;
124 35e4977f Hans de Goede
    USBBus bus; /* Note unused when we're a companion controller */
125 bb36d470 bellard
    uint16_t cmd; /* cmd register */
126 bb36d470 bellard
    uint16_t status;
127 bb36d470 bellard
    uint16_t intr; /* interrupt enable register */
128 bb36d470 bellard
    uint16_t frnum; /* frame number */
129 bb36d470 bellard
    uint32_t fl_base_addr; /* frame list base address */
130 bb36d470 bellard
    uint8_t sof_timing;
131 bb36d470 bellard
    uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
132 8e65b7c0 David S. Ahern
    int64_t expire_time;
133 bb36d470 bellard
    QEMUTimer *frame_timer;
134 bb36d470 bellard
    UHCIPort ports[NB_PORTS];
135 4d611c9a pbrook
136 4d611c9a pbrook
    /* Interrupts that should be raised at the end of the current frame.  */
137 4d611c9a pbrook
    uint32_t pending_int_mask;
138 54f254f9 aliguori
139 54f254f9 aliguori
    /* Active packets */
140 f8af1e88 Gerd Hoffmann
    QTAILQ_HEAD(, UHCIQueue) queues;
141 64e58fe5 Juan Quintela
    uint8_t num_ports_vmstate;
142 35e4977f Hans de Goede
143 35e4977f Hans de Goede
    /* Properties */
144 35e4977f Hans de Goede
    char *masterbus;
145 35e4977f Hans de Goede
    uint32_t firstport;
146 7b5a44c5 Gerd Hoffmann
};
147 bb36d470 bellard
148 bb36d470 bellard
typedef struct UHCI_TD {
149 bb36d470 bellard
    uint32_t link;
150 bb36d470 bellard
    uint32_t ctrl; /* see TD_CTRL_xxx */
151 bb36d470 bellard
    uint32_t token;
152 bb36d470 bellard
    uint32_t buffer;
153 bb36d470 bellard
} UHCI_TD;
154 bb36d470 bellard
155 bb36d470 bellard
typedef struct UHCI_QH {
156 bb36d470 bellard
    uint32_t link;
157 bb36d470 bellard
    uint32_t el_link;
158 bb36d470 bellard
} UHCI_QH;
159 bb36d470 bellard
160 f8af1e88 Gerd Hoffmann
static inline int32_t uhci_queue_token(UHCI_TD *td)
161 f8af1e88 Gerd Hoffmann
{
162 f8af1e88 Gerd Hoffmann
    /* covers ep, dev, pid -> identifies the endpoint */
163 f8af1e88 Gerd Hoffmann
    return td->token & 0x7ffff;
164 f8af1e88 Gerd Hoffmann
}
165 f8af1e88 Gerd Hoffmann
166 f8af1e88 Gerd Hoffmann
static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td)
167 f8af1e88 Gerd Hoffmann
{
168 f8af1e88 Gerd Hoffmann
    uint32_t token = uhci_queue_token(td);
169 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
170 f8af1e88 Gerd Hoffmann
171 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(queue, &s->queues, next) {
172 f8af1e88 Gerd Hoffmann
        if (queue->token == token) {
173 f8af1e88 Gerd Hoffmann
            return queue;
174 f8af1e88 Gerd Hoffmann
        }
175 f8af1e88 Gerd Hoffmann
    }
176 f8af1e88 Gerd Hoffmann
177 f8af1e88 Gerd Hoffmann
    queue = g_new0(UHCIQueue, 1);
178 f8af1e88 Gerd Hoffmann
    queue->uhci = s;
179 f8af1e88 Gerd Hoffmann
    queue->token = token;
180 f8af1e88 Gerd Hoffmann
    QTAILQ_INIT(&queue->asyncs);
181 f8af1e88 Gerd Hoffmann
    QTAILQ_INSERT_HEAD(&s->queues, queue, next);
182 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_queue_add(queue->token);
183 f8af1e88 Gerd Hoffmann
    return queue;
184 f8af1e88 Gerd Hoffmann
}
185 f8af1e88 Gerd Hoffmann
186 f8af1e88 Gerd Hoffmann
static void uhci_queue_free(UHCIQueue *queue)
187 f8af1e88 Gerd Hoffmann
{
188 f8af1e88 Gerd Hoffmann
    UHCIState *s = queue->uhci;
189 f8af1e88 Gerd Hoffmann
190 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_queue_del(queue->token);
191 f8af1e88 Gerd Hoffmann
    QTAILQ_REMOVE(&s->queues, queue, next);
192 f8af1e88 Gerd Hoffmann
    g_free(queue);
193 f8af1e88 Gerd Hoffmann
}
194 f8af1e88 Gerd Hoffmann
195 16ce543e Gerd Hoffmann
static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t addr)
196 54f254f9 aliguori
{
197 326700e3 Gerd Hoffmann
    UHCIAsync *async = g_new0(UHCIAsync, 1);
198 487414f1 aliguori
199 f8af1e88 Gerd Hoffmann
    async->queue = queue;
200 16ce543e Gerd Hoffmann
    async->td = addr;
201 4f4321c1 Gerd Hoffmann
    usb_packet_init(&async->packet);
202 f8af1e88 Gerd Hoffmann
    pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);
203 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_add(async->queue->token, async->td);
204 54f254f9 aliguori
205 54f254f9 aliguori
    return async;
206 54f254f9 aliguori
}
207 54f254f9 aliguori
208 f8af1e88 Gerd Hoffmann
static void uhci_async_free(UHCIAsync *async)
209 54f254f9 aliguori
{
210 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_del(async->queue->token, async->td);
211 4f4321c1 Gerd Hoffmann
    usb_packet_cleanup(&async->packet);
212 df5e66ee Gerd Hoffmann
    qemu_sglist_destroy(&async->sgl);
213 7267c094 Anthony Liguori
    g_free(async);
214 54f254f9 aliguori
}
215 54f254f9 aliguori
216 f8af1e88 Gerd Hoffmann
static void uhci_async_link(UHCIAsync *async)
217 54f254f9 aliguori
{
218 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue = async->queue;
219 f8af1e88 Gerd Hoffmann
    QTAILQ_INSERT_TAIL(&queue->asyncs, async, next);
220 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_link_async(async->queue->token, async->td);
221 54f254f9 aliguori
}
222 54f254f9 aliguori
223 f8af1e88 Gerd Hoffmann
static void uhci_async_unlink(UHCIAsync *async)
224 54f254f9 aliguori
{
225 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue = async->queue;
226 f8af1e88 Gerd Hoffmann
    QTAILQ_REMOVE(&queue->asyncs, async, next);
227 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_unlink_async(async->queue->token, async->td);
228 54f254f9 aliguori
}
229 54f254f9 aliguori
230 f8af1e88 Gerd Hoffmann
static void uhci_async_cancel(UHCIAsync *async)
231 54f254f9 aliguori
{
232 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_cancel(async->queue->token, async->td, async->done);
233 54f254f9 aliguori
    if (!async->done)
234 54f254f9 aliguori
        usb_cancel_packet(&async->packet);
235 f8af1e88 Gerd Hoffmann
    uhci_async_free(async);
236 54f254f9 aliguori
}
237 54f254f9 aliguori
238 54f254f9 aliguori
/*
239 54f254f9 aliguori
 * Mark all outstanding async packets as invalid.
240 54f254f9 aliguori
 * This is used for canceling them when TDs are removed by the HCD.
241 54f254f9 aliguori
 */
242 f8af1e88 Gerd Hoffmann
static void uhci_async_validate_begin(UHCIState *s)
243 54f254f9 aliguori
{
244 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
245 54f254f9 aliguori
246 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(queue, &s->queues, next) {
247 f8af1e88 Gerd Hoffmann
        queue->valid--;
248 54f254f9 aliguori
    }
249 54f254f9 aliguori
}
250 54f254f9 aliguori
251 54f254f9 aliguori
/*
252 54f254f9 aliguori
 * Cancel async packets that are no longer valid
253 54f254f9 aliguori
 */
254 54f254f9 aliguori
static void uhci_async_validate_end(UHCIState *s)
255 54f254f9 aliguori
{
256 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue, *n;
257 f8af1e88 Gerd Hoffmann
    UHCIAsync *async;
258 54f254f9 aliguori
259 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
260 f8af1e88 Gerd Hoffmann
        if (queue->valid > 0) {
261 54f254f9 aliguori
            continue;
262 54f254f9 aliguori
        }
263 f8af1e88 Gerd Hoffmann
        while (!QTAILQ_EMPTY(&queue->asyncs)) {
264 f8af1e88 Gerd Hoffmann
            async = QTAILQ_FIRST(&queue->asyncs);
265 f8af1e88 Gerd Hoffmann
            uhci_async_unlink(async);
266 f8af1e88 Gerd Hoffmann
            uhci_async_cancel(async);
267 f8af1e88 Gerd Hoffmann
        }
268 f8af1e88 Gerd Hoffmann
        uhci_queue_free(queue);
269 54f254f9 aliguori
    }
270 54f254f9 aliguori
}
271 54f254f9 aliguori
272 07771f6f Gerd Hoffmann
static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
273 07771f6f Gerd Hoffmann
{
274 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
275 07771f6f Gerd Hoffmann
    UHCIAsync *curr, *n;
276 07771f6f Gerd Hoffmann
277 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(queue, &s->queues, next) {
278 f8af1e88 Gerd Hoffmann
        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
279 f8af1e88 Gerd Hoffmann
            if (!usb_packet_is_inflight(&curr->packet) ||
280 f8af1e88 Gerd Hoffmann
                curr->packet.ep->dev != dev) {
281 f8af1e88 Gerd Hoffmann
                continue;
282 f8af1e88 Gerd Hoffmann
            }
283 f8af1e88 Gerd Hoffmann
            uhci_async_unlink(curr);
284 f8af1e88 Gerd Hoffmann
            uhci_async_cancel(curr);
285 07771f6f Gerd Hoffmann
        }
286 07771f6f Gerd Hoffmann
    }
287 07771f6f Gerd Hoffmann
}
288 07771f6f Gerd Hoffmann
289 54f254f9 aliguori
static void uhci_async_cancel_all(UHCIState *s)
290 54f254f9 aliguori
{
291 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
292 ddf6583f Gerd Hoffmann
    UHCIAsync *curr, *n;
293 54f254f9 aliguori
294 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(queue, &s->queues, next) {
295 f8af1e88 Gerd Hoffmann
        QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
296 f8af1e88 Gerd Hoffmann
            uhci_async_unlink(curr);
297 f8af1e88 Gerd Hoffmann
            uhci_async_cancel(curr);
298 f8af1e88 Gerd Hoffmann
        }
299 60f8afcb Gerd Hoffmann
        uhci_queue_free(queue);
300 54f254f9 aliguori
    }
301 54f254f9 aliguori
}
302 54f254f9 aliguori
303 f8af1e88 Gerd Hoffmann
static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, UHCI_TD *td)
304 54f254f9 aliguori
{
305 f8af1e88 Gerd Hoffmann
    uint32_t token = uhci_queue_token(td);
306 f8af1e88 Gerd Hoffmann
    UHCIQueue *queue;
307 ddf6583f Gerd Hoffmann
    UHCIAsync *async;
308 e8ee3c72 aurel32
309 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(queue, &s->queues, next) {
310 f8af1e88 Gerd Hoffmann
        if (queue->token == token) {
311 f8af1e88 Gerd Hoffmann
            break;
312 54f254f9 aliguori
        }
313 f8af1e88 Gerd Hoffmann
    }
314 f8af1e88 Gerd Hoffmann
    if (queue == NULL) {
315 f8af1e88 Gerd Hoffmann
        return NULL;
316 54f254f9 aliguori
    }
317 e8ee3c72 aurel32
318 f8af1e88 Gerd Hoffmann
    QTAILQ_FOREACH(async, &queue->asyncs, next) {
319 f8af1e88 Gerd Hoffmann
        if (async->td == addr) {
320 f8af1e88 Gerd Hoffmann
            return async;
321 f8af1e88 Gerd Hoffmann
        }
322 f8af1e88 Gerd Hoffmann
    }
323 e8ee3c72 aurel32
324 f8af1e88 Gerd Hoffmann
    return NULL;
325 54f254f9 aliguori
}
326 54f254f9 aliguori
327 bb36d470 bellard
static void uhci_update_irq(UHCIState *s)
328 bb36d470 bellard
{
329 bb36d470 bellard
    int level;
330 bb36d470 bellard
    if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
331 bb36d470 bellard
        ((s->status2 & 2) && (s->intr & (1 << 3))) ||
332 bb36d470 bellard
        ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
333 bb36d470 bellard
        ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
334 bb36d470 bellard
        (s->status & UHCI_STS_HSERR) ||
335 bb36d470 bellard
        (s->status & UHCI_STS_HCPERR)) {
336 bb36d470 bellard
        level = 1;
337 bb36d470 bellard
    } else {
338 bb36d470 bellard
        level = 0;
339 bb36d470 bellard
    }
340 d537cf6c pbrook
    qemu_set_irq(s->dev.irq[3], level);
341 bb36d470 bellard
}
342 bb36d470 bellard
343 c8075ac3 Gleb Natapov
static void uhci_reset(void *opaque)
344 bb36d470 bellard
{
345 c8075ac3 Gleb Natapov
    UHCIState *s = opaque;
346 bb36d470 bellard
    uint8_t *pci_conf;
347 bb36d470 bellard
    int i;
348 bb36d470 bellard
    UHCIPort *port;
349 bb36d470 bellard
350 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_reset();
351 6f382b5e aliguori
352 bb36d470 bellard
    pci_conf = s->dev.config;
353 bb36d470 bellard
354 bb36d470 bellard
    pci_conf[0x6a] = 0x01; /* usb clock */
355 bb36d470 bellard
    pci_conf[0x6b] = 0x00;
356 bb36d470 bellard
    s->cmd = 0;
357 bb36d470 bellard
    s->status = 0;
358 bb36d470 bellard
    s->status2 = 0;
359 bb36d470 bellard
    s->intr = 0;
360 bb36d470 bellard
    s->fl_base_addr = 0;
361 bb36d470 bellard
    s->sof_timing = 64;
362 54f254f9 aliguori
363 bb36d470 bellard
    for(i = 0; i < NB_PORTS; i++) {
364 bb36d470 bellard
        port = &s->ports[i];
365 bb36d470 bellard
        port->ctrl = 0x0080;
366 891fb2cd Gerd Hoffmann
        if (port->port.dev && port->port.dev->attached) {
367 d28f4e2d Gerd Hoffmann
            usb_port_reset(&port->port);
368 618c169b Gerd Hoffmann
        }
369 bb36d470 bellard
    }
370 54f254f9 aliguori
371 54f254f9 aliguori
    uhci_async_cancel_all(s);
372 bb36d470 bellard
}
373 bb36d470 bellard
374 817afc61 Juan Quintela
static void uhci_pre_save(void *opaque)
375 b9dc033c balrog
{
376 b9dc033c balrog
    UHCIState *s = opaque;
377 b9dc033c balrog
378 6f382b5e aliguori
    uhci_async_cancel_all(s);
379 b9dc033c balrog
}
380 b9dc033c balrog
381 817afc61 Juan Quintela
static const VMStateDescription vmstate_uhci_port = {
382 817afc61 Juan Quintela
    .name = "uhci port",
383 817afc61 Juan Quintela
    .version_id = 1,
384 817afc61 Juan Quintela
    .minimum_version_id = 1,
385 817afc61 Juan Quintela
    .minimum_version_id_old = 1,
386 817afc61 Juan Quintela
    .fields      = (VMStateField []) {
387 817afc61 Juan Quintela
        VMSTATE_UINT16(ctrl, UHCIPort),
388 817afc61 Juan Quintela
        VMSTATE_END_OF_LIST()
389 817afc61 Juan Quintela
    }
390 817afc61 Juan Quintela
};
391 817afc61 Juan Quintela
392 817afc61 Juan Quintela
static const VMStateDescription vmstate_uhci = {
393 817afc61 Juan Quintela
    .name = "uhci",
394 6881dd5f TeLeMan
    .version_id = 2,
395 817afc61 Juan Quintela
    .minimum_version_id = 1,
396 817afc61 Juan Quintela
    .minimum_version_id_old = 1,
397 817afc61 Juan Quintela
    .pre_save = uhci_pre_save,
398 817afc61 Juan Quintela
    .fields      = (VMStateField []) {
399 817afc61 Juan Quintela
        VMSTATE_PCI_DEVICE(dev, UHCIState),
400 817afc61 Juan Quintela
        VMSTATE_UINT8_EQUAL(num_ports_vmstate, UHCIState),
401 817afc61 Juan Quintela
        VMSTATE_STRUCT_ARRAY(ports, UHCIState, NB_PORTS, 1,
402 817afc61 Juan Quintela
                             vmstate_uhci_port, UHCIPort),
403 817afc61 Juan Quintela
        VMSTATE_UINT16(cmd, UHCIState),
404 817afc61 Juan Quintela
        VMSTATE_UINT16(status, UHCIState),
405 817afc61 Juan Quintela
        VMSTATE_UINT16(intr, UHCIState),
406 817afc61 Juan Quintela
        VMSTATE_UINT16(frnum, UHCIState),
407 817afc61 Juan Quintela
        VMSTATE_UINT32(fl_base_addr, UHCIState),
408 817afc61 Juan Quintela
        VMSTATE_UINT8(sof_timing, UHCIState),
409 817afc61 Juan Quintela
        VMSTATE_UINT8(status2, UHCIState),
410 817afc61 Juan Quintela
        VMSTATE_TIMER(frame_timer, UHCIState),
411 6881dd5f TeLeMan
        VMSTATE_INT64_V(expire_time, UHCIState, 2),
412 817afc61 Juan Quintela
        VMSTATE_END_OF_LIST()
413 817afc61 Juan Quintela
    }
414 817afc61 Juan Quintela
};
415 b9dc033c balrog
416 bb36d470 bellard
static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
417 bb36d470 bellard
{
418 bb36d470 bellard
    UHCIState *s = opaque;
419 3b46e624 ths
420 bb36d470 bellard
    addr &= 0x1f;
421 bb36d470 bellard
    switch(addr) {
422 bb36d470 bellard
    case 0x0c:
423 bb36d470 bellard
        s->sof_timing = val;
424 bb36d470 bellard
        break;
425 bb36d470 bellard
    }
426 bb36d470 bellard
}
427 bb36d470 bellard
428 bb36d470 bellard
static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
429 bb36d470 bellard
{
430 bb36d470 bellard
    UHCIState *s = opaque;
431 bb36d470 bellard
    uint32_t val;
432 bb36d470 bellard
433 bb36d470 bellard
    addr &= 0x1f;
434 bb36d470 bellard
    switch(addr) {
435 bb36d470 bellard
    case 0x0c:
436 bb36d470 bellard
        val = s->sof_timing;
437 d80cfb3f pbrook
        break;
438 bb36d470 bellard
    default:
439 bb36d470 bellard
        val = 0xff;
440 bb36d470 bellard
        break;
441 bb36d470 bellard
    }
442 bb36d470 bellard
    return val;
443 bb36d470 bellard
}
444 bb36d470 bellard
445 bb36d470 bellard
static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
446 bb36d470 bellard
{
447 bb36d470 bellard
    UHCIState *s = opaque;
448 3b46e624 ths
449 bb36d470 bellard
    addr &= 0x1f;
450 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_mmio_writew(addr, val);
451 54f254f9 aliguori
452 bb36d470 bellard
    switch(addr) {
453 bb36d470 bellard
    case 0x00:
454 bb36d470 bellard
        if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
455 bb36d470 bellard
            /* start frame processing */
456 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_schedule_start();
457 94cc916a Gerd Hoffmann
            s->expire_time = qemu_get_clock_ns(vm_clock) +
458 94cc916a Gerd Hoffmann
                (get_ticks_per_sec() / FRAME_TIMER_FREQ);
459 74475455 Paolo Bonzini
            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
460 52328140 bellard
            s->status &= ~UHCI_STS_HCHALTED;
461 467d409f bellard
        } else if (!(val & UHCI_CMD_RS)) {
462 52328140 bellard
            s->status |= UHCI_STS_HCHALTED;
463 bb36d470 bellard
        }
464 bb36d470 bellard
        if (val & UHCI_CMD_GRESET) {
465 bb36d470 bellard
            UHCIPort *port;
466 bb36d470 bellard
            int i;
467 bb36d470 bellard
468 bb36d470 bellard
            /* send reset on the USB bus */
469 bb36d470 bellard
            for(i = 0; i < NB_PORTS; i++) {
470 bb36d470 bellard
                port = &s->ports[i];
471 d28f4e2d Gerd Hoffmann
                usb_device_reset(port->port.dev);
472 bb36d470 bellard
            }
473 bb36d470 bellard
            uhci_reset(s);
474 bb36d470 bellard
            return;
475 bb36d470 bellard
        }
476 5e9ab4c4 bellard
        if (val & UHCI_CMD_HCRESET) {
477 bb36d470 bellard
            uhci_reset(s);
478 bb36d470 bellard
            return;
479 bb36d470 bellard
        }
480 bb36d470 bellard
        s->cmd = val;
481 bb36d470 bellard
        break;
482 bb36d470 bellard
    case 0x02:
483 bb36d470 bellard
        s->status &= ~val;
484 bb36d470 bellard
        /* XXX: the chip spec is not coherent, so we add a hidden
485 bb36d470 bellard
           register to distinguish between IOC and SPD */
486 bb36d470 bellard
        if (val & UHCI_STS_USBINT)
487 bb36d470 bellard
            s->status2 = 0;
488 bb36d470 bellard
        uhci_update_irq(s);
489 bb36d470 bellard
        break;
490 bb36d470 bellard
    case 0x04:
491 bb36d470 bellard
        s->intr = val;
492 bb36d470 bellard
        uhci_update_irq(s);
493 bb36d470 bellard
        break;
494 bb36d470 bellard
    case 0x06:
495 bb36d470 bellard
        if (s->status & UHCI_STS_HCHALTED)
496 bb36d470 bellard
            s->frnum = val & 0x7ff;
497 bb36d470 bellard
        break;
498 bb36d470 bellard
    case 0x10 ... 0x1f:
499 bb36d470 bellard
        {
500 bb36d470 bellard
            UHCIPort *port;
501 bb36d470 bellard
            USBDevice *dev;
502 bb36d470 bellard
            int n;
503 bb36d470 bellard
504 bb36d470 bellard
            n = (addr >> 1) & 7;
505 bb36d470 bellard
            if (n >= NB_PORTS)
506 bb36d470 bellard
                return;
507 bb36d470 bellard
            port = &s->ports[n];
508 a594cfbf bellard
            dev = port->port.dev;
509 891fb2cd Gerd Hoffmann
            if (dev && dev->attached) {
510 bb36d470 bellard
                /* port reset */
511 5fafdf24 ths
                if ( (val & UHCI_PORT_RESET) &&
512 bb36d470 bellard
                     !(port->ctrl & UHCI_PORT_RESET) ) {
513 d28f4e2d Gerd Hoffmann
                    usb_device_reset(dev);
514 bb36d470 bellard
                }
515 bb36d470 bellard
            }
516 9159f679 Gerd Hoffmann
            port->ctrl &= UHCI_PORT_READ_ONLY;
517 9159f679 Gerd Hoffmann
            port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
518 bb36d470 bellard
            /* some bits are reset when a '1' is written to them */
519 9159f679 Gerd Hoffmann
            port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
520 bb36d470 bellard
        }
521 bb36d470 bellard
        break;
522 bb36d470 bellard
    }
523 bb36d470 bellard
}
524 bb36d470 bellard
525 bb36d470 bellard
static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
526 bb36d470 bellard
{
527 bb36d470 bellard
    UHCIState *s = opaque;
528 bb36d470 bellard
    uint32_t val;
529 bb36d470 bellard
530 bb36d470 bellard
    addr &= 0x1f;
531 bb36d470 bellard
    switch(addr) {
532 bb36d470 bellard
    case 0x00:
533 bb36d470 bellard
        val = s->cmd;
534 bb36d470 bellard
        break;
535 bb36d470 bellard
    case 0x02:
536 bb36d470 bellard
        val = s->status;
537 bb36d470 bellard
        break;
538 bb36d470 bellard
    case 0x04:
539 bb36d470 bellard
        val = s->intr;
540 bb36d470 bellard
        break;
541 bb36d470 bellard
    case 0x06:
542 bb36d470 bellard
        val = s->frnum;
543 bb36d470 bellard
        break;
544 bb36d470 bellard
    case 0x10 ... 0x1f:
545 bb36d470 bellard
        {
546 bb36d470 bellard
            UHCIPort *port;
547 bb36d470 bellard
            int n;
548 bb36d470 bellard
            n = (addr >> 1) & 7;
549 5fafdf24 ths
            if (n >= NB_PORTS)
550 bb36d470 bellard
                goto read_default;
551 bb36d470 bellard
            port = &s->ports[n];
552 bb36d470 bellard
            val = port->ctrl;
553 bb36d470 bellard
        }
554 bb36d470 bellard
        break;
555 bb36d470 bellard
    default:
556 bb36d470 bellard
    read_default:
557 bb36d470 bellard
        val = 0xff7f; /* disabled port */
558 bb36d470 bellard
        break;
559 bb36d470 bellard
    }
560 54f254f9 aliguori
561 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_mmio_readw(addr, val);
562 54f254f9 aliguori
563 bb36d470 bellard
    return val;
564 bb36d470 bellard
}
565 bb36d470 bellard
566 bb36d470 bellard
static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
567 bb36d470 bellard
{
568 bb36d470 bellard
    UHCIState *s = opaque;
569 bb36d470 bellard
570 bb36d470 bellard
    addr &= 0x1f;
571 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_mmio_writel(addr, val);
572 54f254f9 aliguori
573 bb36d470 bellard
    switch(addr) {
574 bb36d470 bellard
    case 0x08:
575 bb36d470 bellard
        s->fl_base_addr = val & ~0xfff;
576 bb36d470 bellard
        break;
577 bb36d470 bellard
    }
578 bb36d470 bellard
}
579 bb36d470 bellard
580 bb36d470 bellard
static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
581 bb36d470 bellard
{
582 bb36d470 bellard
    UHCIState *s = opaque;
583 bb36d470 bellard
    uint32_t val;
584 bb36d470 bellard
585 bb36d470 bellard
    addr &= 0x1f;
586 bb36d470 bellard
    switch(addr) {
587 bb36d470 bellard
    case 0x08:
588 bb36d470 bellard
        val = s->fl_base_addr;
589 bb36d470 bellard
        break;
590 bb36d470 bellard
    default:
591 bb36d470 bellard
        val = 0xffffffff;
592 bb36d470 bellard
        break;
593 bb36d470 bellard
    }
594 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_mmio_readl(addr, val);
595 bb36d470 bellard
    return val;
596 bb36d470 bellard
}
597 bb36d470 bellard
598 96217e31 ths
/* signal resume if controller suspended */
599 96217e31 ths
static void uhci_resume (void *opaque)
600 96217e31 ths
{
601 96217e31 ths
    UHCIState *s = (UHCIState *)opaque;
602 96217e31 ths
603 96217e31 ths
    if (!s)
604 96217e31 ths
        return;
605 96217e31 ths
606 96217e31 ths
    if (s->cmd & UHCI_CMD_EGSM) {
607 96217e31 ths
        s->cmd |= UHCI_CMD_FGR;
608 96217e31 ths
        s->status |= UHCI_STS_RD;
609 96217e31 ths
        uhci_update_irq(s);
610 96217e31 ths
    }
611 96217e31 ths
}
612 96217e31 ths
613 618c169b Gerd Hoffmann
static void uhci_attach(USBPort *port1)
614 bb36d470 bellard
{
615 bb36d470 bellard
    UHCIState *s = port1->opaque;
616 bb36d470 bellard
    UHCIPort *port = &s->ports[port1->index];
617 bb36d470 bellard
618 618c169b Gerd Hoffmann
    /* set connect status */
619 618c169b Gerd Hoffmann
    port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
620 61064870 pbrook
621 618c169b Gerd Hoffmann
    /* update speed */
622 618c169b Gerd Hoffmann
    if (port->port.dev->speed == USB_SPEED_LOW) {
623 618c169b Gerd Hoffmann
        port->ctrl |= UHCI_PORT_LSDA;
624 bb36d470 bellard
    } else {
625 618c169b Gerd Hoffmann
        port->ctrl &= ~UHCI_PORT_LSDA;
626 618c169b Gerd Hoffmann
    }
627 96217e31 ths
628 618c169b Gerd Hoffmann
    uhci_resume(s);
629 618c169b Gerd Hoffmann
}
630 96217e31 ths
631 618c169b Gerd Hoffmann
static void uhci_detach(USBPort *port1)
632 618c169b Gerd Hoffmann
{
633 618c169b Gerd Hoffmann
    UHCIState *s = port1->opaque;
634 618c169b Gerd Hoffmann
    UHCIPort *port = &s->ports[port1->index];
635 618c169b Gerd Hoffmann
636 4706ab6c Hans de Goede
    uhci_async_cancel_device(s, port1->dev);
637 4706ab6c Hans de Goede
638 618c169b Gerd Hoffmann
    /* set connect status */
639 618c169b Gerd Hoffmann
    if (port->ctrl & UHCI_PORT_CCS) {
640 618c169b Gerd Hoffmann
        port->ctrl &= ~UHCI_PORT_CCS;
641 618c169b Gerd Hoffmann
        port->ctrl |= UHCI_PORT_CSC;
642 bb36d470 bellard
    }
643 618c169b Gerd Hoffmann
    /* disable port */
644 618c169b Gerd Hoffmann
    if (port->ctrl & UHCI_PORT_EN) {
645 618c169b Gerd Hoffmann
        port->ctrl &= ~UHCI_PORT_EN;
646 618c169b Gerd Hoffmann
        port->ctrl |= UHCI_PORT_ENC;
647 618c169b Gerd Hoffmann
    }
648 618c169b Gerd Hoffmann
649 618c169b Gerd Hoffmann
    uhci_resume(s);
650 bb36d470 bellard
}
651 bb36d470 bellard
652 4706ab6c Hans de Goede
static void uhci_child_detach(USBPort *port1, USBDevice *child)
653 4706ab6c Hans de Goede
{
654 4706ab6c Hans de Goede
    UHCIState *s = port1->opaque;
655 4706ab6c Hans de Goede
656 4706ab6c Hans de Goede
    uhci_async_cancel_device(s, child);
657 4706ab6c Hans de Goede
}
658 4706ab6c Hans de Goede
659 d47e59b8 Hans de Goede
static void uhci_wakeup(USBPort *port1)
660 9159f679 Gerd Hoffmann
{
661 d47e59b8 Hans de Goede
    UHCIState *s = port1->opaque;
662 d47e59b8 Hans de Goede
    UHCIPort *port = &s->ports[port1->index];
663 9159f679 Gerd Hoffmann
664 9159f679 Gerd Hoffmann
    if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
665 9159f679 Gerd Hoffmann
        port->ctrl |= UHCI_PORT_RD;
666 9159f679 Gerd Hoffmann
        uhci_resume(s);
667 9159f679 Gerd Hoffmann
    }
668 9159f679 Gerd Hoffmann
}
669 9159f679 Gerd Hoffmann
670 461700c1 Gerd Hoffmann
static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr)
671 bb36d470 bellard
{
672 461700c1 Gerd Hoffmann
    USBDevice *dev;
673 461700c1 Gerd Hoffmann
    int i;
674 54f254f9 aliguori
675 461700c1 Gerd Hoffmann
    for (i = 0; i < NB_PORTS; i++) {
676 54f254f9 aliguori
        UHCIPort *port = &s->ports[i];
677 461700c1 Gerd Hoffmann
        if (!(port->ctrl & UHCI_PORT_EN)) {
678 461700c1 Gerd Hoffmann
            continue;
679 461700c1 Gerd Hoffmann
        }
680 461700c1 Gerd Hoffmann
        dev = usb_find_device(&port->port, addr);
681 461700c1 Gerd Hoffmann
        if (dev != NULL) {
682 461700c1 Gerd Hoffmann
            return dev;
683 891fb2cd Gerd Hoffmann
        }
684 bb36d470 bellard
    }
685 461700c1 Gerd Hoffmann
    return NULL;
686 bb36d470 bellard
}
687 bb36d470 bellard
688 d47e59b8 Hans de Goede
static void uhci_async_complete(USBPort *port, USBPacket *packet);
689 54f254f9 aliguori
static void uhci_process_frame(UHCIState *s);
690 4d611c9a pbrook
691 bb36d470 bellard
/* return -1 if fatal error (frame must be stopped)
692 bb36d470 bellard
          0 if TD successful
693 bb36d470 bellard
          1 if TD unsuccessful or inactive
694 bb36d470 bellard
*/
695 54f254f9 aliguori
static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
696 bb36d470 bellard
{
697 54f254f9 aliguori
    int len = 0, max_len, err, ret;
698 bb36d470 bellard
    uint8_t pid;
699 bb36d470 bellard
700 54f254f9 aliguori
    max_len = ((td->token >> 21) + 1) & 0x7ff;
701 54f254f9 aliguori
    pid = td->token & 0xff;
702 54f254f9 aliguori
703 4f4321c1 Gerd Hoffmann
    ret = async->packet.result;
704 54f254f9 aliguori
705 54f254f9 aliguori
    if (td->ctrl & TD_CTRL_IOS)
706 54f254f9 aliguori
        td->ctrl &= ~TD_CTRL_ACTIVE;
707 bb36d470 bellard
708 54f254f9 aliguori
    if (ret < 0)
709 54f254f9 aliguori
        goto out;
710 b9dc033c balrog
711 4f4321c1 Gerd Hoffmann
    len = async->packet.result;
712 54f254f9 aliguori
    td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
713 54f254f9 aliguori
714 54f254f9 aliguori
    /* The NAK bit may have been set by a previous frame, so clear it
715 54f254f9 aliguori
       here.  The docs are somewhat unclear, but win2k relies on this
716 54f254f9 aliguori
       behavior.  */
717 54f254f9 aliguori
    td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
718 5bd2c0d7 Paul Brook
    if (td->ctrl & TD_CTRL_IOC)
719 5bd2c0d7 Paul Brook
        *int_mask |= 0x01;
720 54f254f9 aliguori
721 54f254f9 aliguori
    if (pid == USB_TOKEN_IN) {
722 54f254f9 aliguori
        if (len > max_len) {
723 54f254f9 aliguori
            ret = USB_RET_BABBLE;
724 54f254f9 aliguori
            goto out;
725 4d611c9a pbrook
        }
726 b9dc033c balrog
727 54f254f9 aliguori
        if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
728 bb36d470 bellard
            *int_mask |= 0x02;
729 bb36d470 bellard
            /* short packet: do not update QH */
730 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_packet_complete_shortxfer(async->queue->token,
731 50dcc0f8 Gerd Hoffmann
                                                    async->td);
732 60e1b2a6 Gerd Hoffmann
            return TD_RESULT_NEXT_QH;
733 bb36d470 bellard
        }
734 54f254f9 aliguori
    }
735 54f254f9 aliguori
736 54f254f9 aliguori
    /* success */
737 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_packet_complete_success(async->queue->token, async->td);
738 60e1b2a6 Gerd Hoffmann
    return TD_RESULT_COMPLETE;
739 54f254f9 aliguori
740 54f254f9 aliguori
out:
741 54f254f9 aliguori
    switch(ret) {
742 54f254f9 aliguori
    case USB_RET_STALL:
743 54f254f9 aliguori
        td->ctrl |= TD_CTRL_STALL;
744 54f254f9 aliguori
        td->ctrl &= ~TD_CTRL_ACTIVE;
745 8656954a Jan Vesely
        s->status |= UHCI_STS_USBERR;
746 0070f095 Gerd Hoffmann
        if (td->ctrl & TD_CTRL_IOC) {
747 0070f095 Gerd Hoffmann
            *int_mask |= 0x01;
748 0070f095 Gerd Hoffmann
        }
749 8656954a Jan Vesely
        uhci_update_irq(s);
750 50dcc0f8 Gerd Hoffmann
        trace_usb_uhci_packet_complete_stall(async->queue->token, async->td);
751 60e1b2a6 Gerd Hoffmann
        return TD_RESULT_NEXT_QH;
752 54f254f9 aliguori
753 54f254f9 aliguori
    case USB_RET_BABBLE:
754 54f254f9 aliguori
        td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
755 54f254f9 aliguori
        td->ctrl &= ~TD_CTRL_ACTIVE;
756 8656954a Jan Vesely
        s->status |= UHCI_STS_USBERR;
757 0070f095 Gerd Hoffmann
        if (td->ctrl & TD_CTRL_IOC) {
758 0070f095 Gerd Hoffmann
            *int_mask |= 0x01;
759 0070f095 Gerd Hoffmann
        }
760 8656954a Jan Vesely
        uhci_update_irq(s);
761 54f254f9 aliguori
        /* frame interrupted */
762 50dcc0f8 Gerd Hoffmann
        trace_usb_uhci_packet_complete_babble(async->queue->token, async->td);
763 60e1b2a6 Gerd Hoffmann
        return TD_RESULT_STOP_FRAME;
764 54f254f9 aliguori
765 54f254f9 aliguori
    case USB_RET_NAK:
766 54f254f9 aliguori
        td->ctrl |= TD_CTRL_NAK;
767 54f254f9 aliguori
        if (pid == USB_TOKEN_SETUP)
768 54f254f9 aliguori
            break;
769 60e1b2a6 Gerd Hoffmann
        return TD_RESULT_NEXT_QH;
770 54f254f9 aliguori
771 d61000a8 Hans de Goede
    case USB_RET_IOERROR:
772 54f254f9 aliguori
    case USB_RET_NODEV:
773 54f254f9 aliguori
    default:
774 54f254f9 aliguori
        break;
775 54f254f9 aliguori
    }
776 54f254f9 aliguori
777 54f254f9 aliguori
    /* Retry the TD if error count is not zero */
778 54f254f9 aliguori
779 54f254f9 aliguori
    td->ctrl |= TD_CTRL_TIMEOUT;
780 54f254f9 aliguori
    err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
781 54f254f9 aliguori
    if (err != 0) {
782 54f254f9 aliguori
        err--;
783 54f254f9 aliguori
        if (err == 0) {
784 bb36d470 bellard
            td->ctrl &= ~TD_CTRL_ACTIVE;
785 54f254f9 aliguori
            s->status |= UHCI_STS_USBERR;
786 5bd2c0d7 Paul Brook
            if (td->ctrl & TD_CTRL_IOC)
787 5bd2c0d7 Paul Brook
                *int_mask |= 0x01;
788 54f254f9 aliguori
            uhci_update_irq(s);
789 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_packet_complete_error(async->queue->token,
790 50dcc0f8 Gerd Hoffmann
                                                 async->td);
791 bb36d470 bellard
        }
792 bb36d470 bellard
    }
793 54f254f9 aliguori
    td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
794 54f254f9 aliguori
        (err << TD_CTRL_ERROR_SHIFT);
795 60e1b2a6 Gerd Hoffmann
    return TD_RESULT_NEXT_QH;
796 bb36d470 bellard
}
797 bb36d470 bellard
798 54f254f9 aliguori
static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
799 54f254f9 aliguori
{
800 54f254f9 aliguori
    UHCIAsync *async;
801 5d808245 aurel32
    int len = 0, max_len;
802 f8af1e88 Gerd Hoffmann
    uint8_t pid;
803 079d0b7f Gerd Hoffmann
    USBDevice *dev;
804 079d0b7f Gerd Hoffmann
    USBEndpoint *ep;
805 54f254f9 aliguori
806 54f254f9 aliguori
    /* Is active ? */
807 54f254f9 aliguori
    if (!(td->ctrl & TD_CTRL_ACTIVE))
808 60e1b2a6 Gerd Hoffmann
        return TD_RESULT_NEXT_QH;
809 54f254f9 aliguori
810 f8af1e88 Gerd Hoffmann
    async = uhci_async_find_td(s, addr, td);
811 54f254f9 aliguori
    if (async) {
812 54f254f9 aliguori
        /* Already submitted */
813 f8af1e88 Gerd Hoffmann
        async->queue->valid = 32;
814 54f254f9 aliguori
815 54f254f9 aliguori
        if (!async->done)
816 4efe4ef3 Gerd Hoffmann
            return TD_RESULT_ASYNC_CONT;
817 54f254f9 aliguori
818 f8af1e88 Gerd Hoffmann
        uhci_async_unlink(async);
819 54f254f9 aliguori
        goto done;
820 54f254f9 aliguori
    }
821 54f254f9 aliguori
822 54f254f9 aliguori
    /* Allocate new packet */
823 16ce543e Gerd Hoffmann
    async = uhci_async_alloc(uhci_queue_get(s, td), addr);
824 54f254f9 aliguori
825 8e65b7c0 David S. Ahern
    /* valid needs to be large enough to handle 10 frame delay
826 8e65b7c0 David S. Ahern
     * for initial isochronous requests
827 8e65b7c0 David S. Ahern
     */
828 f8af1e88 Gerd Hoffmann
    async->queue->valid = 32;
829 f8af1e88 Gerd Hoffmann
    async->isoc  = td->ctrl & TD_CTRL_IOS;
830 54f254f9 aliguori
831 54f254f9 aliguori
    max_len = ((td->token >> 21) + 1) & 0x7ff;
832 54f254f9 aliguori
    pid = td->token & 0xff;
833 54f254f9 aliguori
834 079d0b7f Gerd Hoffmann
    dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
835 079d0b7f Gerd Hoffmann
    ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
836 079d0b7f Gerd Hoffmann
    usb_packet_setup(&async->packet, pid, ep);
837 df5e66ee Gerd Hoffmann
    qemu_sglist_add(&async->sgl, td->buffer, max_len);
838 df5e66ee Gerd Hoffmann
    usb_packet_map(&async->packet, &async->sgl);
839 54f254f9 aliguori
840 54f254f9 aliguori
    switch(pid) {
841 54f254f9 aliguori
    case USB_TOKEN_OUT:
842 54f254f9 aliguori
    case USB_TOKEN_SETUP:
843 079d0b7f Gerd Hoffmann
        len = usb_handle_packet(dev, &async->packet);
844 5d808245 aurel32
        if (len >= 0)
845 5d808245 aurel32
            len = max_len;
846 54f254f9 aliguori
        break;
847 54f254f9 aliguori
848 54f254f9 aliguori
    case USB_TOKEN_IN:
849 079d0b7f Gerd Hoffmann
        len = usb_handle_packet(dev, &async->packet);
850 54f254f9 aliguori
        break;
851 54f254f9 aliguori
852 54f254f9 aliguori
    default:
853 54f254f9 aliguori
        /* invalid pid : frame interrupted */
854 f8af1e88 Gerd Hoffmann
        uhci_async_free(async);
855 54f254f9 aliguori
        s->status |= UHCI_STS_HCPERR;
856 54f254f9 aliguori
        uhci_update_irq(s);
857 60e1b2a6 Gerd Hoffmann
        return TD_RESULT_STOP_FRAME;
858 54f254f9 aliguori
    }
859 54f254f9 aliguori
 
860 5d808245 aurel32
    if (len == USB_RET_ASYNC) {
861 f8af1e88 Gerd Hoffmann
        uhci_async_link(async);
862 4efe4ef3 Gerd Hoffmann
        return TD_RESULT_ASYNC_START;
863 54f254f9 aliguori
    }
864 54f254f9 aliguori
865 4f4321c1 Gerd Hoffmann
    async->packet.result = len;
866 54f254f9 aliguori
867 54f254f9 aliguori
done:
868 5d808245 aurel32
    len = uhci_complete_td(s, td, async, int_mask);
869 df5e66ee Gerd Hoffmann
    usb_packet_unmap(&async->packet);
870 f8af1e88 Gerd Hoffmann
    uhci_async_free(async);
871 5d808245 aurel32
    return len;
872 54f254f9 aliguori
}
873 54f254f9 aliguori
874 d47e59b8 Hans de Goede
static void uhci_async_complete(USBPort *port, USBPacket *packet)
875 4d611c9a pbrook
{
876 7b5a44c5 Gerd Hoffmann
    UHCIAsync *async = container_of(packet, UHCIAsync, packet);
877 f8af1e88 Gerd Hoffmann
    UHCIState *s = async->queue->uhci;
878 54f254f9 aliguori
879 8e65b7c0 David S. Ahern
    if (async->isoc) {
880 8e65b7c0 David S. Ahern
        UHCI_TD td;
881 8e65b7c0 David S. Ahern
        uint32_t link = async->td;
882 8e65b7c0 David S. Ahern
        uint32_t int_mask = 0, val;
883 d4c4e6fd Blue Swirl
884 9fe2fd67 David Gibson
        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
885 8e65b7c0 David S. Ahern
        le32_to_cpus(&td.link);
886 8e65b7c0 David S. Ahern
        le32_to_cpus(&td.ctrl);
887 8e65b7c0 David S. Ahern
        le32_to_cpus(&td.token);
888 8e65b7c0 David S. Ahern
        le32_to_cpus(&td.buffer);
889 8e65b7c0 David S. Ahern
890 f8af1e88 Gerd Hoffmann
        uhci_async_unlink(async);
891 d4c4e6fd Blue Swirl
        uhci_complete_td(s, &td, async, &int_mask);
892 8e65b7c0 David S. Ahern
        s->pending_int_mask |= int_mask;
893 54f254f9 aliguori
894 8e65b7c0 David S. Ahern
        /* update the status bits of the TD */
895 8e65b7c0 David S. Ahern
        val = cpu_to_le32(td.ctrl);
896 9fe2fd67 David Gibson
        pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
897 f8af1e88 Gerd Hoffmann
        uhci_async_free(async);
898 8e65b7c0 David S. Ahern
    } else {
899 8e65b7c0 David S. Ahern
        async->done = 1;
900 8e65b7c0 David S. Ahern
        uhci_process_frame(s);
901 8e65b7c0 David S. Ahern
    }
902 54f254f9 aliguori
}
903 54f254f9 aliguori
904 54f254f9 aliguori
static int is_valid(uint32_t link)
905 54f254f9 aliguori
{
906 54f254f9 aliguori
    return (link & 1) == 0;
907 54f254f9 aliguori
}
908 54f254f9 aliguori
909 54f254f9 aliguori
static int is_qh(uint32_t link)
910 54f254f9 aliguori
{
911 54f254f9 aliguori
    return (link & 2) != 0;
912 54f254f9 aliguori
}
913 54f254f9 aliguori
914 54f254f9 aliguori
static int depth_first(uint32_t link)
915 54f254f9 aliguori
{
916 54f254f9 aliguori
    return (link & 4) != 0;
917 54f254f9 aliguori
}
918 54f254f9 aliguori
919 54f254f9 aliguori
/* QH DB used for detecting QH loops */
920 54f254f9 aliguori
#define UHCI_MAX_QUEUES 128
921 54f254f9 aliguori
typedef struct {
922 54f254f9 aliguori
    uint32_t addr[UHCI_MAX_QUEUES];
923 54f254f9 aliguori
    int      count;
924 54f254f9 aliguori
} QhDb;
925 54f254f9 aliguori
926 54f254f9 aliguori
static void qhdb_reset(QhDb *db)
927 54f254f9 aliguori
{
928 54f254f9 aliguori
    db->count = 0;
929 54f254f9 aliguori
}
930 54f254f9 aliguori
931 54f254f9 aliguori
/* Add QH to DB. Returns 1 if already present or DB is full. */
932 54f254f9 aliguori
static int qhdb_insert(QhDb *db, uint32_t addr)
933 54f254f9 aliguori
{
934 54f254f9 aliguori
    int i;
935 54f254f9 aliguori
    for (i = 0; i < db->count; i++)
936 54f254f9 aliguori
        if (db->addr[i] == addr)
937 54f254f9 aliguori
            return 1;
938 54f254f9 aliguori
939 54f254f9 aliguori
    if (db->count >= UHCI_MAX_QUEUES)
940 54f254f9 aliguori
        return 1;
941 54f254f9 aliguori
942 54f254f9 aliguori
    db->addr[db->count++] = addr;
943 54f254f9 aliguori
    return 0;
944 54f254f9 aliguori
}
945 54f254f9 aliguori
946 5a248289 Gerd Hoffmann
static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
947 5a248289 Gerd Hoffmann
{
948 5a248289 Gerd Hoffmann
    uint32_t int_mask = 0;
949 5a248289 Gerd Hoffmann
    uint32_t plink = td->link;
950 5a248289 Gerd Hoffmann
    uint32_t token = uhci_queue_token(td);
951 5a248289 Gerd Hoffmann
    UHCI_TD ptd;
952 5a248289 Gerd Hoffmann
    int ret;
953 5a248289 Gerd Hoffmann
954 5a248289 Gerd Hoffmann
    while (is_valid(plink)) {
955 5a248289 Gerd Hoffmann
        pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
956 5a248289 Gerd Hoffmann
        le32_to_cpus(&ptd.link);
957 5a248289 Gerd Hoffmann
        le32_to_cpus(&ptd.ctrl);
958 5a248289 Gerd Hoffmann
        le32_to_cpus(&ptd.token);
959 5a248289 Gerd Hoffmann
        le32_to_cpus(&ptd.buffer);
960 5a248289 Gerd Hoffmann
        if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
961 5a248289 Gerd Hoffmann
            break;
962 5a248289 Gerd Hoffmann
        }
963 5a248289 Gerd Hoffmann
        if (uhci_queue_token(&ptd) != token) {
964 5a248289 Gerd Hoffmann
            break;
965 5a248289 Gerd Hoffmann
        }
966 50dcc0f8 Gerd Hoffmann
        trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
967 5a248289 Gerd Hoffmann
        ret = uhci_handle_td(s, plink, &ptd, &int_mask);
968 4efe4ef3 Gerd Hoffmann
        assert(ret == TD_RESULT_ASYNC_START);
969 5a248289 Gerd Hoffmann
        assert(int_mask == 0);
970 5a248289 Gerd Hoffmann
        plink = ptd.link;
971 5a248289 Gerd Hoffmann
    }
972 5a248289 Gerd Hoffmann
}
973 5a248289 Gerd Hoffmann
974 54f254f9 aliguori
static void uhci_process_frame(UHCIState *s)
975 54f254f9 aliguori
{
976 54f254f9 aliguori
    uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
977 3200d108 Gerd Hoffmann
    uint32_t curr_qh, td_count = 0, bytes_count = 0;
978 54f254f9 aliguori
    int cnt, ret;
979 4d611c9a pbrook
    UHCI_TD td;
980 54f254f9 aliguori
    UHCI_QH qh;
981 54f254f9 aliguori
    QhDb qhdb;
982 4d611c9a pbrook
983 54f254f9 aliguori
    frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
984 54f254f9 aliguori
985 9fe2fd67 David Gibson
    pci_dma_read(&s->dev, frame_addr, &link, 4);
986 54f254f9 aliguori
    le32_to_cpus(&link);
987 b9dc033c balrog
988 54f254f9 aliguori
    int_mask = 0;
989 54f254f9 aliguori
    curr_qh  = 0;
990 54f254f9 aliguori
991 54f254f9 aliguori
    qhdb_reset(&qhdb);
992 54f254f9 aliguori
993 54f254f9 aliguori
    for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
994 54f254f9 aliguori
        if (is_qh(link)) {
995 54f254f9 aliguori
            /* QH */
996 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_qh_load(link & ~0xf);
997 54f254f9 aliguori
998 54f254f9 aliguori
            if (qhdb_insert(&qhdb, link)) {
999 54f254f9 aliguori
                /*
1000 54f254f9 aliguori
                 * We're going in circles. Which is not a bug because
1001 3200d108 Gerd Hoffmann
                 * HCD is allowed to do that as part of the BW management.
1002 3200d108 Gerd Hoffmann
                 *
1003 3200d108 Gerd Hoffmann
                 * Stop processing here if
1004 3200d108 Gerd Hoffmann
                 *  (a) no transaction has been done since we've been
1005 3200d108 Gerd Hoffmann
                 *      here last time, or
1006 3200d108 Gerd Hoffmann
                 *  (b) we've reached the usb 1.1 bandwidth, which is
1007 3200d108 Gerd Hoffmann
                 *      1280 bytes/frame.
1008 54f254f9 aliguori
                 */
1009 3200d108 Gerd Hoffmann
                if (td_count == 0) {
1010 50dcc0f8 Gerd Hoffmann
                    trace_usb_uhci_frame_loop_stop_idle();
1011 3200d108 Gerd Hoffmann
                    break;
1012 3200d108 Gerd Hoffmann
                } else if (bytes_count >= 1280) {
1013 50dcc0f8 Gerd Hoffmann
                    trace_usb_uhci_frame_loop_stop_bandwidth();
1014 3200d108 Gerd Hoffmann
                    break;
1015 3200d108 Gerd Hoffmann
                } else {
1016 50dcc0f8 Gerd Hoffmann
                    trace_usb_uhci_frame_loop_continue();
1017 3200d108 Gerd Hoffmann
                    td_count = 0;
1018 3200d108 Gerd Hoffmann
                    qhdb_reset(&qhdb);
1019 3200d108 Gerd Hoffmann
                    qhdb_insert(&qhdb, link);
1020 3200d108 Gerd Hoffmann
                }
1021 54f254f9 aliguori
            }
1022 54f254f9 aliguori
1023 9fe2fd67 David Gibson
            pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
1024 54f254f9 aliguori
            le32_to_cpus(&qh.link);
1025 54f254f9 aliguori
            le32_to_cpus(&qh.el_link);
1026 54f254f9 aliguori
1027 54f254f9 aliguori
            if (!is_valid(qh.el_link)) {
1028 54f254f9 aliguori
                /* QH w/o elements */
1029 54f254f9 aliguori
                curr_qh = 0;
1030 54f254f9 aliguori
                link = qh.link;
1031 54f254f9 aliguori
            } else {
1032 54f254f9 aliguori
                /* QH with elements */
1033 54f254f9 aliguori
                    curr_qh = link;
1034 54f254f9 aliguori
                    link = qh.el_link;
1035 54f254f9 aliguori
            }
1036 54f254f9 aliguori
            continue;
1037 54f254f9 aliguori
        }
1038 54f254f9 aliguori
1039 54f254f9 aliguori
        /* TD */
1040 9fe2fd67 David Gibson
        pci_dma_read(&s->dev, link & ~0xf, &td, sizeof(td));
1041 b9dc033c balrog
        le32_to_cpus(&td.link);
1042 b9dc033c balrog
        le32_to_cpus(&td.ctrl);
1043 b9dc033c balrog
        le32_to_cpus(&td.token);
1044 b9dc033c balrog
        le32_to_cpus(&td.buffer);
1045 50dcc0f8 Gerd Hoffmann
        trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
1046 54f254f9 aliguori
1047 54f254f9 aliguori
        old_td_ctrl = td.ctrl;
1048 54f254f9 aliguori
        ret = uhci_handle_td(s, link, &td, &int_mask);
1049 b9dc033c balrog
        if (old_td_ctrl != td.ctrl) {
1050 54f254f9 aliguori
            /* update the status bits of the TD */
1051 b9dc033c balrog
            val = cpu_to_le32(td.ctrl);
1052 9fe2fd67 David Gibson
            pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
1053 b9dc033c balrog
        }
1054 54f254f9 aliguori
1055 971a5a40 Gerd Hoffmann
        switch (ret) {
1056 60e1b2a6 Gerd Hoffmann
        case TD_RESULT_STOP_FRAME: /* interrupted frame */
1057 971a5a40 Gerd Hoffmann
            goto out;
1058 b9dc033c balrog
1059 60e1b2a6 Gerd Hoffmann
        case TD_RESULT_NEXT_QH:
1060 4efe4ef3 Gerd Hoffmann
        case TD_RESULT_ASYNC_CONT:
1061 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_td_nextqh(curr_qh & ~0xf, link & ~0xf);
1062 54f254f9 aliguori
            link = curr_qh ? qh.link : td.link;
1063 54f254f9 aliguori
            continue;
1064 54f254f9 aliguori
1065 4efe4ef3 Gerd Hoffmann
        case TD_RESULT_ASYNC_START:
1066 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
1067 5a248289 Gerd Hoffmann
            if (is_valid(td.link)) {
1068 5a248289 Gerd Hoffmann
                uhci_fill_queue(s, &td);
1069 5a248289 Gerd Hoffmann
            }
1070 971a5a40 Gerd Hoffmann
            link = curr_qh ? qh.link : td.link;
1071 971a5a40 Gerd Hoffmann
            continue;
1072 54f254f9 aliguori
1073 60e1b2a6 Gerd Hoffmann
        case TD_RESULT_COMPLETE:
1074 50dcc0f8 Gerd Hoffmann
            trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
1075 971a5a40 Gerd Hoffmann
            link = td.link;
1076 971a5a40 Gerd Hoffmann
            td_count++;
1077 971a5a40 Gerd Hoffmann
            bytes_count += (td.ctrl & 0x7ff) + 1;
1078 54f254f9 aliguori
1079 971a5a40 Gerd Hoffmann
            if (curr_qh) {
1080 971a5a40 Gerd Hoffmann
                /* update QH element link */
1081 971a5a40 Gerd Hoffmann
                qh.el_link = link;
1082 971a5a40 Gerd Hoffmann
                val = cpu_to_le32(qh.el_link);
1083 971a5a40 Gerd Hoffmann
                pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, &val, sizeof(val));
1084 54f254f9 aliguori
1085 971a5a40 Gerd Hoffmann
                if (!depth_first(link)) {
1086 971a5a40 Gerd Hoffmann
                    /* done with this QH */
1087 971a5a40 Gerd Hoffmann
                    curr_qh = 0;
1088 971a5a40 Gerd Hoffmann
                    link    = qh.link;
1089 971a5a40 Gerd Hoffmann
                }
1090 54f254f9 aliguori
            }
1091 971a5a40 Gerd Hoffmann
            break;
1092 971a5a40 Gerd Hoffmann
1093 971a5a40 Gerd Hoffmann
        default:
1094 971a5a40 Gerd Hoffmann
            assert(!"unknown return code");
1095 4d611c9a pbrook
        }
1096 54f254f9 aliguori
1097 54f254f9 aliguori
        /* go to the next entry */
1098 4d611c9a pbrook
    }
1099 54f254f9 aliguori
1100 971a5a40 Gerd Hoffmann
out:
1101 8e65b7c0 David S. Ahern
    s->pending_int_mask |= int_mask;
1102 4d611c9a pbrook
}
1103 4d611c9a pbrook
1104 bb36d470 bellard
static void uhci_frame_timer(void *opaque)
1105 bb36d470 bellard
{
1106 bb36d470 bellard
    UHCIState *s = opaque;
1107 8e65b7c0 David S. Ahern
1108 8e65b7c0 David S. Ahern
    /* prepare the timer for the next frame */
1109 8e65b7c0 David S. Ahern
    s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
1110 bb36d470 bellard
1111 bb36d470 bellard
    if (!(s->cmd & UHCI_CMD_RS)) {
1112 54f254f9 aliguori
        /* Full stop */
1113 50dcc0f8 Gerd Hoffmann
        trace_usb_uhci_schedule_stop();
1114 bb36d470 bellard
        qemu_del_timer(s->frame_timer);
1115 d9a528db Gerd Hoffmann
        uhci_async_cancel_all(s);
1116 52328140 bellard
        /* set hchalted bit in status - UHCI11D 2.1.2 */
1117 52328140 bellard
        s->status |= UHCI_STS_HCHALTED;
1118 bb36d470 bellard
        return;
1119 bb36d470 bellard
    }
1120 54f254f9 aliguori
1121 54f254f9 aliguori
    /* Complete the previous frame */
1122 4d611c9a pbrook
    if (s->pending_int_mask) {
1123 4d611c9a pbrook
        s->status2 |= s->pending_int_mask;
1124 54f254f9 aliguori
        s->status  |= UHCI_STS_USBINT;
1125 4d611c9a pbrook
        uhci_update_irq(s);
1126 4d611c9a pbrook
    }
1127 8e65b7c0 David S. Ahern
    s->pending_int_mask = 0;
1128 b9dc033c balrog
1129 54f254f9 aliguori
    /* Start new frame */
1130 54f254f9 aliguori
    s->frnum = (s->frnum + 1) & 0x7ff;
1131 54f254f9 aliguori
1132 50dcc0f8 Gerd Hoffmann
    trace_usb_uhci_frame_start(s->frnum);
1133 54f254f9 aliguori
1134 54f254f9 aliguori
    uhci_async_validate_begin(s);
1135 54f254f9 aliguori
1136 54f254f9 aliguori
    uhci_process_frame(s);
1137 54f254f9 aliguori
1138 54f254f9 aliguori
    uhci_async_validate_end(s);
1139 b9dc033c balrog
1140 8e65b7c0 David S. Ahern
    qemu_mod_timer(s->frame_timer, s->expire_time);
1141 bb36d470 bellard
}
1142 bb36d470 bellard
1143 a03f66e4 Avi Kivity
static const MemoryRegionPortio uhci_portio[] = {
1144 a03f66e4 Avi Kivity
    { 0, 32, 2, .write = uhci_ioport_writew, },
1145 a03f66e4 Avi Kivity
    { 0, 32, 2, .read = uhci_ioport_readw, },
1146 a03f66e4 Avi Kivity
    { 0, 32, 4, .write = uhci_ioport_writel, },
1147 a03f66e4 Avi Kivity
    { 0, 32, 4, .read = uhci_ioport_readl, },
1148 a03f66e4 Avi Kivity
    { 0, 32, 1, .write = uhci_ioport_writeb, },
1149 a03f66e4 Avi Kivity
    { 0, 32, 1, .read = uhci_ioport_readb, },
1150 a03f66e4 Avi Kivity
    PORTIO_END_OF_LIST()
1151 a03f66e4 Avi Kivity
};
1152 a03f66e4 Avi Kivity
1153 a03f66e4 Avi Kivity
static const MemoryRegionOps uhci_ioport_ops = {
1154 a03f66e4 Avi Kivity
    .old_portio = uhci_portio,
1155 a03f66e4 Avi Kivity
};
1156 bb36d470 bellard
1157 0d86d2be Gerd Hoffmann
static USBPortOps uhci_port_ops = {
1158 0d86d2be Gerd Hoffmann
    .attach = uhci_attach,
1159 618c169b Gerd Hoffmann
    .detach = uhci_detach,
1160 4706ab6c Hans de Goede
    .child_detach = uhci_child_detach,
1161 9159f679 Gerd Hoffmann
    .wakeup = uhci_wakeup,
1162 13a9a0d3 Gerd Hoffmann
    .complete = uhci_async_complete,
1163 0d86d2be Gerd Hoffmann
};
1164 0d86d2be Gerd Hoffmann
1165 07771f6f Gerd Hoffmann
static USBBusOps uhci_bus_ops = {
1166 07771f6f Gerd Hoffmann
};
1167 07771f6f Gerd Hoffmann
1168 dc638fad Isaku Yamahata
static int usb_uhci_common_initfn(PCIDevice *dev)
1169 bb36d470 bellard
{
1170 dc638fad Isaku Yamahata
    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
1171 6cf9b6f1 Gerd Hoffmann
    uint8_t *pci_conf = s->dev.config;
1172 bb36d470 bellard
    int i;
1173 bb36d470 bellard
1174 db579e9e Michael S. Tsirkin
    pci_conf[PCI_CLASS_PROG] = 0x00;
1175 db579e9e Michael S. Tsirkin
    /* TODO: reset value should be 0. */
1176 817e0b6f Michael S. Tsirkin
    pci_conf[PCI_INTERRUPT_PIN] = 4; /* interrupt pin D */
1177 e59d33a7 Brad Hards
    pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
1178 3b46e624 ths
1179 35e4977f Hans de Goede
    if (s->masterbus) {
1180 35e4977f Hans de Goede
        USBPort *ports[NB_PORTS];
1181 35e4977f Hans de Goede
        for(i = 0; i < NB_PORTS; i++) {
1182 35e4977f Hans de Goede
            ports[i] = &s->ports[i].port;
1183 35e4977f Hans de Goede
        }
1184 35e4977f Hans de Goede
        if (usb_register_companion(s->masterbus, ports, NB_PORTS,
1185 35e4977f Hans de Goede
                s->firstport, s, &uhci_port_ops,
1186 35e4977f Hans de Goede
                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
1187 35e4977f Hans de Goede
            return -1;
1188 35e4977f Hans de Goede
        }
1189 35e4977f Hans de Goede
    } else {
1190 35e4977f Hans de Goede
        usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
1191 35e4977f Hans de Goede
        for (i = 0; i < NB_PORTS; i++) {
1192 35e4977f Hans de Goede
            usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
1193 35e4977f Hans de Goede
                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1194 35e4977f Hans de Goede
        }
1195 bb36d470 bellard
    }
1196 74475455 Paolo Bonzini
    s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
1197 64e58fe5 Juan Quintela
    s->num_ports_vmstate = NB_PORTS;
1198 f8af1e88 Gerd Hoffmann
    QTAILQ_INIT(&s->queues);
1199 bb36d470 bellard
1200 a08d4367 Jan Kiszka
    qemu_register_reset(uhci_reset, s);
1201 bb36d470 bellard
1202 a03f66e4 Avi Kivity
    memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20);
1203 38ca0f6d pbrook
    /* Use region 4 for consistency with real hardware.  BSD guests seem
1204 38ca0f6d pbrook
       to rely on this.  */
1205 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
1206 6f382b5e aliguori
1207 6cf9b6f1 Gerd Hoffmann
    return 0;
1208 bb36d470 bellard
}
1209 afcc3cdf ths
1210 30235a54 Huacai Chen
static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
1211 30235a54 Huacai Chen
{
1212 30235a54 Huacai Chen
    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
1213 30235a54 Huacai Chen
    uint8_t *pci_conf = s->dev.config;
1214 30235a54 Huacai Chen
1215 30235a54 Huacai Chen
    /* USB misc control 1/2 */
1216 30235a54 Huacai Chen
    pci_set_long(pci_conf + 0x40,0x00001000);
1217 30235a54 Huacai Chen
    /* PM capability */
1218 30235a54 Huacai Chen
    pci_set_long(pci_conf + 0x80,0x00020001);
1219 30235a54 Huacai Chen
    /* USB legacy support  */
1220 30235a54 Huacai Chen
    pci_set_long(pci_conf + 0xc0,0x00002000);
1221 30235a54 Huacai Chen
1222 dc638fad Isaku Yamahata
    return usb_uhci_common_initfn(dev);
1223 30235a54 Huacai Chen
}
1224 30235a54 Huacai Chen
1225 a03f66e4 Avi Kivity
static int usb_uhci_exit(PCIDevice *dev)
1226 a03f66e4 Avi Kivity
{
1227 a03f66e4 Avi Kivity
    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
1228 a03f66e4 Avi Kivity
1229 a03f66e4 Avi Kivity
    memory_region_destroy(&s->io_bar);
1230 a03f66e4 Avi Kivity
    return 0;
1231 a03f66e4 Avi Kivity
}
1232 a03f66e4 Avi Kivity
1233 1b5a7570 Gerd Hoffmann
static Property uhci_properties[] = {
1234 1b5a7570 Gerd Hoffmann
    DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
1235 1b5a7570 Gerd Hoffmann
    DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
1236 1b5a7570 Gerd Hoffmann
    DEFINE_PROP_END_OF_LIST(),
1237 1b5a7570 Gerd Hoffmann
};
1238 1b5a7570 Gerd Hoffmann
1239 40021f08 Anthony Liguori
static void piix3_uhci_class_init(ObjectClass *klass, void *data)
1240 40021f08 Anthony Liguori
{
1241 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1242 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1243 40021f08 Anthony Liguori
1244 40021f08 Anthony Liguori
    k->init = usb_uhci_common_initfn;
1245 40021f08 Anthony Liguori
    k->exit = usb_uhci_exit;
1246 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1247 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_INTEL_82371SB_2;
1248 40021f08 Anthony Liguori
    k->revision = 0x01;
1249 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1250 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1251 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1252 40021f08 Anthony Liguori
}
1253 40021f08 Anthony Liguori
1254 39bffca2 Anthony Liguori
static TypeInfo piix3_uhci_info = {
1255 39bffca2 Anthony Liguori
    .name          = "piix3-usb-uhci",
1256 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1257 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1258 39bffca2 Anthony Liguori
    .class_init    = piix3_uhci_class_init,
1259 e855761c Anthony Liguori
};
1260 e855761c Anthony Liguori
1261 40021f08 Anthony Liguori
static void piix4_uhci_class_init(ObjectClass *klass, void *data)
1262 40021f08 Anthony Liguori
{
1263 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1264 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1265 40021f08 Anthony Liguori
1266 40021f08 Anthony Liguori
    k->init = usb_uhci_common_initfn;
1267 40021f08 Anthony Liguori
    k->exit = usb_uhci_exit;
1268 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1269 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_INTEL_82371AB_2;
1270 40021f08 Anthony Liguori
    k->revision = 0x01;
1271 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1272 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1273 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1274 40021f08 Anthony Liguori
}
1275 40021f08 Anthony Liguori
1276 39bffca2 Anthony Liguori
static TypeInfo piix4_uhci_info = {
1277 39bffca2 Anthony Liguori
    .name          = "piix4-usb-uhci",
1278 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1279 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1280 39bffca2 Anthony Liguori
    .class_init    = piix4_uhci_class_init,
1281 e855761c Anthony Liguori
};
1282 e855761c Anthony Liguori
1283 40021f08 Anthony Liguori
static void vt82c686b_uhci_class_init(ObjectClass *klass, void *data)
1284 40021f08 Anthony Liguori
{
1285 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1286 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1287 40021f08 Anthony Liguori
1288 40021f08 Anthony Liguori
    k->init = usb_uhci_vt82c686b_initfn;
1289 40021f08 Anthony Liguori
    k->exit = usb_uhci_exit;
1290 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_VIA;
1291 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIA_UHCI;
1292 40021f08 Anthony Liguori
    k->revision = 0x01;
1293 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1294 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1295 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1296 40021f08 Anthony Liguori
}
1297 40021f08 Anthony Liguori
1298 39bffca2 Anthony Liguori
static TypeInfo vt82c686b_uhci_info = {
1299 39bffca2 Anthony Liguori
    .name          = "vt82c686b-usb-uhci",
1300 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1301 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1302 39bffca2 Anthony Liguori
    .class_init    = vt82c686b_uhci_class_init,
1303 e855761c Anthony Liguori
};
1304 e855761c Anthony Liguori
1305 40021f08 Anthony Liguori
static void ich9_uhci1_class_init(ObjectClass *klass, void *data)
1306 40021f08 Anthony Liguori
{
1307 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1308 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1309 40021f08 Anthony Liguori
1310 40021f08 Anthony Liguori
    k->init = usb_uhci_common_initfn;
1311 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1312 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1;
1313 40021f08 Anthony Liguori
    k->revision = 0x03;
1314 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1315 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1316 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1317 40021f08 Anthony Liguori
}
1318 40021f08 Anthony Liguori
1319 39bffca2 Anthony Liguori
static TypeInfo ich9_uhci1_info = {
1320 39bffca2 Anthony Liguori
    .name          = "ich9-usb-uhci1",
1321 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1322 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1323 39bffca2 Anthony Liguori
    .class_init    = ich9_uhci1_class_init,
1324 e855761c Anthony Liguori
};
1325 e855761c Anthony Liguori
1326 40021f08 Anthony Liguori
static void ich9_uhci2_class_init(ObjectClass *klass, void *data)
1327 40021f08 Anthony Liguori
{
1328 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1329 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1330 40021f08 Anthony Liguori
1331 40021f08 Anthony Liguori
    k->init = usb_uhci_common_initfn;
1332 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1333 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2;
1334 40021f08 Anthony Liguori
    k->revision = 0x03;
1335 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1336 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1337 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1338 40021f08 Anthony Liguori
}
1339 40021f08 Anthony Liguori
1340 39bffca2 Anthony Liguori
static TypeInfo ich9_uhci2_info = {
1341 39bffca2 Anthony Liguori
    .name          = "ich9-usb-uhci2",
1342 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1343 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1344 39bffca2 Anthony Liguori
    .class_init    = ich9_uhci2_class_init,
1345 e855761c Anthony Liguori
};
1346 e855761c Anthony Liguori
1347 40021f08 Anthony Liguori
static void ich9_uhci3_class_init(ObjectClass *klass, void *data)
1348 40021f08 Anthony Liguori
{
1349 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1350 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1351 40021f08 Anthony Liguori
1352 40021f08 Anthony Liguori
    k->init = usb_uhci_common_initfn;
1353 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
1354 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3;
1355 40021f08 Anthony Liguori
    k->revision = 0x03;
1356 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_SERIAL_USB;
1357 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_uhci;
1358 39bffca2 Anthony Liguori
    dc->props = uhci_properties;
1359 40021f08 Anthony Liguori
}
1360 40021f08 Anthony Liguori
1361 39bffca2 Anthony Liguori
static TypeInfo ich9_uhci3_info = {
1362 39bffca2 Anthony Liguori
    .name          = "ich9-usb-uhci3",
1363 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1364 39bffca2 Anthony Liguori
    .instance_size = sizeof(UHCIState),
1365 39bffca2 Anthony Liguori
    .class_init    = ich9_uhci3_class_init,
1366 6cf9b6f1 Gerd Hoffmann
};
1367 afcc3cdf ths
1368 83f7d43a Andreas Färber
static void uhci_register_types(void)
1369 6cf9b6f1 Gerd Hoffmann
{
1370 39bffca2 Anthony Liguori
    type_register_static(&piix3_uhci_info);
1371 39bffca2 Anthony Liguori
    type_register_static(&piix4_uhci_info);
1372 39bffca2 Anthony Liguori
    type_register_static(&vt82c686b_uhci_info);
1373 39bffca2 Anthony Liguori
    type_register_static(&ich9_uhci1_info);
1374 39bffca2 Anthony Liguori
    type_register_static(&ich9_uhci2_info);
1375 39bffca2 Anthony Liguori
    type_register_static(&ich9_uhci3_info);
1376 6cf9b6f1 Gerd Hoffmann
}
1377 83f7d43a Andreas Färber
1378 83f7d43a Andreas Färber
type_init(uhci_register_types)