Revision 439a97cc hw/usb-ehci.c

b/hw/usb-ehci.c
30 30
#include "usb.h"
31 31
#include "pci.h"
32 32
#include "monitor.h"
33
#include "trace.h"
33 34

  
34 35
#define EHCI_DEBUG   0
35 36
#define STATE_DEBUG  0       /* state transitions  */
......
417 418
    } while(0)
418 419

  
419 420

  
420
#if EHCI_DEBUG
421
static const char *addr2str(unsigned addr)
421
static const char *addr2str(target_phys_addr_t addr)
422 422
{
423
    const char *r            = "   unknown";
423
    const char *r            = "unknown";
424 424
    const char *n[] = {
425
        [ CAPLENGTH ]        = " CAPLENGTH",
425
        [ CAPLENGTH ]        = "CAPLENGTH",
426 426
        [ HCIVERSION ]       = "HCIVERSION",
427
        [ HCSPARAMS ]        = " HCSPARAMS",
428
        [ HCCPARAMS ]        = " HCCPARAMS",
429
        [ USBCMD ]           = "   COMMAND",
430
        [ USBSTS ]           = "    STATUS",
431
        [ USBINTR ]          = " INTERRUPT",
432
        [ FRINDEX ]          = " FRAME IDX",
427
        [ HCSPARAMS ]        = "HCSPARAMS",
428
        [ HCCPARAMS ]        = "HCCPARAMS",
429
        [ USBCMD ]           = "USBCMD",
430
        [ USBSTS ]           = "USBSTS",
431
        [ USBINTR ]          = "USBINTR",
432
        [ FRINDEX ]          = "FRINDEX",
433 433
        [ PERIODICLISTBASE ] = "P-LIST BASE",
434 434
        [ ASYNCLISTADDR ]    = "A-LIST ADDR",
435 435
        [ PORTSC_BEGIN ...
436
          PORTSC_END ]       = "PORT STATUS",
437
        [ CONFIGFLAG ]       = "CONFIG FLAG",
436
          PORTSC_END ]       = "PORTSC",
437
        [ CONFIGFLAG ]       = "CONFIGFLAG",
438 438
    };
439 439

  
440 440
    if (addr < ARRAY_SIZE(n) && n[addr] != NULL) {
......
443 443
        return r;
444 444
    }
445 445
}
446
#endif
447 446

  
447
static void ehci_trace_usbsts(uint32_t mask, int state)
448
{
449
    /* interrupts */
450
    if (mask & USBSTS_INT) {
451
        trace_usb_ehci_usbsts("INT", state);
452
    }
453
    if (mask & USBSTS_ERRINT) {
454
        trace_usb_ehci_usbsts("ERRINT", state);
455
    }
456
    if (mask & USBSTS_PCD) {
457
        trace_usb_ehci_usbsts("PCD", state);
458
    }
459
    if (mask & USBSTS_FLR) {
460
        trace_usb_ehci_usbsts("FLR", state);
461
    }
462
    if (mask & USBSTS_HSE) {
463
        trace_usb_ehci_usbsts("HSE", state);
464
    }
465
    if (mask & USBSTS_IAA) {
466
        trace_usb_ehci_usbsts("IAA", state);
467
    }
468

  
469
    /* status */
470
    if (mask & USBSTS_HALT) {
471
        trace_usb_ehci_usbsts("HALT", state);
472
    }
473
    if (mask & USBSTS_REC) {
474
        trace_usb_ehci_usbsts("REC", state);
475
    }
476
    if (mask & USBSTS_PSS) {
477
        trace_usb_ehci_usbsts("PSS", state);
478
    }
479
    if (mask & USBSTS_ASS) {
480
        trace_usb_ehci_usbsts("ASS", state);
481
    }
482
}
483

  
484
static inline void ehci_set_usbsts(EHCIState *s, int mask)
485
{
486
    if ((s->usbsts & mask) == mask) {
487
        return;
488
    }
489
    ehci_trace_usbsts(mask, 1);
490
    s->usbsts |= mask;
491
}
492

  
493
static inline void ehci_clear_usbsts(EHCIState *s, int mask)
494
{
495
    if ((s->usbsts & mask) == 0) {
496
        return;
497
    }
498
    ehci_trace_usbsts(mask, 0);
499
    s->usbsts &= ~mask;
500
}
448 501

  
449 502
static inline void ehci_set_interrupt(EHCIState *s, int intr)
450 503
{
......
452 505

  
453 506
    // TODO honour interrupt threshold requests
454 507

  
455
    s->usbsts |= intr;
508
    ehci_set_usbsts(s, intr);
456 509

  
457 510
    if ((s->usbsts & USBINTR_MASK) & s->usbintr) {
458 511
        level = 1;
......
526 579
    uint8_t *pci_conf;
527 580
    int i;
528 581

  
582
    trace_usb_ehci_reset();
529 583
    pci_conf = s->dev.config;
530 584

  
531 585
    memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
......
576 630
    val = s->mmio[addr] | (s->mmio[addr+1] << 8) |
577 631
          (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24);
578 632

  
633
    trace_usb_ehci_mmio_readl(addr, addr2str(addr), val);
579 634
    return val;
580 635
}
581 636

  
......
645 700
{
646 701
    EHCIState *s = ptr;
647 702
    int i;
648
#if EHCI_DEBUG
649
    const char *str;
650
#endif
703

  
704
    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val,
705
                               *(uint32_t *)(&s->mmio[addr]));
651 706

  
652 707
    /* Only aligned reads are allowed on OHCI */
653 708
    if (addr & 3) {
......
669 724

  
670 725

  
671 726
    /* Do any register specific pre-write processing here.  */
672
#if EHCI_DEBUG
673
    str = addr2str((unsigned) addr);
674
#endif
675 727
    switch(addr) {
676 728
    case USBCMD:
677
        DPRINTF("ehci_mem_writel: USBCMD val=0x%08X, current cmd=0x%08X\n",
678
                val, s->usbcmd);
679

  
680 729
        if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
681
            DPRINTF("ehci_mem_writel: %s run, clear halt\n", str);
682 730
            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
683 731
            SET_LAST_RUN_CLOCK(s);
684
            s->usbsts &= ~USBSTS_HALT;
732
            ehci_clear_usbsts(s, USBSTS_HALT);
685 733
        }
686 734

  
687 735
        if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
688
            DPRINTF("                         ** STOP **\n");
689 736
            qemu_del_timer(s->frame_timer);
690 737
            // TODO - should finish out some stuff before setting halt
691
            s->usbsts |= USBSTS_HALT;
738
            ehci_set_usbsts(s, USBSTS_HALT);
692 739
        }
693 740

  
694 741
        if (val & USBCMD_HCRESET) {
695
            DPRINTF("ehci_mem_writel: %s run, resetting\n", str);
696 742
            ehci_reset(s);
697 743
            val &= ~USBCMD_HCRESET;
698 744
        }
......
703 749
                    val & USBCMD_FLS);
704 750
            val &= ~USBCMD_FLS;
705 751
        }
706
#if EHCI_DEBUG
707
        if ((val & USBCMD_PSE) && !(s->usbcmd & USBCMD_PSE)) {
708
            DPRINTF("periodic scheduling enabled\n");
709
        }
710
        if (!(val & USBCMD_PSE) && (s->usbcmd & USBCMD_PSE)) {
711
            DPRINTF("periodic scheduling disabled\n");
712
        }
713
        if ((val & USBCMD_ASE) && !(s->usbcmd & USBCMD_ASE)) {
714
            DPRINTF("asynchronous scheduling enabled\n");
715
        }
716
        if (!(val & USBCMD_ASE) && (s->usbcmd & USBCMD_ASE)) {
717
            DPRINTF("asynchronous scheduling disabled\n");
718
        }
719
        if ((val & USBCMD_IAAD) && !(s->usbcmd & USBCMD_IAAD)) {
720
            DPRINTF("doorbell request received\n");
721
        }
722
        if ((val & USBCMD_LHCR) && !(s->usbcmd & USBCMD_LHCR)) {
723
            DPRINTF("light host controller reset received\n");
724
        }
725
        if ((val & USBCMD_ITC) != (s->usbcmd & USBCMD_ITC)) {
726
            DPRINTF("interrupt threshold control set to %x\n",
727
                    (val & USBCMD_ITC)>>USBCMD_ITC_SH);
728
        }
729
#endif
730 752
        break;
731 753

  
732

  
733 754
    case USBSTS:
734 755
        val &= USBSTS_RO_MASK;              // bits 6 thru 31 are RO
735
        DPRINTF("ehci_mem_writel: %s RWC set to 0x%08X\n", str, val);
736

  
737
        val = (s->usbsts &= ~val);         // bits 0 thru 5 are R/WC
738

  
739
        DPRINTF("ehci_mem_writel: %s updating interrupt condition\n", str);
756
        ehci_clear_usbsts(s, val);          // bits 0 thru 5 are R/WC
757
        val = s->usbsts;
740 758
        ehci_set_interrupt(s, 0);
741 759
        break;
742 760

  
743

  
744 761
    case USBINTR:
745 762
        val &= USBINTR_MASK;
746
        DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val);
747 763
        break;
748 764

  
749 765
    case FRINDEX:
750 766
        s->sofv = val >> 3;
751
        DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val);
752 767
        break;
753 768

  
754 769
    case CONFIGFLAG:
755
        DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val);
756 770
        val &= 0x1;
757 771
        if (val) {
758 772
            for(i = 0; i < NB_PORTS; i++)
......
766 780
              "ehci: PERIODIC list base register set while periodic schedule\n"
767 781
              "      is enabled and HC is enabled\n");
768 782
        }
769
        DPRINTF("ehci_mem_writel: P-LIST BASE set to 0x%08X\n", val);
770 783
        break;
771 784

  
772 785
    case ASYNCLISTADDR:
......
775 788
              "ehci: ASYNC list address register set while async schedule\n"
776 789
              "      is enabled and HC is enabled\n");
777 790
        }
778
        DPRINTF("ehci_mem_writel: A-LIST ADDR set to 0x%08X\n", val);
779 791
        break;
780 792
    }
781 793

  
......
1227 1239

  
1228 1240
    /* set reclamation flag at start event (4.8.6) */
1229 1241
    if (async) {
1230
        ehci->usbsts |= USBSTS_REC;
1242
        ehci_set_usbsts(ehci, USBSTS_REC);
1231 1243
    }
1232 1244

  
1233 1245
    /*  Find the head of the list (4.9.1.1) */
......
1334 1346

  
1335 1347
        /*  EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */
1336 1348
        if (ehci->usbsts & USBSTS_REC) {
1337
            ehci->usbsts &= ~USBSTS_REC;
1349
            ehci_clear_usbsts(ehci, USBSTS_REC);
1338 1350
        } else {
1339 1351
            DPRINTF("FETCHQH:  QH 0x%08x. H-bit set, reclamation status reset"
1340 1352
                       " - done processing\n", ehci->qhaddr);
......
1534 1546
    }
1535 1547

  
1536 1548
    if (async) {
1537
        ehci->usbsts |= USBSTS_REC;
1549
        ehci_set_usbsts(ehci, USBSTS_REC);
1538 1550
    }
1539 1551

  
1540 1552
    ehci->exec_status = ehci_execute(ehci, qh);
......
1734 1746
        if (!(ehci->usbcmd & USBCMD_ASE)) {
1735 1747
            break;
1736 1748
        }
1737
        ehci->usbsts |= USBSTS_ASS;
1749
        ehci_set_usbsts(ehci, USBSTS_ASS);
1738 1750
        ehci->astate = EST_ACTIVE;
1739 1751
        // No break, fall through to ACTIVE
1740 1752

  
1741 1753
    case EST_ACTIVE:
1742 1754
        if ( !(ehci->usbcmd & USBCMD_ASE)) {
1743
            ehci->usbsts &= ~USBSTS_ASS;
1755
            ehci_clear_usbsts(ehci, USBSTS_ASS);
1744 1756
            ehci->astate = EST_INACTIVE;
1745 1757
            break;
1746 1758
        }
......
1800 1812
    switch(ehci->pstate) {
1801 1813
    case EST_INACTIVE:
1802 1814
        if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
1803
            DPRINTF("PERIODIC going active\n");
1804
            ehci->usbsts |= USBSTS_PSS;
1815
            ehci_set_usbsts(ehci, USBSTS_PSS);
1805 1816
            ehci->pstate = EST_ACTIVE;
1806 1817
            // No break, fall through to ACTIVE
1807 1818
        } else
......
1809 1820

  
1810 1821
    case EST_ACTIVE:
1811 1822
        if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
1812
            DPRINTF("PERIODIC going inactive\n");
1813
            ehci->usbsts &= ~USBSTS_PSS;
1823
            ehci_clear_usbsts(ehci, USBSTS_PSS);
1814 1824
            ehci->pstate = EST_INACTIVE;
1815 1825
            break;
1816 1826
        }

Also available in: Unified diff