Revision c6432634

b/hw/usb/hcd-ehci.c
438 438
    return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
439 439
}
440 440

  
441
static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh)
442
{
443
    uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR);
444
    uint32_t endp    = get_field(qh->epchar, QH_EPCHAR_EP);
445
    if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
446
        (endp    != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
447
        (qh->current_qtd != q->qh.current_qtd) ||
448
        (q->async && qh->next_qtd != q->qh.next_qtd) ||
449
        (memcmp(&qh->altnext_qtd, &q->qh.altnext_qtd,
450
                                 7 * sizeof(uint32_t)) != 0) ||
451
        (q->dev != NULL && q->dev->addr != devaddr)) {
452
        return false;
453
    } else {
454
        return true;
455
    }
456
}
457

  
458
static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd)
459
{
460
    if (p->qtdaddr != p->queue->qtdaddr ||
461
        (p->queue->async && !NLPTR_TBIT(p->qtd.next) &&
462
            (p->qtd.next != qtd->next)) ||
463
        (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) ||
464
        p->qtd.bufptr[0] != qtd->bufptr[0]) {
465
        return false;
466
    } else {
467
        return true;
468
    }
469
}
470

  
441 471
/* Finish executing and writeback a packet outside of the regular
442 472
   fetchqh -> fetchqtd -> execute -> writeback cycle */
443 473
static void ehci_writeback_async_complete_packet(EHCIPacket *p)
......
1557 1587

  
1558 1588
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
1559 1589
{
1590
    uint32_t entry;
1560 1591
    EHCIPacket *p;
1561
    uint32_t entry, devaddr, endp;
1562 1592
    EHCIQueue *q;
1563 1593
    EHCIqh qh;
1564 1594

  
......
1588 1618
     * The overlay area of the qh should never be changed by the guest,
1589 1619
     * except when idle, in which case the reset is a nop.
1590 1620
     */
1591
    devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR);
1592
    endp    = get_field(qh.epchar, QH_EPCHAR_EP);
1593
    if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
1594
        (endp    != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
1595
        (qh.current_qtd != q->qh.current_qtd) ||
1596
        (q->async && qh.next_qtd != q->qh.next_qtd) ||
1597
        (memcmp(&qh.altnext_qtd, &q->qh.altnext_qtd,
1598
                                 7 * sizeof(uint32_t)) != 0) ||
1599
        (q->dev != NULL && q->dev->addr != devaddr)) {
1621
    if (!ehci_verify_qh(q, &qh)) {
1600 1622
        if (ehci_reset_queue(q) > 0) {
1601 1623
            ehci_trace_guest_bug(ehci, "guest updated active QH");
1602 1624
        }
......
1610 1632
    }
1611 1633

  
1612 1634
    if (q->dev == NULL) {
1613
        q->dev = ehci_find_device(q->ehci, devaddr);
1635
        q->dev = ehci_find_device(q->ehci,
1636
                                  get_field(q->qh.epchar, QH_EPCHAR_DEVADDR));
1614 1637
    }
1615 1638

  
1616 1639
    if (p && p->async == EHCI_ASYNC_FINISHED) {
......
1768 1791

  
1769 1792
    p = QTAILQ_FIRST(&q->packets);
1770 1793
    if (p != NULL) {
1771
        if (p->qtdaddr != q->qtdaddr ||
1772
            (q->async && !NLPTR_TBIT(p->qtd.next) &&
1773
                (p->qtd.next != qtd.next)) ||
1774
            (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
1775
            p->qtd.bufptr[0] != qtd.bufptr[0]) {
1794
        if (!ehci_verify_qtd(p, &qtd)) {
1776 1795
            ehci_cancel_queue(q);
1777 1796
            ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
1778 1797
            p = NULL;

Also available in: Unified diff