hcd-ehci.c 72.2 KB
Newer Older
G
Gerd Hoffmann 已提交
1 2 3 4
/*
 * QEMU USB EHCI Emulation
 *
 * Copyright(c) 2008  Emutex Ltd. (address@hidden)
5 6 7 8 9
 * Copyright(c) 2011-2012 Red Hat, Inc.
 *
 * Red Hat Authors:
 * Gerd Hoffmann <kraxel@redhat.com>
 * Hans de Goede <hdegoede@redhat.com>
G
Gerd Hoffmann 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * EHCI project was started by Mark Burkley, with contributions by
 * Niels de Vos.  David S. Ahern continued working on it.  Kevin Wolf,
 * Jan Kiszka and Vincent Palatin contributed bugfixes.
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or(at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

P
Peter Maydell 已提交
30
#include "qemu/osdep.h"
31
#include "qapi/error.h"
32
#include "hw/usb/ehci-regs.h"
33
#include "hw/usb/hcd-ehci.h"
34
#include "trace.h"
G
Gerd Hoffmann 已提交
35 36

#define FRAME_TIMER_FREQ 1000
37
#define FRAME_TIMER_NS   (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ)
38
#define UFRAME_TIMER_NS  (FRAME_TIMER_NS / 8)
G
Gerd Hoffmann 已提交
39 40 41 42

#define NB_MAXINTRATE    8        // Max rate at which controller issues ints
#define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
#define MAX_QH           100      // Max allowable queue heads in a chain
43 44
#define MIN_UFR_PER_TICK 24       /* Min frames to process when catching up */
#define PERIODIC_ACTIVE  512      /* Micro-frames */
G
Gerd Hoffmann 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58

/*  Internal periodic / asynchronous schedule state machine states
 */
typedef enum {
    EST_INACTIVE = 1000,
    EST_ACTIVE,
    EST_EXECUTING,
    EST_SLEEPING,
    /*  The following states are internal to the state machine function
    */
    EST_WAITLISTHEAD,
    EST_FETCHENTRY,
    EST_FETCHQH,
    EST_FETCHITD,
G
Gerd Hoffmann 已提交
59
    EST_FETCHSITD,
G
Gerd Hoffmann 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    EST_ADVANCEQUEUE,
    EST_FETCHQTD,
    EST_EXECUTE,
    EST_WRITEBACK,
    EST_HORIZONTALQH
} EHCI_STATES;

/* macros for accessing fields within next link pointer entry */
#define NLPTR_GET(x)             ((x) & 0xffffffe0)
#define NLPTR_TYPE_GET(x)        (((x) >> 1) & 3)
#define NLPTR_TBIT(x)            ((x) & 1)  // 1=invalid, 0=valid

/* link pointer types */
#define NLPTR_TYPE_ITD           0     // isoc xfer descriptor
#define NLPTR_TYPE_QH            1     // queue head
#define NLPTR_TYPE_STITD         2     // split xaction, isoc xfer descriptor
#define NLPTR_TYPE_FSTN          3     // frame span traversal node

#define SET_LAST_RUN_CLOCK(s) \
79
    (s)->last_run_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
G
Gerd Hoffmann 已提交
80 81 82 83 84 85 86 87 88 89 90 91

/* nifty macros from Arnon's EHCI version  */
#define get_field(data, field) \
    (((data) & field##_MASK) >> field##_SH)

#define set_field(data, newval, field) do { \
    uint32_t val = *data; \
    val &= ~ field##_MASK; \
    val |= ((newval) << field##_SH) & field##_MASK; \
    *data = val; \
    } while(0)

92
static const char *ehci_state_names[] = {
G
Gerd Hoffmann 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105
    [EST_INACTIVE]     = "INACTIVE",
    [EST_ACTIVE]       = "ACTIVE",
    [EST_EXECUTING]    = "EXECUTING",
    [EST_SLEEPING]     = "SLEEPING",
    [EST_WAITLISTHEAD] = "WAITLISTHEAD",
    [EST_FETCHENTRY]   = "FETCH ENTRY",
    [EST_FETCHQH]      = "FETCH QH",
    [EST_FETCHITD]     = "FETCH ITD",
    [EST_ADVANCEQUEUE] = "ADVANCEQUEUE",
    [EST_FETCHQTD]     = "FETCH QTD",
    [EST_EXECUTE]      = "EXECUTE",
    [EST_WRITEBACK]    = "WRITEBACK",
    [EST_HORIZONTALQH] = "HORIZONTALQH",
106 107 108
};

static const char *ehci_mmio_names[] = {
G
Gerd Hoffmann 已提交
109 110 111 112 113 114 115
    [USBCMD]            = "USBCMD",
    [USBSTS]            = "USBSTS",
    [USBINTR]           = "USBINTR",
    [FRINDEX]           = "FRINDEX",
    [PERIODICLISTBASE]  = "P-LIST BASE",
    [ASYNCLISTADDR]     = "A-LIST ADDR",
    [CONFIGFLAG]        = "CONFIGFLAG",
116
};
G
Gerd Hoffmann 已提交
117

118 119
static int ehci_state_executing(EHCIQueue *q);
static int ehci_state_writeback(EHCIQueue *q);
120
static int ehci_state_advqueue(EHCIQueue *q);
121
static int ehci_fill_queue(EHCIPacket *p);
122
static void ehci_free_packet(EHCIPacket *p);
123

124
static const char *nr2str(const char **n, size_t len, uint32_t nr)
G
Gerd Hoffmann 已提交
125
{
126 127
    if (nr < len && n[nr] != NULL) {
        return n[nr];
G
Gerd Hoffmann 已提交
128
    } else {
129
        return "unknown";
G
Gerd Hoffmann 已提交
130 131 132
    }
}

133 134 135 136 137
static const char *state2str(uint32_t state)
{
    return nr2str(ehci_state_names, ARRAY_SIZE(ehci_state_names), state);
}

A
Avi Kivity 已提交
138
static const char *addr2str(hwaddr addr)
139
{
140
    return nr2str(ehci_mmio_names, ARRAY_SIZE(ehci_mmio_names), addr);
141 142
}

G
Gerd Hoffmann 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
static void ehci_trace_usbsts(uint32_t mask, int state)
{
    /* interrupts */
    if (mask & USBSTS_INT) {
        trace_usb_ehci_usbsts("INT", state);
    }
    if (mask & USBSTS_ERRINT) {
        trace_usb_ehci_usbsts("ERRINT", state);
    }
    if (mask & USBSTS_PCD) {
        trace_usb_ehci_usbsts("PCD", state);
    }
    if (mask & USBSTS_FLR) {
        trace_usb_ehci_usbsts("FLR", state);
    }
    if (mask & USBSTS_HSE) {
        trace_usb_ehci_usbsts("HSE", state);
    }
    if (mask & USBSTS_IAA) {
        trace_usb_ehci_usbsts("IAA", state);
    }

    /* status */
    if (mask & USBSTS_HALT) {
        trace_usb_ehci_usbsts("HALT", state);
    }
    if (mask & USBSTS_REC) {
        trace_usb_ehci_usbsts("REC", state);
    }
    if (mask & USBSTS_PSS) {
        trace_usb_ehci_usbsts("PSS", state);
    }
    if (mask & USBSTS_ASS) {
        trace_usb_ehci_usbsts("ASS", state);
    }
}

static inline void ehci_set_usbsts(EHCIState *s, int mask)
{
    if ((s->usbsts & mask) == mask) {
        return;
    }
    ehci_trace_usbsts(mask, 1);
    s->usbsts |= mask;
}

static inline void ehci_clear_usbsts(EHCIState *s, int mask)
{
    if ((s->usbsts & mask) == 0) {
        return;
    }
    ehci_trace_usbsts(mask, 0);
    s->usbsts &= ~mask;
}
G
Gerd Hoffmann 已提交
197

198 199
/* update irq line */
static inline void ehci_update_irq(EHCIState *s)
G
Gerd Hoffmann 已提交
200 201 202 203 204 205 206
{
    int level = 0;

    if ((s->usbsts & USBINTR_MASK) & s->usbintr) {
        level = 1;
    }

207
    trace_usb_ehci_irq(level, s->frindex, s->usbsts, s->usbintr);
G
Gerd Hoffmann 已提交
208 209 210
    qemu_set_irq(s->irq, level);
}

211 212
/* flag interrupt condition */
static inline void ehci_raise_irq(EHCIState *s, int intr)
G
Gerd Hoffmann 已提交
213
{
214 215 216 217 218 219
    if (intr & (USBSTS_PCD | USBSTS_FLR | USBSTS_HSE)) {
        s->usbsts |= intr;
        ehci_update_irq(s);
    } else {
        s->usbsts_pending |= intr;
    }
G
Gerd Hoffmann 已提交
220 221
}

222 223 224 225 226
/*
 * Commit pending interrupts (added via ehci_raise_irq),
 * at the rate allowed by "Interrupt Threshold Control".
 */
static inline void ehci_commit_irq(EHCIState *s)
G
Gerd Hoffmann 已提交
227
{
228 229
    uint32_t itc;

G
Gerd Hoffmann 已提交
230 231 232
    if (!s->usbsts_pending) {
        return;
    }
233 234 235 236 237 238
    if (s->usbsts_frindex > s->frindex) {
        return;
    }

    itc = (s->usbcmd >> 16) & 0xff;
    s->usbsts |= s->usbsts_pending;
G
Gerd Hoffmann 已提交
239
    s->usbsts_pending = 0;
240 241
    s->usbsts_frindex = s->frindex + itc;
    ehci_update_irq(s);
G
Gerd Hoffmann 已提交
242 243
}

G
Gerd Hoffmann 已提交
244 245 246 247 248 249 250 251 252 253 254
static void ehci_update_halt(EHCIState *s)
{
    if (s->usbcmd & USBCMD_RUNSTOP) {
        ehci_clear_usbsts(s, USBSTS_HALT);
    } else {
        if (s->astate == EST_INACTIVE && s->pstate == EST_INACTIVE) {
            ehci_set_usbsts(s, USBSTS_HALT);
        }
    }
}

255 256 257 258 259
static void ehci_set_state(EHCIState *s, int async, int state)
{
    if (async) {
        trace_usb_ehci_state("async", state2str(state));
        s->astate = state;
260 261
        if (s->astate == EST_INACTIVE) {
            ehci_clear_usbsts(s, USBSTS_ASS);
G
Gerd Hoffmann 已提交
262
            ehci_update_halt(s);
263 264 265
        } else {
            ehci_set_usbsts(s, USBSTS_ASS);
        }
266 267 268
    } else {
        trace_usb_ehci_state("periodic", state2str(state));
        s->pstate = state;
269 270
        if (s->pstate == EST_INACTIVE) {
            ehci_clear_usbsts(s, USBSTS_PSS);
G
Gerd Hoffmann 已提交
271
            ehci_update_halt(s);
272 273 274
        } else {
            ehci_set_usbsts(s, USBSTS_PSS);
        }
275 276 277 278 279 280 281 282
    }
}

static int ehci_get_state(EHCIState *s, int async)
{
    return async ? s->astate : s->pstate;
}

G
Gerd Hoffmann 已提交
283 284 285 286 287 288 289 290 291 292 293 294 295 296
static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr)
{
    if (async) {
        s->a_fetch_addr = addr;
    } else {
        s->p_fetch_addr = addr;
    }
}

static int ehci_get_fetch_addr(EHCIState *s, int async)
{
    return async ? s->a_fetch_addr : s->p_fetch_addr;
}

A
Avi Kivity 已提交
297
static void ehci_trace_qh(EHCIQueue *q, hwaddr addr, EHCIqh *qh)
298
{
299 300 301 302 303 304 305 306 307 308 309 310 311 312
    /* need three here due to argument count limits */
    trace_usb_ehci_qh_ptrs(q, addr, qh->next,
                           qh->current_qtd, qh->next_qtd, qh->altnext_qtd);
    trace_usb_ehci_qh_fields(addr,
                             get_field(qh->epchar, QH_EPCHAR_RL),
                             get_field(qh->epchar, QH_EPCHAR_MPLEN),
                             get_field(qh->epchar, QH_EPCHAR_EPS),
                             get_field(qh->epchar, QH_EPCHAR_EP),
                             get_field(qh->epchar, QH_EPCHAR_DEVADDR));
    trace_usb_ehci_qh_bits(addr,
                           (bool)(qh->epchar & QH_EPCHAR_C),
                           (bool)(qh->epchar & QH_EPCHAR_H),
                           (bool)(qh->epchar & QH_EPCHAR_DTC),
                           (bool)(qh->epchar & QH_EPCHAR_I));
313 314
}

A
Avi Kivity 已提交
315
static void ehci_trace_qtd(EHCIQueue *q, hwaddr addr, EHCIqtd *qtd)
316
{
317 318 319 320 321 322 323 324 325 326 327 328 329
    /* need three here due to argument count limits */
    trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext);
    trace_usb_ehci_qtd_fields(addr,
                              get_field(qtd->token, QTD_TOKEN_TBYTES),
                              get_field(qtd->token, QTD_TOKEN_CPAGE),
                              get_field(qtd->token, QTD_TOKEN_CERR),
                              get_field(qtd->token, QTD_TOKEN_PID));
    trace_usb_ehci_qtd_bits(addr,
                            (bool)(qtd->token & QTD_TOKEN_IOC),
                            (bool)(qtd->token & QTD_TOKEN_ACTIVE),
                            (bool)(qtd->token & QTD_TOKEN_HALT),
                            (bool)(qtd->token & QTD_TOKEN_BABBLE),
                            (bool)(qtd->token & QTD_TOKEN_XACTERR));
330 331
}

A
Avi Kivity 已提交
332
static void ehci_trace_itd(EHCIState *s, hwaddr addr, EHCIitd *itd)
333
{
G
Gerd Hoffmann 已提交
334 335 336 337 338
    trace_usb_ehci_itd(addr, itd->next,
                       get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT),
                       get_field(itd->bufptr[2], ITD_BUFPTR_MULT),
                       get_field(itd->bufptr[0], ITD_BUFPTR_EP),
                       get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
339 340
}

A
Avi Kivity 已提交
341
static void ehci_trace_sitd(EHCIState *s, hwaddr addr,
G
Gerd Hoffmann 已提交
342 343 344 345 346 347
                            EHCIsitd *sitd)
{
    trace_usb_ehci_sitd(addr, sitd->next,
                        (bool)(sitd->results & SITD_RESULTS_ACTIVE));
}

G
Gerd Hoffmann 已提交
348 349 350 351 352 353
static void ehci_trace_guest_bug(EHCIState *s, const char *message)
{
    trace_usb_ehci_guest_bug(message);
    fprintf(stderr, "ehci warning: %s\n", message);
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
static inline bool ehci_enabled(EHCIState *s)
{
    return s->usbcmd & USBCMD_RUNSTOP;
}

static inline bool ehci_async_enabled(EHCIState *s)
{
    return ehci_enabled(s) && (s->usbcmd & USBCMD_ASE);
}

static inline bool ehci_periodic_enabled(EHCIState *s)
{
    return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
}

369 370 371 372 373 374
/* Get an array of dwords from main memory */
static inline int get_dwords(EHCIState *ehci, uint32_t addr,
                             uint32_t *buf, int num)
{
    int i;

P
Paolo Bonzini 已提交
375
    if (!ehci->as) {
376 377 378 379 380 381 382
        ehci_raise_irq(ehci, USBSTS_HSE);
        ehci->usbcmd &= ~USBCMD_RUNSTOP;
        trace_usb_ehci_dma_error();
        return -1;
    }

    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
P
Paolo Bonzini 已提交
383
        dma_memory_read(ehci->as, addr, buf, sizeof(*buf));
384 385 386 387 388 389 390 391 392 393 394 395
        *buf = le32_to_cpu(*buf);
    }

    return num;
}

/* Put an array of dwords in to main memory */
static inline int put_dwords(EHCIState *ehci, uint32_t addr,
                             uint32_t *buf, int num)
{
    int i;

P
Paolo Bonzini 已提交
396
    if (!ehci->as) {
397 398 399 400 401 402 403 404
        ehci_raise_irq(ehci, USBSTS_HSE);
        ehci->usbcmd &= ~USBCMD_RUNSTOP;
        trace_usb_ehci_dma_error();
        return -1;
    }

    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
        uint32_t tmp = cpu_to_le32(*buf);
P
Paolo Bonzini 已提交
405
        dma_memory_write(ehci->as, addr, &tmp, sizeof(tmp));
406 407 408 409 410
    }

    return num;
}

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
static int ehci_get_pid(EHCIqtd *qtd)
{
    switch (get_field(qtd->token, QTD_TOKEN_PID)) {
    case 0:
        return USB_TOKEN_OUT;
    case 1:
        return USB_TOKEN_IN;
    case 2:
        return USB_TOKEN_SETUP;
    default:
        fprintf(stderr, "bad token\n");
        return 0;
    }
}

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh)
{
    uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR);
    uint32_t endp    = get_field(qh->epchar, QH_EPCHAR_EP);
    if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
        (endp    != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
        (qh->current_qtd != q->qh.current_qtd) ||
        (q->async && qh->next_qtd != q->qh.next_qtd) ||
        (memcmp(&qh->altnext_qtd, &q->qh.altnext_qtd,
                                 7 * sizeof(uint32_t)) != 0) ||
        (q->dev != NULL && q->dev->addr != devaddr)) {
        return false;
    } else {
        return true;
    }
}

static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd)
{
    if (p->qtdaddr != p->queue->qtdaddr ||
        (p->queue->async && !NLPTR_TBIT(p->qtd.next) &&
            (p->qtd.next != qtd->next)) ||
        (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) ||
449
        p->qtd.token != qtd->token ||
450 451 452 453 454 455 456
        p->qtd.bufptr[0] != qtd->bufptr[0]) {
        return false;
    } else {
        return true;
    }
}

457 458 459 460 461 462 463 464 465 466 467 468 469
static bool ehci_verify_pid(EHCIQueue *q, EHCIqtd *qtd)
{
    int ep  = get_field(q->qh.epchar, QH_EPCHAR_EP);
    int pid = ehci_get_pid(qtd);

    /* Note the pid changing is normal for ep 0 (the control ep) */
    if (q->last_pid && ep != 0 && pid != q->last_pid) {
        return false;
    } else {
        return true;
    }
}

470 471 472 473 474
/* Finish executing and writeback a packet outside of the regular
   fetchqh -> fetchqtd -> execute -> writeback cycle */
static void ehci_writeback_async_complete_packet(EHCIPacket *p)
{
    EHCIQueue *q = p->queue;
475 476
    EHCIqtd qtd;
    EHCIqh qh;
477 478
    int state;

479 480 481 482 483 484 485 486 487 488 489
    /* Verify the qh + qtd, like we do when going through fetchqh & fetchqtd */
    get_dwords(q->ehci, NLPTR_GET(q->qhaddr),
               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr),
               (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
    if (!ehci_verify_qh(q, &qh) || !ehci_verify_qtd(p, &qtd)) {
        p->async = EHCI_ASYNC_INITIALIZED;
        ehci_free_packet(p);
        return;
    }

490 491 492 493 494 495 496 497 498
    state = ehci_get_state(q->ehci, q->async);
    ehci_state_executing(q);
    ehci_state_writeback(q); /* Frees the packet! */
    if (!(q->qh.token & QTD_TOKEN_HALT)) {
        ehci_state_advqueue(q);
    }
    ehci_set_state(q->ehci, q->async, state);
}

G
Gerd Hoffmann 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/* packet management */

static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
{
    EHCIPacket *p;

    p = g_new0(EHCIPacket, 1);
    p->queue = q;
    usb_packet_init(&p->packet);
    QTAILQ_INSERT_TAIL(&q->packets, p, next);
    trace_usb_ehci_packet_action(p->queue, p, "alloc");
    return p;
}

static void ehci_free_packet(EHCIPacket *p)
{
515 516
    if (p->async == EHCI_ASYNC_FINISHED &&
            !(p->queue->qh.token & QTD_TOKEN_HALT)) {
517
        ehci_writeback_async_complete_packet(p);
518 519
        return;
    }
520 521 522
    trace_usb_ehci_packet_action(p->queue, p, "free");
    if (p->async == EHCI_ASYNC_INFLIGHT) {
        usb_cancel_packet(&p->packet);
523 524 525 526 527 528 529 530 531
    }
    if (p->async == EHCI_ASYNC_FINISHED &&
            p->packet.status == USB_RET_SUCCESS) {
        fprintf(stderr,
                "EHCI: Dropping completed packet from halted %s ep %02X\n",
                (p->pid == USB_TOKEN_IN) ? "in" : "out",
                get_field(p->queue->qh.epchar, QH_EPCHAR_EP));
    }
    if (p->async != EHCI_ASYNC_NONE) {
532 533 534
        usb_packet_unmap(&p->packet, &p->sgl);
        qemu_sglist_destroy(&p->sgl);
    }
G
Gerd Hoffmann 已提交
535 536 537 538 539
    QTAILQ_REMOVE(&p->queue->packets, p, next);
    usb_packet_cleanup(&p->packet);
    g_free(p);
}

G
Gerd Hoffmann 已提交
540 541
/* queue management */

G
Gerd Hoffmann 已提交
542
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
G
Gerd Hoffmann 已提交
543
{
544
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
G
Gerd Hoffmann 已提交
545 546
    EHCIQueue *q;

547
    q = g_malloc0(sizeof(*q));
G
Gerd Hoffmann 已提交
548
    q->ehci = ehci;
G
Gerd Hoffmann 已提交
549
    q->qhaddr = addr;
550
    q->async = async;
G
Gerd Hoffmann 已提交
551
    QTAILQ_INIT(&q->packets);
552
    QTAILQ_INSERT_HEAD(head, q, next);
G
Gerd Hoffmann 已提交
553 554 555 556
    trace_usb_ehci_queue_action(q, "alloc");
    return q;
}

557 558 559 560 561 562 563 564 565 566 567
static void ehci_queue_stopped(EHCIQueue *q)
{
    int endp  = get_field(q->qh.epchar, QH_EPCHAR_EP);

    if (!q->last_pid || !q->dev) {
        return;
    }

    usb_device_ep_stopped(q->dev, usb_ep_get(q->dev, q->last_pid, endp));
}

G
Gerd Hoffmann 已提交
568
static int ehci_cancel_queue(EHCIQueue *q)
G
Gerd Hoffmann 已提交
569 570
{
    EHCIPacket *p;
G
Gerd Hoffmann 已提交
571
    int packets = 0;
G
Gerd Hoffmann 已提交
572 573 574

    p = QTAILQ_FIRST(&q->packets);
    if (p == NULL) {
575
        goto leave;
G
Gerd Hoffmann 已提交
576 577 578 579 580
    }

    trace_usb_ehci_queue_action(q, "cancel");
    do {
        ehci_free_packet(p);
G
Gerd Hoffmann 已提交
581
        packets++;
G
Gerd Hoffmann 已提交
582
    } while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
583 584 585

leave:
    ehci_queue_stopped(q);
G
Gerd Hoffmann 已提交
586
    return packets;
G
Gerd Hoffmann 已提交
587 588
}

G
Gerd Hoffmann 已提交
589
static int ehci_reset_queue(EHCIQueue *q)
590
{
G
Gerd Hoffmann 已提交
591 592
    int packets;

593
    trace_usb_ehci_queue_action(q, "reset");
G
Gerd Hoffmann 已提交
594
    packets = ehci_cancel_queue(q);
595 596
    q->dev = NULL;
    q->qtdaddr = 0;
597
    q->last_pid = 0;
G
Gerd Hoffmann 已提交
598
    return packets;
599 600
}

601
static void ehci_free_queue(EHCIQueue *q, const char *warn)
G
Gerd Hoffmann 已提交
602
{
603
    EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
604
    int cancelled;
G
Gerd Hoffmann 已提交
605

G
Gerd Hoffmann 已提交
606
    trace_usb_ehci_queue_action(q, "free");
607 608 609 610
    cancelled = ehci_cancel_queue(q);
    if (warn && cancelled > 0) {
        ehci_trace_guest_bug(q->ehci, warn);
    }
611
    QTAILQ_REMOVE(head, q, next);
612
    g_free(q);
G
Gerd Hoffmann 已提交
613 614
}

615 616
static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
                                        int async)
G
Gerd Hoffmann 已提交
617
{
618
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
G
Gerd Hoffmann 已提交
619 620
    EHCIQueue *q;

621
    QTAILQ_FOREACH(q, head, next) {
G
Gerd Hoffmann 已提交
622 623 624 625 626 627 628
        if (addr == q->qhaddr) {
            return q;
        }
    }
    return NULL;
}

629
static void ehci_queues_rip_unused(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
630
{
631
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
632
    const char *warn = async ? "guest unlinked busy QH" : NULL;
G
Gerd Hoffmann 已提交
633
    uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
G
Gerd Hoffmann 已提交
634 635
    EHCIQueue *q, *tmp;

636
    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
G
Gerd Hoffmann 已提交
637 638
        if (q->seen) {
            q->seen = 0;
G
Gerd Hoffmann 已提交
639
            q->ts = ehci->last_run_ns;
G
Gerd Hoffmann 已提交
640 641
            continue;
        }
642
        if (ehci->last_run_ns < q->ts + maxage) {
G
Gerd Hoffmann 已提交
643 644
            continue;
        }
645
        ehci_free_queue(q, warn);
G
Gerd Hoffmann 已提交
646 647 648
    }
}

649 650 651 652 653 654 655 656 657 658 659 660
static void ehci_queues_rip_unseen(EHCIState *ehci, int async)
{
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
    EHCIQueue *q, *tmp;

    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
        if (!q->seen) {
            ehci_free_queue(q, NULL);
        }
    }
}

661
static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
662
{
663
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
664 665
    EHCIQueue *q, *tmp;

666
    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
667
        if (q->dev != dev) {
668 669
            continue;
        }
670
        ehci_free_queue(q, NULL);
671 672 673
    }
}

674
static void ehci_queues_rip_all(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
675
{
676
    EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
677
    const char *warn = async ? "guest stopped busy async schedule" : NULL;
G
Gerd Hoffmann 已提交
678 679
    EHCIQueue *q, *tmp;

680
    QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
681
        ehci_free_queue(q, warn);
G
Gerd Hoffmann 已提交
682 683 684
    }
}

G
Gerd Hoffmann 已提交
685 686 687 688 689 690
/* Attach or detach a device on root hub */

static void ehci_attach(USBPort *port)
{
    EHCIState *s = port->opaque;
    uint32_t *portsc = &s->portsc[port->index];
G
Gerd Hoffmann 已提交
691
    const char *owner = (*portsc & PORTSC_POWNER) ? "comp" : "ehci";
G
Gerd Hoffmann 已提交
692

G
Gerd Hoffmann 已提交
693
    trace_usb_ehci_port_attach(port->index, owner, port->dev->product_desc);
G
Gerd Hoffmann 已提交
694

695 696 697 698 699 700 701
    if (*portsc & PORTSC_POWNER) {
        USBPort *companion = s->companion_ports[port->index];
        companion->dev = port->dev;
        companion->ops->attach(companion);
        return;
    }

G
Gerd Hoffmann 已提交
702 703 704
    *portsc |= PORTSC_CONNECT;
    *portsc |= PORTSC_CSC;

705
    ehci_raise_irq(s, USBSTS_PCD);
G
Gerd Hoffmann 已提交
706 707 708 709 710 711
}

static void ehci_detach(USBPort *port)
{
    EHCIState *s = port->opaque;
    uint32_t *portsc = &s->portsc[port->index];
G
Gerd Hoffmann 已提交
712
    const char *owner = (*portsc & PORTSC_POWNER) ? "comp" : "ehci";
G
Gerd Hoffmann 已提交
713

G
Gerd Hoffmann 已提交
714
    trace_usb_ehci_port_detach(port->index, owner);
G
Gerd Hoffmann 已提交
715

716 717 718 719
    if (*portsc & PORTSC_POWNER) {
        USBPort *companion = s->companion_ports[port->index];
        companion->ops->detach(companion);
        companion->dev = NULL;
720 721 722 723 724
        /*
         * EHCI spec 4.2.2: "When a disconnect occurs... On the event,
         * the port ownership is returned immediately to the EHCI controller."
         */
        *portsc &= ~PORTSC_POWNER;
725 726 727
        return;
    }

728 729
    ehci_queues_rip_device(s, port->dev, 0);
    ehci_queues_rip_device(s, port->dev, 1);
730

G
Gerd Hoffmann 已提交
731
    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED|PORTSC_SUSPEND);
G
Gerd Hoffmann 已提交
732 733
    *portsc |= PORTSC_CSC;

734
    ehci_raise_irq(s, USBSTS_PCD);
G
Gerd Hoffmann 已提交
735 736
}

737 738 739
static void ehci_child_detach(USBPort *port, USBDevice *child)
{
    EHCIState *s = port->opaque;
740 741 742 743 744 745 746
    uint32_t portsc = s->portsc[port->index];

    if (portsc & PORTSC_POWNER) {
        USBPort *companion = s->companion_ports[port->index];
        companion->ops->child_detach(companion, child);
        return;
    }
747

748 749
    ehci_queues_rip_device(s, child, 0);
    ehci_queues_rip_device(s, child, 1);
750 751
}

752 753 754
static void ehci_wakeup(USBPort *port)
{
    EHCIState *s = port->opaque;
G
Gerd Hoffmann 已提交
755
    uint32_t *portsc = &s->portsc[port->index];
756

G
Gerd Hoffmann 已提交
757
    if (*portsc & PORTSC_POWNER) {
758 759 760 761
        USBPort *companion = s->companion_ports[port->index];
        if (companion->ops->wakeup) {
            companion->ops->wakeup(companion);
        }
762
        return;
763
    }
764

G
Gerd Hoffmann 已提交
765 766 767 768 769 770
    if (*portsc & PORTSC_SUSPEND) {
        trace_usb_ehci_port_wakeup(port->index);
        *portsc |= PORTSC_FPRES;
        ehci_raise_irq(s, USBSTS_PCD);
    }

771
    qemu_bh_schedule(s->async_bh);
772 773
}

774 775 776
static void ehci_register_companion(USBBus *bus, USBPort *ports[],
                                    uint32_t portcount, uint32_t firstport,
                                    Error **errp)
777 778 779 780 781
{
    EHCIState *s = container_of(bus, EHCIState, bus);
    uint32_t i;

    if (firstport + portcount > NB_PORTS) {
782 783
        error_setg(errp, "firstport must be between 0 and %u",
                   NB_PORTS - portcount);
784
        return;
785 786 787 788
    }

    for (i = 0; i < portcount; i++) {
        if (s->companion_ports[firstport + i]) {
789 790 791 792
            error_setg(errp, "firstport %u asks for ports %u-%u,"
                       " but port %u has a companion assigned already",
                       firstport, firstport, firstport + portcount - 1,
                       firstport + i);
793
            return;
794 795 796 797 798 799 800 801 802 803 804 805
        }
    }

    for (i = 0; i < portcount; i++) {
        s->companion_ports[firstport + i] = ports[i];
        s->ports[firstport + i].speedmask |=
            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
        /* Ensure devs attached before the initial reset go to the companion */
        s->portsc[firstport + i] = PORTSC_POWNER;
    }

    s->companion_count++;
806
    s->caps[0x05] = (s->companion_count << 4) | portcount;
807 808
}

G
Gerd Hoffmann 已提交
809 810
static void ehci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
                                 unsigned int stream)
811 812 813 814 815 816 817 818 819 820 821 822
{
    EHCIState *s = container_of(bus, EHCIState, bus);
    uint32_t portsc = s->portsc[ep->dev->port->index];

    if (portsc & PORTSC_POWNER) {
        return;
    }

    s->periodic_sched_active = PERIODIC_ACTIVE;
    qemu_bh_schedule(s->async_bh);
}

823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
static USBDevice *ehci_find_device(EHCIState *ehci, uint8_t addr)
{
    USBDevice *dev;
    USBPort *port;
    int i;

    for (i = 0; i < NB_PORTS; i++) {
        port = &ehci->ports[i];
        if (!(ehci->portsc[i] & PORTSC_PED)) {
            DPRINTF("Port %d not enabled\n", i);
            continue;
        }
        dev = usb_find_device(port, addr);
        if (dev != NULL) {
            return dev;
        }
    }
    return NULL;
}

G
Gerd Hoffmann 已提交
843
/* 4.1 host controller initialization */
844
void ehci_reset(void *opaque)
G
Gerd Hoffmann 已提交
845 846 847
{
    EHCIState *s = opaque;
    int i;
848
    USBDevice *devs[NB_PORTS];
G
Gerd Hoffmann 已提交
849

G
Gerd Hoffmann 已提交
850
    trace_usb_ehci_reset();
G
Gerd Hoffmann 已提交
851

852 853 854 855 856 857
    /*
     * Do the detach before touching portsc, so that it correctly gets send to
     * us or to our companion based on PORTSC_POWNER before the reset.
     */
    for(i = 0; i < NB_PORTS; i++) {
        devs[i] = s->ports[i].dev;
858 859
        if (devs[i] && devs[i]->attached) {
            usb_detach(&s->ports[i]);
860 861 862
        }
    }

863 864
    memset(&s->opreg, 0x00, sizeof(s->opreg));
    memset(&s->portsc, 0x00, sizeof(s->portsc));
G
Gerd Hoffmann 已提交
865 866 867

    s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
    s->usbsts = USBSTS_HALT;
868 869
    s->usbsts_pending = 0;
    s->usbsts_frindex = 0;
G
Gerd Hoffmann 已提交
870
    ehci_update_irq(s);
G
Gerd Hoffmann 已提交
871 872 873 874 875

    s->astate = EST_INACTIVE;
    s->pstate = EST_INACTIVE;

    for(i = 0; i < NB_PORTS; i++) {
876 877 878 879 880
        if (s->companion_ports[i]) {
            s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
        } else {
            s->portsc[i] = PORTSC_PPOWER;
        }
881 882
        if (devs[i] && devs[i]->attached) {
            usb_attach(&s->ports[i]);
G
Gerd Hoffmann 已提交
883
            usb_device_reset(devs[i]);
G
Gerd Hoffmann 已提交
884 885
        }
    }
886 887
    ehci_queues_rip_all(s, 0);
    ehci_queues_rip_all(s, 1);
888
    timer_del(s->frame_timer);
889
    qemu_bh_cancel(s->async_bh);
G
Gerd Hoffmann 已提交
890 891
}

A
Avi Kivity 已提交
892
static uint64_t ehci_caps_read(void *ptr, hwaddr addr,
893
                               unsigned size)
G
Gerd Hoffmann 已提交
894 895
{
    EHCIState *s = ptr;
896
    return s->caps[addr];
G
Gerd Hoffmann 已提交
897 898
}

899 900 901 902 903
static void ehci_caps_write(void *ptr, hwaddr addr,
                             uint64_t val, unsigned size)
{
}

A
Avi Kivity 已提交
904
static uint64_t ehci_opreg_read(void *ptr, hwaddr addr,
905
                                unsigned size)
G
Gerd Hoffmann 已提交
906 907 908 909
{
    EHCIState *s = ptr;
    uint32_t val;

910 911 912 913 914 915 916 917 918
    switch (addr) {
    case FRINDEX:
        /* Round down to mult of 8, else it can go backwards on migration */
        val = s->frindex & ~7;
        break;
    default:
        val = s->opreg[addr >> 2];
    }

919
    trace_usb_ehci_opreg_read(addr + s->opregbase, addr2str(addr), val);
G
Gerd Hoffmann 已提交
920 921 922
    return val;
}

A
Avi Kivity 已提交
923
static uint64_t ehci_port_read(void *ptr, hwaddr addr,
924
                               unsigned size)
G
Gerd Hoffmann 已提交
925 926 927 928
{
    EHCIState *s = ptr;
    uint32_t val;

929
    val = s->portsc[addr >> 2];
930
    trace_usb_ehci_portsc_read(addr + s->portscbase, addr >> 2, val);
G
Gerd Hoffmann 已提交
931 932 933
    return val;
}

934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
{
    USBDevice *dev = s->ports[port].dev;
    uint32_t *portsc = &s->portsc[port];
    uint32_t orig;

    if (s->companion_ports[port] == NULL)
        return;

    owner = owner & PORTSC_POWNER;
    orig  = *portsc & PORTSC_POWNER;

    if (!(owner ^ orig)) {
        return;
    }

950 951
    if (dev && dev->attached) {
        usb_detach(&s->ports[port]);
952 953 954 955 956
    }

    *portsc &= ~PORTSC_POWNER;
    *portsc |= owner;

957 958
    if (dev && dev->attached) {
        usb_attach(&s->ports[port]);
959 960 961
    }
}

A
Avi Kivity 已提交
962
static void ehci_port_write(void *ptr, hwaddr addr,
963
                            uint64_t val, unsigned size)
G
Gerd Hoffmann 已提交
964
{
965 966
    EHCIState *s = ptr;
    int port = addr >> 2;
G
Gerd Hoffmann 已提交
967
    uint32_t *portsc = &s->portsc[port];
968
    uint32_t old = *portsc;
G
Gerd Hoffmann 已提交
969 970
    USBDevice *dev = s->ports[port].dev;

971
    trace_usb_ehci_portsc_write(addr + s->portscbase, addr >> 2, val);
972

973 974 975 976
    /* Clear rwc bits */
    *portsc &= ~(val & PORTSC_RWC_MASK);
    /* The guest may clear, but not set the PED bit */
    *portsc &= val | ~PORTSC_PED;
977 978 979
    /* POWNER is masked out by RO_MASK as it is RO when we've no companion */
    handle_port_owner_write(s, port, val);
    /* And finally apply RO_MASK */
G
Gerd Hoffmann 已提交
980 981 982
    val &= PORTSC_RO_MASK;

    if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
G
Gerd Hoffmann 已提交
983
        trace_usb_ehci_port_reset(port, 1);
G
Gerd Hoffmann 已提交
984 985 986
    }

    if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
G
Gerd Hoffmann 已提交
987
        trace_usb_ehci_port_reset(port, 0);
988
        if (dev && dev->attached) {
G
Gerd Hoffmann 已提交
989
            usb_port_reset(&s->ports[port]);
G
Gerd Hoffmann 已提交
990 991 992
            *portsc &= ~PORTSC_CSC;
        }

993 994
        /*
         *  Table 2.16 Set the enable bit(and enable bit change) to indicate
G
Gerd Hoffmann 已提交
995 996
         *  to SW that this port has a high speed device attached
         */
997
        if (dev && dev->attached && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
998 999
            val |= PORTSC_PED;
        }
G
Gerd Hoffmann 已提交
1000 1001
    }

G
Gerd Hoffmann 已提交
1002 1003 1004 1005 1006 1007 1008 1009
    if ((val & PORTSC_SUSPEND) && !(*portsc & PORTSC_SUSPEND)) {
        trace_usb_ehci_port_suspend(port);
    }
    if (!(val & PORTSC_FPRES) && (*portsc & PORTSC_FPRES)) {
        trace_usb_ehci_port_resume(port);
        val &= ~PORTSC_SUSPEND;
    }

G
Gerd Hoffmann 已提交
1010 1011
    *portsc &= ~PORTSC_RO_MASK;
    *portsc |= val;
1012
    trace_usb_ehci_portsc_change(addr + s->portscbase, addr >> 2, *portsc, old);
G
Gerd Hoffmann 已提交
1013 1014
}

A
Avi Kivity 已提交
1015
static void ehci_opreg_write(void *ptr, hwaddr addr,
1016
                             uint64_t val, unsigned size)
G
Gerd Hoffmann 已提交
1017 1018
{
    EHCIState *s = ptr;
1019
    uint32_t *mmio = s->opreg + (addr >> 2);
G
Gerd Hoffmann 已提交
1020
    uint32_t old = *mmio;
G
Gerd Hoffmann 已提交
1021
    int i;
G
Gerd Hoffmann 已提交
1022

1023
    trace_usb_ehci_opreg_write(addr + s->opregbase, addr2str(addr), val);
G
Gerd Hoffmann 已提交
1024

1025
    switch (addr) {
G
Gerd Hoffmann 已提交
1026
    case USBCMD:
G
Gerd Hoffmann 已提交
1027 1028 1029 1030 1031 1032
        if (val & USBCMD_HCRESET) {
            ehci_reset(s);
            val = s->usbcmd;
            break;
        }

1033 1034 1035
        /* not supporting dynamic frame list size at the moment */
        if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
            fprintf(stderr, "attempt to set frame list size -- value %d\n",
1036
                    (int)val & USBCMD_FLS);
1037 1038 1039
            val &= ~USBCMD_FLS;
        }

1040 1041 1042 1043 1044 1045 1046
        if (val & USBCMD_IAAD) {
            /*
             * Process IAAD immediately, otherwise the Linux IAAD watchdog may
             * trigger and re-use a qh without us seeing the unlink.
             */
            s->async_stepdown = 0;
            qemu_bh_schedule(s->async_bh);
G
Gerd Hoffmann 已提交
1047
            trace_usb_ehci_doorbell_ring();
1048 1049
        }

G
Gerd Hoffmann 已提交
1050 1051
        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
G
Gerd Hoffmann 已提交
1052
            if (s->pstate == EST_INACTIVE) {
G
Gerd Hoffmann 已提交
1053 1054
                SET_LAST_RUN_CLOCK(s);
            }
1055
            s->usbcmd = val; /* Set usbcmd for ehci_update_halt() */
G
Gerd Hoffmann 已提交
1056
            ehci_update_halt(s);
G
Gerd Hoffmann 已提交
1057
            s->async_stepdown = 0;
1058
            qemu_bh_schedule(s->async_bh);
G
Gerd Hoffmann 已提交
1059 1060 1061 1062
        }
        break;

    case USBSTS:
J
Jim Meyering 已提交
1063 1064
        val &= USBSTS_RO_MASK;              // bits 6 through 31 are RO
        ehci_clear_usbsts(s, val);          // bits 0 through 5 are R/WC
G
Gerd Hoffmann 已提交
1065
        val = s->usbsts;
1066
        ehci_update_irq(s);
G
Gerd Hoffmann 已提交
1067 1068 1069 1070
        break;

    case USBINTR:
        val &= USBINTR_MASK;
1071 1072 1073
        if (ehci_enabled(s) && (USBSTS_FLR & val)) {
            qemu_bh_schedule(s->async_bh);
        }
G
Gerd Hoffmann 已提交
1074 1075
        break;

1076
    case FRINDEX:
1077 1078
        val &= 0x00003fff; /* frindex is 14bits */
        s->usbsts_frindex = val;
1079 1080
        break;

G
Gerd Hoffmann 已提交
1081 1082 1083 1084
    case CONFIGFLAG:
        val &= 0x1;
        if (val) {
            for(i = 0; i < NB_PORTS; i++)
1085
                handle_port_owner_write(s, i, 0);
G
Gerd Hoffmann 已提交
1086 1087 1088 1089
        }
        break;

    case PERIODICLISTBASE:
1090
        if (ehci_periodic_enabled(s)) {
G
Gerd Hoffmann 已提交
1091 1092 1093 1094 1095 1096 1097
            fprintf(stderr,
              "ehci: PERIODIC list base register set while periodic schedule\n"
              "      is enabled and HC is enabled\n");
        }
        break;

    case ASYNCLISTADDR:
1098
        if (ehci_async_enabled(s)) {
G
Gerd Hoffmann 已提交
1099 1100 1101 1102 1103 1104 1105
            fprintf(stderr,
              "ehci: ASYNC list address register set while async schedule\n"
              "      is enabled and HC is enabled\n");
        }
        break;
    }

G
Gerd Hoffmann 已提交
1106
    *mmio = val;
1107 1108
    trace_usb_ehci_opreg_change(addr + s->opregbase, addr2str(addr),
                                *mmio, old);
G
Gerd Hoffmann 已提交
1109 1110
}

G
Gerd Hoffmann 已提交
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
/*
 *  Write the qh back to guest physical memory.  This step isn't
 *  in the EHCI spec but we need to do it since we don't share
 *  physical memory with our guest VM.
 *
 *  The first three dwords are read-only for the EHCI, so skip them
 *  when writing back the qh.
 */
static void ehci_flush_qh(EHCIQueue *q)
{
    uint32_t *qh = (uint32_t *) &q->qh;
    uint32_t dwords = sizeof(EHCIqh) >> 2;
    uint32_t addr = NLPTR_GET(q->qhaddr);

    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
}

G
Gerd Hoffmann 已提交
1128 1129
// 4.10.2

G
Gerd Hoffmann 已提交
1130
static int ehci_qh_do_overlay(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1131
{
G
Gerd Hoffmann 已提交
1132
    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
G
Gerd Hoffmann 已提交
1133 1134 1135 1136 1137 1138
    int i;
    int dtoggle;
    int ping;
    int eps;
    int reload;

G
Gerd Hoffmann 已提交
1139 1140 1141
    assert(p != NULL);
    assert(p->qtdaddr == q->qtdaddr);

G
Gerd Hoffmann 已提交
1142 1143
    // remember values in fields to preserve in qh after overlay

G
Gerd Hoffmann 已提交
1144 1145
    dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE;
    ping    = q->qh.token & QTD_TOKEN_PING;
G
Gerd Hoffmann 已提交
1146

G
Gerd Hoffmann 已提交
1147 1148 1149 1150
    q->qh.current_qtd = p->qtdaddr;
    q->qh.next_qtd    = p->qtd.next;
    q->qh.altnext_qtd = p->qtd.altnext;
    q->qh.token       = p->qtd.token;
G
Gerd Hoffmann 已提交
1151 1152


G
Gerd Hoffmann 已提交
1153
    eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
G
Gerd Hoffmann 已提交
1154
    if (eps == EHCI_QH_EPS_HIGH) {
G
Gerd Hoffmann 已提交
1155 1156
        q->qh.token &= ~QTD_TOKEN_PING;
        q->qh.token |= ping;
G
Gerd Hoffmann 已提交
1157 1158
    }

G
Gerd Hoffmann 已提交
1159 1160
    reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
    set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
G
Gerd Hoffmann 已提交
1161 1162

    for (i = 0; i < 5; i++) {
G
Gerd Hoffmann 已提交
1163
        q->qh.bufptr[i] = p->qtd.bufptr[i];
G
Gerd Hoffmann 已提交
1164 1165
    }

G
Gerd Hoffmann 已提交
1166
    if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
G
Gerd Hoffmann 已提交
1167
        // preserve QH DT bit
G
Gerd Hoffmann 已提交
1168 1169
        q->qh.token &= ~QTD_TOKEN_DTOGGLE;
        q->qh.token |= dtoggle;
G
Gerd Hoffmann 已提交
1170 1171
    }

G
Gerd Hoffmann 已提交
1172 1173
    q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
    q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
G
Gerd Hoffmann 已提交
1174

G
Gerd Hoffmann 已提交
1175
    ehci_flush_qh(q);
G
Gerd Hoffmann 已提交
1176 1177 1178 1179

    return 0;
}

G
Gerd Hoffmann 已提交
1180
static int ehci_init_transfer(EHCIPacket *p)
G
Gerd Hoffmann 已提交
1181
{
1182
    uint32_t cpage, offset, bytes, plen;
1183
    dma_addr_t page;
G
Gerd Hoffmann 已提交
1184

G
Gerd Hoffmann 已提交
1185 1186 1187
    cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
    bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
    offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
1188
    qemu_sglist_init(&p->sgl, p->queue->ehci->device, 5, p->queue->ehci->as);
G
Gerd Hoffmann 已提交
1189

1190 1191 1192
    while (bytes > 0) {
        if (cpage > 4) {
            fprintf(stderr, "cpage out of range (%d)\n", cpage);
1193
            qemu_sglist_destroy(&p->sgl);
1194
            return -1;
1195
        }
G
Gerd Hoffmann 已提交
1196

G
Gerd Hoffmann 已提交
1197
        page  = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
1198 1199 1200 1201 1202 1203
        page += offset;
        plen  = bytes;
        if (plen > 4096 - offset) {
            plen = 4096 - offset;
            offset = 0;
            cpage++;
G
Gerd Hoffmann 已提交
1204 1205
        }

G
Gerd Hoffmann 已提交
1206
        qemu_sglist_add(&p->sgl, page, plen);
1207 1208 1209 1210
        bytes -= plen;
    }
    return 0;
}
G
Gerd Hoffmann 已提交
1211

1212
static void ehci_finish_transfer(EHCIQueue *q, int len)
1213 1214
{
    uint32_t cpage, offset;
G
Gerd Hoffmann 已提交
1215

1216
    if (len > 0) {
1217 1218 1219
        /* update cpage & offset */
        cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
        offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
G
Gerd Hoffmann 已提交
1220

1221
        offset += len;
1222 1223
        cpage  += offset >> QTD_BUFPTR_SH;
        offset &= ~QTD_BUFPTR_MASK;
G
Gerd Hoffmann 已提交
1224

1225 1226 1227 1228
        set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE);
        q->qh.bufptr[0] &= QTD_BUFPTR_MASK;
        q->qh.bufptr[0] |= offset;
    }
G
Gerd Hoffmann 已提交
1229 1230
}

1231
static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
G
Gerd Hoffmann 已提交
1232
{
G
Gerd Hoffmann 已提交
1233
    EHCIPacket *p;
1234 1235 1236 1237 1238 1239 1240 1241
    EHCIState *s = port->opaque;
    uint32_t portsc = s->portsc[port->index];

    if (portsc & PORTSC_POWNER) {
        USBPort *companion = s->companion_ports[port->index];
        companion->ops->complete(companion, packet);
        return;
    }
G
Gerd Hoffmann 已提交
1242

G
Gerd Hoffmann 已提交
1243 1244
    p = container_of(packet, EHCIPacket, packet);
    assert(p->async == EHCI_ASYNC_INFLIGHT);
1245

1246
    if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
1247 1248 1249 1250 1251 1252
        trace_usb_ehci_packet_action(p->queue, p, "remove");
        ehci_free_packet(p);
        return;
    }

    trace_usb_ehci_packet_action(p->queue, p, "wakeup");
G
Gerd Hoffmann 已提交
1253
    p->async = EHCI_ASYNC_FINISHED;
1254

1255 1256
    if (!p->queue->async) {
        s->periodic_sched_active = PERIODIC_ACTIVE;
1257
    }
1258
    qemu_bh_schedule(s->async_bh);
G
Gerd Hoffmann 已提交
1259 1260
}

G
Gerd Hoffmann 已提交
1261
static void ehci_execute_complete(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1262
{
G
Gerd Hoffmann 已提交
1263
    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
1264
    uint32_t tbytes;
G
Gerd Hoffmann 已提交
1265 1266 1267

    assert(p != NULL);
    assert(p->qtdaddr == q->qtdaddr);
1268 1269
    assert(p->async == EHCI_ASYNC_INITIALIZED ||
           p->async == EHCI_ASYNC_FINISHED);
G
Gerd Hoffmann 已提交
1270

1271 1272 1273 1274
    DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, "
            "status %d, actual_length %d\n",
            q->qhaddr, q->qh.next, q->qtdaddr,
            p->packet.status, p->packet.actual_length);
G
Gerd Hoffmann 已提交
1275

1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
    switch (p->packet.status) {
    case USB_RET_SUCCESS:
        break;
    case USB_RET_IOERROR:
    case USB_RET_NODEV:
        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
        set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
        break;
    case USB_RET_STALL:
        q->qh.token |= QTD_TOKEN_HALT;
        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
        break;
    case USB_RET_NAK:
        set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
        return; /* We're not done yet with this transaction */
    case USB_RET_BABBLE:
        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
        break;
    default:
        /* should not be triggerable */
        fprintf(stderr, "USB invalid response %d\n", p->packet.status);
1299
        g_assert_not_reached();
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
        break;
    }

    /* TODO check 4.12 for splits */
    tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES);
    if (tbytes && p->pid == USB_TOKEN_IN) {
        tbytes -= p->packet.actual_length;
        if (tbytes) {
            /* 4.15.1.2 must raise int on a short input packet */
            ehci_raise_irq(q->ehci, USBSTS_INT);
1310 1311 1312
            if (q->async) {
                q->ehci->int_req_by_async = true;
            }
G
Gerd Hoffmann 已提交
1313 1314
        }
    } else {
1315
        tbytes = 0;
G
Gerd Hoffmann 已提交
1316
    }
1317 1318 1319 1320
    DPRINTF("updating tbytes to %d\n", tbytes);
    set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES);

    ehci_finish_transfer(q, p->packet.actual_length);
1321
    usb_packet_unmap(&p->packet, &p->sgl);
G
Gerd Hoffmann 已提交
1322
    qemu_sglist_destroy(&p->sgl);
1323
    p->async = EHCI_ASYNC_NONE;
G
Gerd Hoffmann 已提交
1324

G
Gerd Hoffmann 已提交
1325 1326
    q->qh.token ^= QTD_TOKEN_DTOGGLE;
    q->qh.token &= ~QTD_TOKEN_ACTIVE;
G
Gerd Hoffmann 已提交
1327

1328
    if (q->qh.token & QTD_TOKEN_IOC) {
1329
        ehci_raise_irq(q->ehci, USBSTS_INT);
1330 1331 1332
        if (q->async) {
            q->ehci->int_req_by_async = true;
        }
G
Gerd Hoffmann 已提交
1333 1334 1335
    }
}

1336
/* 4.10.3 returns "again" */
G
Gerd Hoffmann 已提交
1337
static int ehci_execute(EHCIPacket *p, const char *action)
G
Gerd Hoffmann 已提交
1338
{
1339
    USBEndpoint *ep;
G
Gerd Hoffmann 已提交
1340
    int endp;
1341
    bool spd;
G
Gerd Hoffmann 已提交
1342

1343 1344 1345
    assert(p->async == EHCI_ASYNC_NONE ||
           p->async == EHCI_ASYNC_INITIALIZED);

1346 1347
    if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
        fprintf(stderr, "Attempting to execute inactive qtd\n");
1348
        return -1;
G
Gerd Hoffmann 已提交
1349 1350
    }

1351
    if (get_field(p->qtd.token, QTD_TOKEN_TBYTES) > BUFF_SIZE) {
1352 1353
        ehci_trace_guest_bug(p->queue->ehci,
                             "guest requested more bytes than allowed");
1354
        return -1;
G
Gerd Hoffmann 已提交
1355 1356
    }

1357 1358 1359
    if (!ehci_verify_pid(p->queue, &p->qtd)) {
        ehci_queue_stopped(p->queue); /* Mark the ep in the prev dir stopped */
    }
1360
    p->pid = ehci_get_pid(&p->qtd);
1361
    p->queue->last_pid = p->pid;
1362
    endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
1363
    ep = usb_ep_get(p->queue->dev, p->pid, endp);
G
Gerd Hoffmann 已提交
1364

1365 1366
    if (p->async == EHCI_ASYNC_NONE) {
        if (ehci_init_transfer(p) != 0) {
1367
            return -1;
1368 1369
        }

1370
        spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0);
G
Gerd Hoffmann 已提交
1371
        usb_packet_setup(&p->packet, p->pid, ep, 0, p->qtdaddr, spd,
1372
                         (p->qtd.token & QTD_TOKEN_IOC) != 0);
1373 1374 1375
        usb_packet_map(&p->packet, &p->sgl);
        p->async = EHCI_ASYNC_INITIALIZED;
    }
1376

G
Gerd Hoffmann 已提交
1377
    trace_usb_ehci_packet_action(p->queue, p, action);
1378 1379 1380 1381 1382
    usb_handle_packet(p->queue->dev, &p->packet);
    DPRINTF("submit: qh 0x%x next 0x%x qtd 0x%x pid 0x%x len %zd endp 0x%x "
            "status %d actual_length %d\n", p->queue->qhaddr, p->qtd.next,
            p->qtdaddr, p->pid, p->packet.iov.size, endp, p->packet.status,
            p->packet.actual_length);
G
Gerd Hoffmann 已提交
1383

1384
    if (p->packet.actual_length > BUFF_SIZE) {
G
Gerd Hoffmann 已提交
1385
        fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
1386
        return -1;
G
Gerd Hoffmann 已提交
1387 1388
    }

1389
    return 1;
G
Gerd Hoffmann 已提交
1390 1391 1392 1393 1394 1395
}

/*  4.7.2
 */

static int ehci_process_itd(EHCIState *ehci,
G
Gerd Hoffmann 已提交
1396 1397
                            EHCIitd *itd,
                            uint32_t addr)
G
Gerd Hoffmann 已提交
1398 1399
{
    USBDevice *dev;
1400
    USBEndpoint *ep;
1401
    uint32_t i, len, pid, dir, devaddr, endp;
G
Gerd Hoffmann 已提交
1402
    uint32_t pg, off, ptr1, ptr2, max, mult;
G
Gerd Hoffmann 已提交
1403

1404 1405
    ehci->periodic_sched_active = PERIODIC_ACTIVE;

G
Gerd Hoffmann 已提交
1406
    dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
G
Gerd Hoffmann 已提交
1407
    devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
G
Gerd Hoffmann 已提交
1408
    endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
G
Gerd Hoffmann 已提交
1409 1410
    max = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT);
    mult = get_field(itd->bufptr[2], ITD_BUFPTR_MULT);
G
Gerd Hoffmann 已提交
1411 1412 1413

    for(i = 0; i < 8; i++) {
        if (itd->transact[i] & ITD_XACT_ACTIVE) {
G
Gerd Hoffmann 已提交
1414 1415 1416 1417 1418 1419 1420
            pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
            off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
            len  = get_field(itd->transact[i], ITD_XACT_LENGTH);

            if (len > max * mult) {
                len = max * mult;
            }
1421
            if (len > BUFF_SIZE || pg > 6) {
1422
                return -1;
G
Gerd Hoffmann 已提交
1423 1424
            }

1425
            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
1426
            qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as);
G
Gerd Hoffmann 已提交
1427 1428
            if (off + len > 4096) {
                /* transfer crosses page border */
1429
                if (pg == 6) {
1430
                    qemu_sglist_destroy(&ehci->isgl);
1431 1432 1433
                    return -1;  /* avoid page pg + 1 */
                }
                ptr2 = (itd->bufptr[pg + 1] & ITD_BUFPTR_MASK);
1434 1435 1436 1437
                uint32_t len2 = off + len - 4096;
                uint32_t len1 = len - len2;
                qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);
                qemu_sglist_add(&ehci->isgl, ptr2, len2);
G
Gerd Hoffmann 已提交
1438
            } else {
1439
                qemu_sglist_add(&ehci->isgl, ptr1 + off, len);
G
Gerd Hoffmann 已提交
1440
            }
G
Gerd Hoffmann 已提交
1441

1442
            pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
G
Gerd Hoffmann 已提交
1443

1444 1445
            dev = ehci_find_device(ehci, devaddr);
            ep = usb_ep_get(dev, pid, endp);
1446
            if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
G
Gerd Hoffmann 已提交
1447
                usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false,
1448
                                 (itd->transact[i] & ITD_XACT_IOC) != 0);
G
Gerd Hoffmann 已提交
1449
                usb_packet_map(&ehci->ipacket, &ehci->isgl);
1450
                usb_handle_packet(dev, &ehci->ipacket);
1451
                usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
G
Gerd Hoffmann 已提交
1452 1453
            } else {
                DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
1454 1455
                ehci->ipacket.status = USB_RET_NAK;
                ehci->ipacket.actual_length = 0;
G
Gerd Hoffmann 已提交
1456
            }
1457 1458
            qemu_sglist_destroy(&ehci->isgl);

1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
            switch (ehci->ipacket.status) {
            case USB_RET_SUCCESS:
                break;
            default:
                fprintf(stderr, "Unexpected iso usb result: %d\n",
                        ehci->ipacket.status);
                /* Fall through */
            case USB_RET_IOERROR:
            case USB_RET_NODEV:
                /* 3.3.2: XACTERR is only allowed on IN transactions */
                if (dir) {
                    itd->transact[i] |= ITD_XACT_XACTERR;
1471
                    ehci_raise_irq(ehci, USBSTS_ERRINT);
1472
                }
1473 1474 1475 1476 1477 1478 1479 1480 1481
                break;
            case USB_RET_BABBLE:
                itd->transact[i] |= ITD_XACT_BABBLE;
                ehci_raise_irq(ehci, USBSTS_ERRINT);
                break;
            case USB_RET_NAK:
                /* no data for us, so do a zero-length transfer */
                ehci->ipacket.actual_length = 0;
                break;
1482
            }
1483 1484 1485 1486 1487 1488
            if (!dir) {
                set_field(&itd->transact[i], len - ehci->ipacket.actual_length,
                          ITD_XACT_LENGTH); /* OUT */
            } else {
                set_field(&itd->transact[i], ehci->ipacket.actual_length,
                          ITD_XACT_LENGTH); /* IN */
G
Gerd Hoffmann 已提交
1489
            }
1490
            if (itd->transact[i] & ITD_XACT_IOC) {
1491
                ehci_raise_irq(ehci, USBSTS_INT);
1492
            }
G
Gerd Hoffmann 已提交
1493
            itd->transact[i] &= ~ITD_XACT_ACTIVE;
G
Gerd Hoffmann 已提交
1494 1495
        }
    }
1496
    return 0;
G
Gerd Hoffmann 已提交
1497 1498
}

G
Gerd Hoffmann 已提交
1499

G
Gerd Hoffmann 已提交
1500 1501 1502
/*  This state is the entry point for asynchronous schedule
 *  processing.  Entry here consitutes a EHCI start event state (4.8.5)
 */
1503
static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
G
Gerd Hoffmann 已提交
1504
{
G
Gerd Hoffmann 已提交
1505
    EHCIqh qh;
G
Gerd Hoffmann 已提交
1506 1507 1508 1509 1510 1511
    int i = 0;
    int again = 0;
    uint32_t entry = ehci->asynclistaddr;

    /* set reclamation flag at start event (4.8.6) */
    if (async) {
G
Gerd Hoffmann 已提交
1512
        ehci_set_usbsts(ehci, USBSTS_REC);
G
Gerd Hoffmann 已提交
1513 1514
    }

1515
    ehci_queues_rip_unused(ehci, async);
G
Gerd Hoffmann 已提交
1516

G
Gerd Hoffmann 已提交
1517 1518
    /*  Find the head of the list (4.9.1.1) */
    for(i = 0; i < MAX_QH; i++) {
G
Gerd Hoffmann 已提交
1519 1520 1521 1522
        if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh,
                       sizeof(EHCIqh) >> 2) < 0) {
            return 0;
        }
G
Gerd Hoffmann 已提交
1523
        ehci_trace_qh(NULL, NLPTR_GET(entry), &qh);
G
Gerd Hoffmann 已提交
1524

G
Gerd Hoffmann 已提交
1525
        if (qh.epchar & QH_EPCHAR_H) {
G
Gerd Hoffmann 已提交
1526 1527 1528 1529
            if (async) {
                entry |= (NLPTR_TYPE_QH << 1);
            }

G
Gerd Hoffmann 已提交
1530
            ehci_set_fetch_addr(ehci, async, entry);
1531
            ehci_set_state(ehci, async, EST_FETCHENTRY);
G
Gerd Hoffmann 已提交
1532 1533 1534 1535
            again = 1;
            goto out;
        }

G
Gerd Hoffmann 已提交
1536
        entry = qh.next;
G
Gerd Hoffmann 已提交
1537 1538 1539 1540 1541 1542 1543
        if (entry == ehci->asynclistaddr) {
            break;
        }
    }

    /* no head found for list. */

1544
    ehci_set_state(ehci, async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
1545 1546 1547 1548 1549 1550 1551 1552 1553

out:
    return again;
}


/*  This state is the entry point for periodic schedule processing as
 *  well as being a continuation state for async processing.
 */
1554
static int ehci_state_fetchentry(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
1555 1556
{
    int again = 0;
G
Gerd Hoffmann 已提交
1557
    uint32_t entry = ehci_get_fetch_addr(ehci, async);
G
Gerd Hoffmann 已提交
1558

1559
    if (NLPTR_TBIT(entry)) {
1560
        ehci_set_state(ehci, async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
        goto out;
    }

    /* section 4.8, only QH in async schedule */
    if (async && (NLPTR_TYPE_GET(entry) != NLPTR_TYPE_QH)) {
        fprintf(stderr, "non queue head request in async schedule\n");
        return -1;
    }

    switch (NLPTR_TYPE_GET(entry)) {
    case NLPTR_TYPE_QH:
1572
        ehci_set_state(ehci, async, EST_FETCHQH);
G
Gerd Hoffmann 已提交
1573 1574 1575 1576
        again = 1;
        break;

    case NLPTR_TYPE_ITD:
1577
        ehci_set_state(ehci, async, EST_FETCHITD);
G
Gerd Hoffmann 已提交
1578 1579 1580
        again = 1;
        break;

G
Gerd Hoffmann 已提交
1581 1582 1583 1584 1585
    case NLPTR_TYPE_STITD:
        ehci_set_state(ehci, async, EST_FETCHSITD);
        again = 1;
        break;

G
Gerd Hoffmann 已提交
1586
    default:
G
Gerd Hoffmann 已提交
1587
        /* TODO: handle FSTN type */
G
Gerd Hoffmann 已提交
1588 1589 1590 1591 1592 1593 1594 1595 1596
        fprintf(stderr, "FETCHENTRY: entry at %X is of type %d "
                "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
        return -1;
    }

out:
    return again;
}

G
Gerd Hoffmann 已提交
1597
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
1598
{
1599
    uint32_t entry;
G
Gerd Hoffmann 已提交
1600
    EHCIQueue *q;
1601
    EHCIqh qh;
G
Gerd Hoffmann 已提交
1602

G
Gerd Hoffmann 已提交
1603
    entry = ehci_get_fetch_addr(ehci, async);
1604
    q = ehci_find_queue_by_qh(ehci, entry, async);
G
Gonglei 已提交
1605
    if (q == NULL) {
G
Gerd Hoffmann 已提交
1606
        q = ehci_alloc_queue(ehci, entry, async);
G
Gerd Hoffmann 已提交
1607 1608
    }

G
Gerd Hoffmann 已提交
1609
    q->seen++;
G
Gerd Hoffmann 已提交
1610 1611 1612 1613 1614 1615
    if (q->seen > 1) {
        /* we are going in circles -- stop processing */
        ehci_set_state(ehci, async, EST_ACTIVE);
        q = NULL;
        goto out;
    }
G
Gerd Hoffmann 已提交
1616

G
Gerd Hoffmann 已提交
1617 1618 1619 1620 1621
    if (get_dwords(ehci, NLPTR_GET(q->qhaddr),
                   (uint32_t *) &qh, sizeof(EHCIqh) >> 2) < 0) {
        q = NULL;
        goto out;
    }
1622 1623 1624 1625 1626 1627
    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh);

    /*
     * The overlay area of the qh should never be changed by the guest,
     * except when idle, in which case the reset is a nop.
     */
1628
    if (!ehci_verify_qh(q, &qh)) {
G
Gerd Hoffmann 已提交
1629 1630 1631
        if (ehci_reset_queue(q) > 0) {
            ehci_trace_guest_bug(ehci, "guest updated active QH");
        }
1632 1633 1634
    }
    q->qh = qh;

1635 1636 1637 1638 1639
    q->transact_ctr = get_field(q->qh.epcap, QH_EPCAP_MULT);
    if (q->transact_ctr == 0) { /* Guest bug in some versions of windows */
        q->transact_ctr = 4;
    }

1640
    if (q->dev == NULL) {
1641 1642
        q->dev = ehci_find_device(q->ehci,
                                  get_field(q->qh.epchar, QH_EPCHAR_DEVADDR));
1643 1644
    }

G
Gerd Hoffmann 已提交
1645
    if (async && (q->qh.epchar & QH_EPCHAR_H)) {
G
Gerd Hoffmann 已提交
1646 1647 1648

        /*  EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */
        if (ehci->usbsts & USBSTS_REC) {
G
Gerd Hoffmann 已提交
1649
            ehci_clear_usbsts(ehci, USBSTS_REC);
G
Gerd Hoffmann 已提交
1650 1651
        } else {
            DPRINTF("FETCHQH:  QH 0x%08x. H-bit set, reclamation status reset"
G
Gerd Hoffmann 已提交
1652
                       " - done processing\n", q->qhaddr);
1653
            ehci_set_state(ehci, async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
1654
            q = NULL;
G
Gerd Hoffmann 已提交
1655 1656 1657 1658 1659
            goto out;
        }
    }

#if EHCI_DEBUG
G
Gerd Hoffmann 已提交
1660
    if (q->qhaddr != q->qh.next) {
G
Gerd Hoffmann 已提交
1661
    DPRINTF("FETCHQH:  QH 0x%08x (h %x halt %x active %x) next 0x%08x\n",
G
Gerd Hoffmann 已提交
1662 1663 1664 1665 1666
               q->qhaddr,
               q->qh.epchar & QH_EPCHAR_H,
               q->qh.token & QTD_TOKEN_HALT,
               q->qh.token & QTD_TOKEN_ACTIVE,
               q->qh.next);
G
Gerd Hoffmann 已提交
1667 1668 1669
    }
#endif

G
Gerd Hoffmann 已提交
1670
    if (q->qh.token & QTD_TOKEN_HALT) {
1671
        ehci_set_state(ehci, async, EST_HORIZONTALQH);
G
Gerd Hoffmann 已提交
1672

1673 1674
    } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
               (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
G
Gerd Hoffmann 已提交
1675
        q->qtdaddr = q->qh.current_qtd;
1676
        ehci_set_state(ehci, async, EST_FETCHQTD);
G
Gerd Hoffmann 已提交
1677 1678 1679

    } else {
        /*  EHCI spec version 1.0 Section 4.10.2 */
1680
        ehci_set_state(ehci, async, EST_ADVANCEQUEUE);
G
Gerd Hoffmann 已提交
1681 1682 1683
    }

out:
G
Gerd Hoffmann 已提交
1684
    return q;
G
Gerd Hoffmann 已提交
1685 1686
}

1687
static int ehci_state_fetchitd(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
1688
{
G
Gerd Hoffmann 已提交
1689
    uint32_t entry;
G
Gerd Hoffmann 已提交
1690 1691
    EHCIitd itd;

G
Gerd Hoffmann 已提交
1692 1693 1694
    assert(!async);
    entry = ehci_get_fetch_addr(ehci, async);

G
Gerd Hoffmann 已提交
1695 1696 1697 1698
    if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
                   sizeof(EHCIitd) >> 2) < 0) {
        return -1;
    }
G
Gerd Hoffmann 已提交
1699
    ehci_trace_itd(ehci, entry, &itd);
G
Gerd Hoffmann 已提交
1700

G
Gerd Hoffmann 已提交
1701
    if (ehci_process_itd(ehci, &itd, entry) != 0) {
G
Gerd Hoffmann 已提交
1702 1703 1704
        return -1;
    }

1705 1706
    put_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd,
               sizeof(EHCIitd) >> 2);
G
Gerd Hoffmann 已提交
1707
    ehci_set_fetch_addr(ehci, async, itd.next);
1708
    ehci_set_state(ehci, async, EST_FETCHENTRY);
G
Gerd Hoffmann 已提交
1709 1710 1711 1712

    return 1;
}

G
Gerd Hoffmann 已提交
1713 1714 1715 1716 1717 1718 1719 1720
static int ehci_state_fetchsitd(EHCIState *ehci, int async)
{
    uint32_t entry;
    EHCIsitd sitd;

    assert(!async);
    entry = ehci_get_fetch_addr(ehci, async);

G
Gerd Hoffmann 已提交
1721 1722 1723 1724
    if (get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd,
                   sizeof(EHCIsitd) >> 2) < 0) {
        return 0;
    }
G
Gerd Hoffmann 已提交
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
    ehci_trace_sitd(ehci, entry, &sitd);

    if (!(sitd.results & SITD_RESULTS_ACTIVE)) {
        /* siTD is not active, nothing to do */;
    } else {
        /* TODO: split transfers are not implemented */
        fprintf(stderr, "WARNING: Skipping active siTD\n");
    }

    ehci_set_fetch_addr(ehci, async, sitd.next);
    ehci_set_state(ehci, async, EST_FETCHENTRY);
    return 1;
}

G
Gerd Hoffmann 已提交
1739
/* Section 4.10.2 - paragraph 3 */
1740
static int ehci_state_advqueue(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1741 1742 1743 1744 1745 1746 1747
{
#if 0
    /* TO-DO: 4.10.2 - paragraph 2
     * if I-bit is set to 1 and QH is not active
     * go to horizontal QH
     */
    if (I-bit set) {
1748
        ehci_set_state(ehci, async, EST_HORIZONTALQH);
G
Gerd Hoffmann 已提交
1749 1750 1751 1752 1753 1754 1755
        goto out;
    }
#endif

    /*
     * want data and alt-next qTD is valid
     */
G
Gerd Hoffmann 已提交
1756 1757 1758
    if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
        (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
        q->qtdaddr = q->qh.altnext_qtd;
1759
        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
G
Gerd Hoffmann 已提交
1760 1761 1762 1763

    /*
     *  next qTD is valid
     */
1764
    } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
G
Gerd Hoffmann 已提交
1765
        q->qtdaddr = q->qh.next_qtd;
1766
        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
G
Gerd Hoffmann 已提交
1767 1768 1769 1770 1771

    /*
     *  no valid qTD, try next QH
     */
    } else {
1772
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
G
Gerd Hoffmann 已提交
1773 1774 1775 1776 1777 1778
    }

    return 1;
}

/* Section 4.10.2 - paragraph 4 */
1779
static int ehci_state_fetchqtd(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1780
{
G
Gerd Hoffmann 已提交
1781 1782
    EHCIqtd qtd;
    EHCIPacket *p;
1783
    int again = 1;
G
Gerd Hoffmann 已提交
1784

G
Gerd Hoffmann 已提交
1785 1786 1787 1788
    if (get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
                   sizeof(EHCIqtd) >> 2) < 0) {
        return 0;
    }
G
Gerd Hoffmann 已提交
1789
    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
G
Gerd Hoffmann 已提交
1790

G
Gerd Hoffmann 已提交
1791 1792
    p = QTAILQ_FIRST(&q->packets);
    if (p != NULL) {
1793
        if (!ehci_verify_qtd(p, &qtd)) {
1794
            ehci_cancel_queue(q);
1795 1796 1797
            if (qtd.token & QTD_TOKEN_ACTIVE) {
                ehci_trace_guest_bug(q->ehci, "guest updated active qTD");
            }
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807
            p = NULL;
        } else {
            p->qtd = qtd;
            ehci_qh_do_overlay(q);
        }
    }

    if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
    } else if (p != NULL) {
1808 1809
        switch (p->async) {
        case EHCI_ASYNC_NONE:
1810
        case EHCI_ASYNC_INITIALIZED:
1811
            /* Not yet executed (MULT), or previously nacked (int) packet */
1812 1813
            ehci_set_state(q->ehci, q->async, EST_EXECUTE);
            break;
1814
        case EHCI_ASYNC_INFLIGHT:
1815
            /* Check if the guest has added new tds to the queue */
1816
            again = ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head));
1817
            /* Unfinished async handled packet, go horizontal */
1818
            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
1819 1820
            break;
        case EHCI_ASYNC_FINISHED:
1821
            /* Complete executing of the packet */
1822
            ehci_set_state(q->ehci, q->async, EST_EXECUTING);
1823
            break;
G
Gerd Hoffmann 已提交
1824
        }
1825
    } else {
G
Gerd Hoffmann 已提交
1826 1827 1828
        p = ehci_alloc_packet(q);
        p->qtdaddr = q->qtdaddr;
        p->qtd = qtd;
1829
        ehci_set_state(q->ehci, q->async, EST_EXECUTE);
G
Gerd Hoffmann 已提交
1830 1831 1832 1833 1834
    }

    return again;
}

1835
static int ehci_state_horizqh(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1836 1837 1838
{
    int again = 0;

1839 1840 1841
    if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) {
        ehci_set_fetch_addr(q->ehci, q->async, q->qh.next);
        ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
G
Gerd Hoffmann 已提交
1842 1843
        again = 1;
    } else {
1844
        ehci_set_state(q->ehci, q->async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
1845 1846 1847 1848 1849
    }

    return again;
}

1850
/* Returns "again" */
1851
static int ehci_fill_queue(EHCIPacket *p)
G
Gerd Hoffmann 已提交
1852
{
1853
    USBEndpoint *ep = p->packet.ep;
G
Gerd Hoffmann 已提交
1854 1855
    EHCIQueue *q = p->queue;
    EHCIqtd qtd = p->qtd;
1856
    uint32_t qtdaddr;
G
Gerd Hoffmann 已提交
1857 1858 1859 1860 1861 1862

    for (;;) {
        if (NLPTR_TBIT(qtd.next) != 0) {
            break;
        }
        qtdaddr = qtd.next;
1863 1864 1865 1866
        /*
         * Detect circular td lists, Windows creates these, counting on the
         * active bit going low after execution to make the queue stop.
         */
1867 1868 1869 1870
        QTAILQ_FOREACH(p, &q->packets, next) {
            if (p->qtdaddr == qtdaddr) {
                goto leave;
            }
1871
        }
G
Gerd Hoffmann 已提交
1872 1873 1874 1875
        if (get_dwords(q->ehci, NLPTR_GET(qtdaddr),
                       (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2) < 0) {
            return -1;
        }
G
Gerd Hoffmann 已提交
1876 1877 1878 1879
        ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);
        if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
            break;
        }
1880 1881 1882 1883
        if (!ehci_verify_pid(q, &qtd)) {
            ehci_trace_guest_bug(q->ehci, "guest queued token with wrong pid");
            break;
        }
G
Gerd Hoffmann 已提交
1884 1885 1886
        p = ehci_alloc_packet(q);
        p->qtdaddr = qtdaddr;
        p->qtd = qtd;
1887 1888
        if (ehci_execute(p, "queue") == -1) {
            return -1;
1889
        }
1890
        assert(p->packet.status == USB_RET_ASYNC);
G
Gerd Hoffmann 已提交
1891 1892
        p->async = EHCI_ASYNC_INFLIGHT;
    }
1893
leave:
1894 1895
    usb_device_flush_ep_queue(ep->dev, ep);
    return 1;
G
Gerd Hoffmann 已提交
1896 1897
}

1898
static int ehci_state_execute(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1899
{
G
Gerd Hoffmann 已提交
1900
    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
G
Gerd Hoffmann 已提交
1901 1902
    int again = 0;

G
Gerd Hoffmann 已提交
1903 1904 1905
    assert(p != NULL);
    assert(p->qtdaddr == q->qtdaddr);

G
Gerd Hoffmann 已提交
1906
    if (ehci_qh_do_overlay(q) != 0) {
G
Gerd Hoffmann 已提交
1907 1908 1909 1910 1911 1912
        return -1;
    }

    // TODO verify enough time remains in the uframe as in 4.4.1.1
    // TODO write back ptr to async list when done or out of time

1913 1914 1915 1916 1917
    /* 4.10.3, bottom of page 82, go horizontal on transaction counter == 0 */
    if (!q->async && q->transact_ctr == 0) {
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
        again = 1;
        goto out;
G
Gerd Hoffmann 已提交
1918 1919
    }

1920
    if (q->async) {
G
Gerd Hoffmann 已提交
1921
        ehci_set_usbsts(q->ehci, USBSTS_REC);
G
Gerd Hoffmann 已提交
1922 1923
    }

1924 1925
    again = ehci_execute(p, "process");
    if (again == -1) {
G
Gerd Hoffmann 已提交
1926 1927
        goto out;
    }
1928
    if (p->packet.status == USB_RET_ASYNC) {
G
Gerd Hoffmann 已提交
1929
        ehci_flush_qh(q);
G
Gerd Hoffmann 已提交
1930
        trace_usb_ehci_packet_action(p->queue, p, "async");
G
Gerd Hoffmann 已提交
1931
        p->async = EHCI_ASYNC_INFLIGHT;
1932
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
1933
        if (q->async) {
1934
            again = ehci_fill_queue(p);
1935 1936 1937
        } else {
            again = 1;
        }
G
Gerd Hoffmann 已提交
1938
        goto out;
G
Gerd Hoffmann 已提交
1939 1940
    }

1941
    ehci_set_state(q->ehci, q->async, EST_EXECUTING);
G
Gerd Hoffmann 已提交
1942 1943
    again = 1;

G
Gerd Hoffmann 已提交
1944 1945 1946 1947
out:
    return again;
}

1948
static int ehci_state_executing(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1949
{
G
Gerd Hoffmann 已提交
1950
    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
G
Gerd Hoffmann 已提交
1951

G
Gerd Hoffmann 已提交
1952 1953 1954
    assert(p != NULL);
    assert(p->qtdaddr == q->qtdaddr);

G
Gerd Hoffmann 已提交
1955
    ehci_execute_complete(q);
G
Gerd Hoffmann 已提交
1956

1957 1958 1959
    /* 4.10.3 */
    if (!q->async && q->transact_ctr > 0) {
        q->transact_ctr--;
G
Gerd Hoffmann 已提交
1960 1961 1962
    }

    /* 4.10.5 */
1963
    if (p->packet.status == USB_RET_NAK) {
1964
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
G
Gerd Hoffmann 已提交
1965
    } else {
1966
        ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
G
Gerd Hoffmann 已提交
1967 1968
    }

G
Gerd Hoffmann 已提交
1969
    ehci_flush_qh(q);
1970
    return 1;
G
Gerd Hoffmann 已提交
1971 1972 1973
}


1974
static int ehci_state_writeback(EHCIQueue *q)
G
Gerd Hoffmann 已提交
1975
{
G
Gerd Hoffmann 已提交
1976
    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
G
Gerd Hoffmann 已提交
1977
    uint32_t *qtd, addr;
G
Gerd Hoffmann 已提交
1978 1979 1980
    int again = 0;

    /*  Write back the QTD from the QH area */
G
Gerd Hoffmann 已提交
1981 1982 1983 1984
    assert(p != NULL);
    assert(p->qtdaddr == q->qtdaddr);

    ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
G
Gerd Hoffmann 已提交
1985 1986 1987
    qtd = (uint32_t *) &q->qh.next_qtd;
    addr = NLPTR_GET(p->qtdaddr);
    put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2);
G
Gerd Hoffmann 已提交
1988
    ehci_free_packet(p);
G
Gerd Hoffmann 已提交
1989

G
Gerd Hoffmann 已提交
1990 1991 1992 1993 1994 1995 1996
    /*
     * EHCI specs say go horizontal here.
     *
     * We can also advance the queue here for performance reasons.  We
     * need to take care to only take that shortcut in case we've
     * processed the qtd just written back without errors, i.e. halt
     * bit is clear.
G
Gerd Hoffmann 已提交
1997
     */
G
Gerd Hoffmann 已提交
1998
    if (q->qh.token & QTD_TOKEN_HALT) {
1999
        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
G
Gerd Hoffmann 已提交
2000 2001
        again = 1;
    } else {
2002
        ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE);
G
Gerd Hoffmann 已提交
2003
        again = 1;
G
Gerd Hoffmann 已提交
2004
    }
G
Gerd Hoffmann 已提交
2005 2006 2007 2008 2009 2010 2011
    return again;
}

/*
 * This is the state machine that is common to both async and periodic
 */

2012
static void ehci_advance_state(EHCIState *ehci, int async)
G
Gerd Hoffmann 已提交
2013
{
G
Gerd Hoffmann 已提交
2014
    EHCIQueue *q = NULL;
2015
    int itd_count = 0;
G
Gerd Hoffmann 已提交
2016 2017 2018
    int again;

    do {
2019
        switch(ehci_get_state(ehci, async)) {
G
Gerd Hoffmann 已提交
2020
        case EST_WAITLISTHEAD:
2021
            again = ehci_state_waitlisthead(ehci, async);
G
Gerd Hoffmann 已提交
2022 2023 2024
            break;

        case EST_FETCHENTRY:
2025
            again = ehci_state_fetchentry(ehci, async);
G
Gerd Hoffmann 已提交
2026 2027 2028
            break;

        case EST_FETCHQH:
G
Gerd Hoffmann 已提交
2029
            q = ehci_state_fetchqh(ehci, async);
2030 2031 2032 2033 2034 2035
            if (q != NULL) {
                assert(q->async == async);
                again = 1;
            } else {
                again = 0;
            }
G
Gerd Hoffmann 已提交
2036 2037 2038
            break;

        case EST_FETCHITD:
2039
            again = ehci_state_fetchitd(ehci, async);
2040
            itd_count++;
G
Gerd Hoffmann 已提交
2041 2042
            break;

G
Gerd Hoffmann 已提交
2043 2044
        case EST_FETCHSITD:
            again = ehci_state_fetchsitd(ehci, async);
2045
            itd_count++;
G
Gerd Hoffmann 已提交
2046 2047
            break;

G
Gerd Hoffmann 已提交
2048
        case EST_ADVANCEQUEUE:
2049
            assert(q != NULL);
2050
            again = ehci_state_advqueue(q);
G
Gerd Hoffmann 已提交
2051 2052 2053
            break;

        case EST_FETCHQTD:
2054
            assert(q != NULL);
2055
            again = ehci_state_fetchqtd(q);
G
Gerd Hoffmann 已提交
2056 2057 2058
            break;

        case EST_HORIZONTALQH:
2059
            assert(q != NULL);
2060
            again = ehci_state_horizqh(q);
G
Gerd Hoffmann 已提交
2061 2062 2063
            break;

        case EST_EXECUTE:
2064
            assert(q != NULL);
2065
            again = ehci_state_execute(q);
G
Gerd Hoffmann 已提交
2066 2067 2068
            if (async) {
                ehci->async_stepdown = 0;
            }
G
Gerd Hoffmann 已提交
2069 2070 2071
            break;

        case EST_EXECUTING:
G
Gerd Hoffmann 已提交
2072
            assert(q != NULL);
G
Gerd Hoffmann 已提交
2073 2074 2075
            if (async) {
                ehci->async_stepdown = 0;
            }
2076
            again = ehci_state_executing(q);
G
Gerd Hoffmann 已提交
2077 2078 2079
            break;

        case EST_WRITEBACK:
G
Gerd Hoffmann 已提交
2080
            assert(q != NULL);
2081
            again = ehci_state_writeback(q);
2082 2083 2084
            if (!async) {
                ehci->periodic_sched_active = PERIODIC_ACTIVE;
            }
G
Gerd Hoffmann 已提交
2085 2086 2087 2088 2089
            break;

        default:
            fprintf(stderr, "Bad state!\n");
            again = -1;
2090
            g_assert_not_reached();
G
Gerd Hoffmann 已提交
2091 2092 2093
            break;
        }

2094 2095
        if (again < 0 || itd_count > 16) {
            /* TODO: notify guest (raise HSE irq?) */
G
Gerd Hoffmann 已提交
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105
            fprintf(stderr, "processing error - resetting ehci HC\n");
            ehci_reset(ehci);
            again = 0;
        }
    }
    while (again);
}

static void ehci_advance_async_state(EHCIState *ehci)
{
2106
    const int async = 1;
G
Gerd Hoffmann 已提交
2107

2108
    switch(ehci_get_state(ehci, async)) {
G
Gerd Hoffmann 已提交
2109
    case EST_INACTIVE:
2110
        if (!ehci_async_enabled(ehci)) {
G
Gerd Hoffmann 已提交
2111 2112
            break;
        }
2113
        ehci_set_state(ehci, async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
2114 2115 2116
        // No break, fall through to ACTIVE

    case EST_ACTIVE:
2117
        if (!ehci_async_enabled(ehci)) {
2118
            ehci_queues_rip_all(ehci, async);
2119
            ehci_set_state(ehci, async, EST_INACTIVE);
G
Gerd Hoffmann 已提交
2120 2121 2122
            break;
        }

2123
        /* make sure guest has acknowledged the doorbell interrupt */
G
Gerd Hoffmann 已提交
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
        /* TO-DO: is this really needed? */
        if (ehci->usbsts & USBSTS_IAA) {
            DPRINTF("IAA status bit still set.\n");
            break;
        }

        /* check that address register has been set */
        if (ehci->asynclistaddr == 0) {
            break;
        }

2135 2136
        ehci_set_state(ehci, async, EST_WAITLISTHEAD);
        ehci_advance_state(ehci, async);
2137 2138 2139 2140 2141 2142 2143

        /* If the doorbell is set, the guest wants to make a change to the
         * schedule. The host controller needs to release cached data.
         * (section 4.8.2)
         */
        if (ehci->usbcmd & USBCMD_IAAD) {
            /* Remove all unseen qhs from the async qhs queue */
2144
            ehci_queues_rip_unseen(ehci, async);
G
Gerd Hoffmann 已提交
2145
            trace_usb_ehci_doorbell_ack();
2146
            ehci->usbcmd &= ~USBCMD_IAAD;
2147
            ehci_raise_irq(ehci, USBSTS_IAA);
2148
        }
G
Gerd Hoffmann 已提交
2149 2150 2151 2152 2153 2154
        break;

    default:
        /* this should only be due to a developer mistake */
        fprintf(stderr, "ehci: Bad asynchronous state %d. "
                "Resetting to active\n", ehci->astate);
2155
        g_assert_not_reached();
G
Gerd Hoffmann 已提交
2156 2157 2158 2159 2160 2161 2162
    }
}

static void ehci_advance_periodic_state(EHCIState *ehci)
{
    uint32_t entry;
    uint32_t list;
2163
    const int async = 0;
G
Gerd Hoffmann 已提交
2164 2165 2166

    // 4.6

2167
    switch(ehci_get_state(ehci, async)) {
G
Gerd Hoffmann 已提交
2168
    case EST_INACTIVE:
2169
        if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
2170
            ehci_set_state(ehci, async, EST_ACTIVE);
G
Gerd Hoffmann 已提交
2171 2172 2173 2174 2175
            // No break, fall through to ACTIVE
        } else
            break;

    case EST_ACTIVE:
2176
        if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
2177
            ehci_queues_rip_all(ehci, async);
2178
            ehci_set_state(ehci, async, EST_INACTIVE);
G
Gerd Hoffmann 已提交
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
            break;
        }

        list = ehci->periodiclistbase & 0xfffff000;
        /* check that register has been set */
        if (list == 0) {
            break;
        }
        list |= ((ehci->frindex & 0x1ff8) >> 1);

G
Gerd Hoffmann 已提交
2189 2190 2191
        if (get_dwords(ehci, list, &entry, 1) < 0) {
            break;
        }
G
Gerd Hoffmann 已提交
2192 2193 2194

        DPRINTF("PERIODIC state adv fr=%d.  [%08X] -> %08X\n",
                ehci->frindex / 8, list, entry);
G
Gerd Hoffmann 已提交
2195
        ehci_set_fetch_addr(ehci, async,entry);
2196 2197
        ehci_set_state(ehci, async, EST_FETCHENTRY);
        ehci_advance_state(ehci, async);
2198
        ehci_queues_rip_unused(ehci, async);
G
Gerd Hoffmann 已提交
2199 2200 2201 2202 2203 2204
        break;

    default:
        /* this should only be due to a developer mistake */
        fprintf(stderr, "ehci: Bad periodic state %d. "
                "Resetting to active\n", ehci->pstate);
2205
        g_assert_not_reached();
G
Gerd Hoffmann 已提交
2206 2207 2208
    }
}

2209
static void ehci_update_frindex(EHCIState *ehci, int uframes)
G
Gerd Hoffmann 已提交
2210
{
2211
    if (!ehci_enabled(ehci) && ehci->pstate == EST_INACTIVE) {
G
Gerd Hoffmann 已提交
2212 2213 2214
        return;
    }

2215 2216 2217 2218
    /* Generate FLR interrupt if frame index rolls over 0x2000 */
    if ((ehci->frindex % 0x2000) + uframes >= 0x2000) {
        ehci_raise_irq(ehci, USBSTS_FLR);
    }
G
Gerd Hoffmann 已提交
2219

2220 2221 2222 2223 2224 2225 2226 2227 2228
    /* How many times will frindex roll over 0x4000 with this frame count?
     * usbsts_frindex is decremented by 0x4000 on rollover until it reaches 0
     */
    int rollovers = (ehci->frindex + uframes) / 0x4000;
    if (rollovers > 0) {
        if (ehci->usbsts_frindex >= (rollovers * 0x4000)) {
            ehci->usbsts_frindex -= 0x4000 * rollovers;
        } else {
            ehci->usbsts_frindex = 0;
G
Gerd Hoffmann 已提交
2229 2230
        }
    }
2231 2232

    ehci->frindex = (ehci->frindex + uframes) % 0x4000;
G
Gerd Hoffmann 已提交
2233 2234
}

2235
static void ehci_work_bh(void *opaque)
G
Gerd Hoffmann 已提交
2236 2237
{
    EHCIState *ehci = opaque;
2238
    int need_timer = 0;
G
Gerd Hoffmann 已提交
2239
    int64_t expire_time, t_now;
G
Gerd Hoffmann 已提交
2240
    uint64_t ns_elapsed;
2241
    uint64_t uframes, skipped_uframes;
G
Gerd Hoffmann 已提交
2242 2243
    int i;

2244
    t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
G
Gerd Hoffmann 已提交
2245
    ns_elapsed = t_now - ehci->last_run_ns;
2246
    uframes = ns_elapsed / UFRAME_TIMER_NS;
G
Gerd Hoffmann 已提交
2247

G
Gerd Hoffmann 已提交
2248
    if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
2249
        need_timer++;
G
Gerd Hoffmann 已提交
2250

2251 2252 2253 2254 2255 2256
        if (uframes > (ehci->maxframes * 8)) {
            skipped_uframes = uframes - (ehci->maxframes * 8);
            ehci_update_frindex(ehci, skipped_uframes);
            ehci->last_run_ns += UFRAME_TIMER_NS * skipped_uframes;
            uframes -= skipped_uframes;
            DPRINTF("WARNING - EHCI skipped %d uframes\n", skipped_uframes);
G
Gerd Hoffmann 已提交
2257 2258
        }

2259
        for (i = 0; i < uframes; i++) {
2260 2261 2262
            /*
             * If we're running behind schedule, we should not catch up
             * too fast, as that will make some guests unhappy:
2263
             * 1) We must process a minimum of MIN_UFR_PER_TICK frames,
2264 2265 2266
             *    otherwise we will never catch up
             * 2) Process frames until the guest has requested an irq (IOC)
             */
2267
            if (i >= MIN_UFR_PER_TICK) {
2268 2269 2270 2271 2272
                ehci_commit_irq(ehci);
                if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) {
                    break;
                }
            }
2273 2274 2275
            if (ehci->periodic_sched_active) {
                ehci->periodic_sched_active--;
            }
G
Gerd Hoffmann 已提交
2276
            ehci_update_frindex(ehci, 1);
2277 2278 2279 2280
            if ((ehci->frindex & 7) == 0) {
                ehci_advance_periodic_state(ehci);
            }
            ehci->last_run_ns += UFRAME_TIMER_NS;
G
Gerd Hoffmann 已提交
2281 2282
        }
    } else {
2283
        ehci->periodic_sched_active = 0;
2284 2285
        ehci_update_frindex(ehci, uframes);
        ehci->last_run_ns += UFRAME_TIMER_NS * uframes;
G
Gerd Hoffmann 已提交
2286 2287
    }

2288 2289 2290 2291 2292 2293
    if (ehci->periodic_sched_active) {
        ehci->async_stepdown = 0;
    } else if (ehci->async_stepdown < ehci->maxframes / 2) {
        ehci->async_stepdown++;
    }

G
Gerd Hoffmann 已提交
2294 2295 2296
    /*  Async is not inside loop since it executes everything it can once
     *  called
     */
G
Gerd Hoffmann 已提交
2297
    if (ehci_async_enabled(ehci) || ehci->astate != EST_INACTIVE) {
2298
        need_timer++;
2299
        ehci_advance_async_state(ehci);
G
Gerd Hoffmann 已提交
2300
    }
G
Gerd Hoffmann 已提交
2301

2302 2303 2304 2305
    ehci_commit_irq(ehci);
    if (ehci->usbsts_pending) {
        need_timer++;
        ehci->async_stepdown = 0;
G
Gerd Hoffmann 已提交
2306
    }
2307

2308 2309 2310 2311
    if (ehci_enabled(ehci) && (ehci->usbintr & USBSTS_FLR)) {
        need_timer++;
    }

2312
    if (need_timer) {
2313 2314 2315
        /* If we've raised int, we speed up the timer, so that we quickly
         * notice any new packets queued up in response */
        if (ehci->int_req_by_async && (ehci->usbsts & USBSTS_INT)) {
2316 2317
            expire_time = t_now +
                NANOSECONDS_PER_SECOND / (FRAME_TIMER_FREQ * 4);
2318 2319
            ehci->int_req_by_async = false;
        } else {
2320
            expire_time = t_now + (NANOSECONDS_PER_SECOND
2321
                               * (ehci->async_stepdown+1) / FRAME_TIMER_FREQ);
2322
        }
2323
        timer_mod(ehci->frame_timer, expire_time);
2324
    }
G
Gerd Hoffmann 已提交
2325 2326
}

2327 2328 2329 2330 2331 2332 2333
static void ehci_work_timer(void *opaque)
{
    EHCIState *ehci = opaque;

    qemu_bh_schedule(ehci->async_bh);
}

2334 2335
static const MemoryRegionOps ehci_mmio_caps_ops = {
    .read = ehci_caps_read,
2336
    .write = ehci_caps_write,
2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356
    .valid.min_access_size = 1,
    .valid.max_access_size = 4,
    .impl.min_access_size = 1,
    .impl.max_access_size = 1,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static const MemoryRegionOps ehci_mmio_opreg_ops = {
    .read = ehci_opreg_read,
    .write = ehci_opreg_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static const MemoryRegionOps ehci_mmio_port_ops = {
    .read = ehci_port_read,
    .write = ehci_port_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
A
Avi Kivity 已提交
2357
    .endianness = DEVICE_LITTLE_ENDIAN,
G
Gerd Hoffmann 已提交
2358 2359 2360 2361 2362
};

static USBPortOps ehci_port_ops = {
    .attach = ehci_attach,
    .detach = ehci_detach,
2363
    .child_detach = ehci_child_detach,
2364
    .wakeup = ehci_wakeup,
G
Gerd Hoffmann 已提交
2365 2366 2367
    .complete = ehci_async_complete_packet,
};

2368
static USBBusOps ehci_bus_ops_companion = {
2369
    .register_companion = ehci_register_companion,
2370
    .wakeup_endpoint = ehci_wakeup_endpoint,
2371
};
2372 2373 2374
static USBBusOps ehci_bus_ops_standalone = {
    .wakeup_endpoint = ehci_wakeup_endpoint,
};
2375

2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
static void usb_ehci_pre_save(void *opaque)
{
    EHCIState *ehci = opaque;
    uint32_t new_frindex;

    /* Round down frindex to a multiple of 8 for migration compatibility */
    new_frindex = ehci->frindex & ~7;
    ehci->last_run_ns -= (ehci->frindex - new_frindex) * UFRAME_TIMER_NS;
    ehci->frindex = new_frindex;
}

G
Gerd Hoffmann 已提交
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406
static int usb_ehci_post_load(void *opaque, int version_id)
{
    EHCIState *s = opaque;
    int i;

    for (i = 0; i < NB_PORTS; i++) {
        USBPort *companion = s->companion_ports[i];
        if (companion == NULL) {
            continue;
        }
        if (s->portsc[i] & PORTSC_POWNER) {
            companion->dev = s->ports[i].dev;
        } else {
            companion->dev = NULL;
        }
    }

    return 0;
}

2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432
static void usb_ehci_vm_state_change(void *opaque, int running, RunState state)
{
    EHCIState *ehci = opaque;

    /*
     * We don't migrate the EHCIQueue-s, instead we rebuild them for the
     * schedule in guest memory. We must do the rebuilt ASAP, so that
     * USB-devices which have async handled packages have a packet in the
     * ep queue to match the completion with.
     */
    if (state == RUN_STATE_RUNNING) {
        ehci_advance_async_state(ehci);
    }

    /*
     * The schedule rebuilt from guest memory could cause the migration dest
     * to miss a QH unlink, and fail to cancel packets, since the unlinked QH
     * will never have existed on the destination. Therefor we must flush the
     * async schedule on savevm to catch any not yet noticed unlinks.
     */
    if (state == RUN_STATE_SAVE_VM) {
        ehci_advance_async_state(ehci);
        ehci_queues_rip_unseen(ehci, 1);
    }
}

2433
const VMStateDescription vmstate_ehci = {
P
Peter Crosthwaite 已提交
2434
    .name        = "ehci-core",
2435 2436
    .version_id  = 2,
    .minimum_version_id  = 1,
2437
    .pre_save    = usb_ehci_pre_save,
G
Gerd Hoffmann 已提交
2438
    .post_load   = usb_ehci_post_load,
2439
    .fields = (VMStateField[]) {
G
Gerd Hoffmann 已提交
2440 2441 2442
        /* mmio registers */
        VMSTATE_UINT32(usbcmd, EHCIState),
        VMSTATE_UINT32(usbsts, EHCIState),
2443 2444
        VMSTATE_UINT32_V(usbsts_pending, EHCIState, 2),
        VMSTATE_UINT32_V(usbsts_frindex, EHCIState, 2),
G
Gerd Hoffmann 已提交
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457
        VMSTATE_UINT32(usbintr, EHCIState),
        VMSTATE_UINT32(frindex, EHCIState),
        VMSTATE_UINT32(ctrldssegment, EHCIState),
        VMSTATE_UINT32(periodiclistbase, EHCIState),
        VMSTATE_UINT32(asynclistaddr, EHCIState),
        VMSTATE_UINT32(configflag, EHCIState),
        VMSTATE_UINT32(portsc[0], EHCIState),
        VMSTATE_UINT32(portsc[1], EHCIState),
        VMSTATE_UINT32(portsc[2], EHCIState),
        VMSTATE_UINT32(portsc[3], EHCIState),
        VMSTATE_UINT32(portsc[4], EHCIState),
        VMSTATE_UINT32(portsc[5], EHCIState),
        /* frame timer */
2458
        VMSTATE_TIMER_PTR(frame_timer, EHCIState),
G
Gerd Hoffmann 已提交
2459 2460 2461 2462 2463 2464 2465 2466 2467
        VMSTATE_UINT64(last_run_ns, EHCIState),
        VMSTATE_UINT32(async_stepdown, EHCIState),
        /* schedule state */
        VMSTATE_UINT32(astate, EHCIState),
        VMSTATE_UINT32(pstate, EHCIState),
        VMSTATE_UINT32(a_fetch_addr, EHCIState),
        VMSTATE_UINT32(p_fetch_addr, EHCIState),
        VMSTATE_END_OF_LIST()
    }
G
Gerd Hoffmann 已提交
2468 2469
};

2470
void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
G
Gerd Hoffmann 已提交
2471 2472 2473
{
    int i;

2474 2475 2476 2477 2478 2479
    if (s->portnr > NB_PORTS) {
        error_setg(errp, "Too many ports! Max. port number is %d.",
                   NB_PORTS);
        return;
    }

2480 2481
    usb_bus_new(&s->bus, sizeof(s->bus), s->companion_enable ?
                &ehci_bus_ops_companion : &ehci_bus_ops_standalone, dev);
2482
    for (i = 0; i < s->portnr; i++) {
2483 2484 2485 2486 2487
        usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
                          USB_SPEED_MASK_HIGH);
        s->ports[i].dev = 0;
    }

2488 2489
    s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_work_timer, s);
    s->async_bh = qemu_bh_new(ehci_work_bh, s);
2490
    s->device = dev;
2491

2492
    s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
2493 2494
}

G
Gonglei 已提交
2495 2496
void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp)
{
G
Gonglei 已提交
2497 2498
    trace_usb_ehci_unrealize();

G
Gonglei 已提交
2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
    if (s->frame_timer) {
        timer_del(s->frame_timer);
        timer_free(s->frame_timer);
        s->frame_timer = NULL;
    }
    if (s->async_bh) {
        qemu_bh_delete(s->async_bh);
    }

    ehci_queues_rip_all(s, 0);
    ehci_queues_rip_all(s, 1);

    memory_region_del_subregion(&s->mem, &s->mem_caps);
    memory_region_del_subregion(&s->mem, &s->mem_opreg);
    memory_region_del_subregion(&s->mem, &s->mem_ports);

    usb_bus_release(&s->bus);

    if (s->vmstate) {
        qemu_del_vm_change_state_handler(s->vmstate);
    }
}

2522 2523
void usb_ehci_init(EHCIState *s, DeviceState *dev)
{
2524
    /* 2.2 host controller interface version */
2525
    s->caps[0x00] = (uint8_t)(s->opregbase - s->capsbase);
2526 2527 2528
    s->caps[0x01] = 0x00;
    s->caps[0x02] = 0x00;
    s->caps[0x03] = 0x01;        /* HC version */
2529
    s->caps[0x04] = s->portnr;   /* Number of downstream ports */
2530 2531 2532 2533 2534 2535
    s->caps[0x05] = 0x00;        /* No companion ports at present */
    s->caps[0x06] = 0x00;
    s->caps[0x07] = 0x00;
    s->caps[0x08] = 0x80;        /* We can cache whole frame, no 64-bit */
    s->caps[0x0a] = 0x00;
    s->caps[0x0b] = 0x00;
G
Gerd Hoffmann 已提交
2536

2537 2538
    QTAILQ_INIT(&s->aqueues);
    QTAILQ_INIT(&s->pqueues);
2539
    usb_packet_init(&s->ipacket);
G
Gerd Hoffmann 已提交
2540

2541 2542
    memory_region_init(&s->mem, OBJECT(dev), "ehci", MMIO_SIZE);
    memory_region_init_io(&s->mem_caps, OBJECT(dev), &ehci_mmio_caps_ops, s,
2543
                          "capabilities", CAPA_SIZE);
2544
    memory_region_init_io(&s->mem_opreg, OBJECT(dev), &ehci_mmio_opreg_ops, s,
2545
                          "operational", s->portscbase);
2546
    memory_region_init_io(&s->mem_ports, OBJECT(dev), &ehci_mmio_port_ops, s,
2547
                          "ports", 4 * s->portnr);
2548

2549 2550
    memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps);
    memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg);
2551
    memory_region_add_subregion(&s->mem, s->opregbase + s->portscbase,
2552
                                &s->mem_ports);
P
Peter Crosthwaite 已提交
2553 2554
}

L
Li Qiang 已提交
2555 2556 2557 2558 2559
void usb_ehci_finalize(EHCIState *s)
{
    usb_packet_cleanup(&s->ipacket);
}

G
Gerd Hoffmann 已提交
2560 2561 2562
/*
 * vim: expandtab ts=4
 */