diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index f63519ecf949ee5316623aa09256d7db79b2bc6b..16fbca6b9dfbb89a69a8091cfb294393d33098e9 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -30,6 +30,7 @@ #include "usb.h" #include "pci.h" #include "monitor.h" +#include "trace.h" #define EHCI_DEBUG 0 #define STATE_DEBUG 0 /* state transitions */ @@ -417,24 +418,23 @@ typedef struct { } while(0) -#if EHCI_DEBUG -static const char *addr2str(unsigned addr) +static const char *addr2str(target_phys_addr_t addr) { - const char *r = " unknown"; + const char *r = "unknown"; const char *n[] = { - [ CAPLENGTH ] = " CAPLENGTH", + [ CAPLENGTH ] = "CAPLENGTH", [ HCIVERSION ] = "HCIVERSION", - [ HCSPARAMS ] = " HCSPARAMS", - [ HCCPARAMS ] = " HCCPARAMS", - [ USBCMD ] = " COMMAND", - [ USBSTS ] = " STATUS", - [ USBINTR ] = " INTERRUPT", - [ FRINDEX ] = " FRAME IDX", + [ HCSPARAMS ] = "HCSPARAMS", + [ HCCPARAMS ] = "HCCPARAMS", + [ USBCMD ] = "USBCMD", + [ USBSTS ] = "USBSTS", + [ USBINTR ] = "USBINTR", + [ FRINDEX ] = "FRINDEX", [ PERIODICLISTBASE ] = "P-LIST BASE", [ ASYNCLISTADDR ] = "A-LIST ADDR", [ PORTSC_BEGIN ... - PORTSC_END ] = "PORT STATUS", - [ CONFIGFLAG ] = "CONFIG FLAG", + PORTSC_END ] = "PORTSC", + [ CONFIGFLAG ] = "CONFIGFLAG", }; if (addr < ARRAY_SIZE(n) && n[addr] != NULL) { @@ -443,8 +443,61 @@ static const char *addr2str(unsigned addr) return r; } } -#endif +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; +} static inline void ehci_set_interrupt(EHCIState *s, int intr) { @@ -452,7 +505,7 @@ static inline void ehci_set_interrupt(EHCIState *s, int intr) // TODO honour interrupt threshold requests - s->usbsts |= intr; + ehci_set_usbsts(s, intr); if ((s->usbsts & USBINTR_MASK) & s->usbintr) { level = 1; @@ -526,6 +579,7 @@ static void ehci_reset(void *opaque) uint8_t *pci_conf; int i; + trace_usb_ehci_reset(); pci_conf = s->dev.config; memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE); @@ -576,6 +630,7 @@ static uint32_t ehci_mem_readl(void *ptr, target_phys_addr_t addr) val = s->mmio[addr] | (s->mmio[addr+1] << 8) | (s->mmio[addr+2] << 16) | (s->mmio[addr+3] << 24); + trace_usb_ehci_mmio_readl(addr, addr2str(addr), val); return val; } @@ -645,9 +700,9 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) { EHCIState *s = ptr; int i; -#if EHCI_DEBUG - const char *str; -#endif + + trace_usb_ehci_mmio_writel(addr, addr2str(addr), val, + *(uint32_t *)(&s->mmio[addr])); /* Only aligned reads are allowed on OHCI */ if (addr & 3) { @@ -669,30 +724,21 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) /* Do any register specific pre-write processing here. */ -#if EHCI_DEBUG - str = addr2str((unsigned) addr); -#endif switch(addr) { case USBCMD: - DPRINTF("ehci_mem_writel: USBCMD val=0x%08X, current cmd=0x%08X\n", - val, s->usbcmd); - if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) { - DPRINTF("ehci_mem_writel: %s run, clear halt\n", str); qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); SET_LAST_RUN_CLOCK(s); - s->usbsts &= ~USBSTS_HALT; + ehci_clear_usbsts(s, USBSTS_HALT); } if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) { - DPRINTF(" ** STOP **\n"); qemu_del_timer(s->frame_timer); // TODO - should finish out some stuff before setting halt - s->usbsts |= USBSTS_HALT; + ehci_set_usbsts(s, USBSTS_HALT); } if (val & USBCMD_HCRESET) { - DPRINTF("ehci_mem_writel: %s run, resetting\n", str); ehci_reset(s); val &= ~USBCMD_HCRESET; } @@ -703,56 +749,24 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) val & USBCMD_FLS); val &= ~USBCMD_FLS; } -#if EHCI_DEBUG - if ((val & USBCMD_PSE) && !(s->usbcmd & USBCMD_PSE)) { - DPRINTF("periodic scheduling enabled\n"); - } - if (!(val & USBCMD_PSE) && (s->usbcmd & USBCMD_PSE)) { - DPRINTF("periodic scheduling disabled\n"); - } - if ((val & USBCMD_ASE) && !(s->usbcmd & USBCMD_ASE)) { - DPRINTF("asynchronous scheduling enabled\n"); - } - if (!(val & USBCMD_ASE) && (s->usbcmd & USBCMD_ASE)) { - DPRINTF("asynchronous scheduling disabled\n"); - } - if ((val & USBCMD_IAAD) && !(s->usbcmd & USBCMD_IAAD)) { - DPRINTF("doorbell request received\n"); - } - if ((val & USBCMD_LHCR) && !(s->usbcmd & USBCMD_LHCR)) { - DPRINTF("light host controller reset received\n"); - } - if ((val & USBCMD_ITC) != (s->usbcmd & USBCMD_ITC)) { - DPRINTF("interrupt threshold control set to %x\n", - (val & USBCMD_ITC)>>USBCMD_ITC_SH); - } -#endif break; - case USBSTS: val &= USBSTS_RO_MASK; // bits 6 thru 31 are RO - DPRINTF("ehci_mem_writel: %s RWC set to 0x%08X\n", str, val); - - val = (s->usbsts &= ~val); // bits 0 thru 5 are R/WC - - DPRINTF("ehci_mem_writel: %s updating interrupt condition\n", str); + ehci_clear_usbsts(s, val); // bits 0 thru 5 are R/WC + val = s->usbsts; ehci_set_interrupt(s, 0); break; - case USBINTR: val &= USBINTR_MASK; - DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val); break; case FRINDEX: s->sofv = val >> 3; - DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val); break; case CONFIGFLAG: - DPRINTF("ehci_mem_writel: %s set to 0x%08X\n", str, val); val &= 0x1; if (val) { for(i = 0; i < NB_PORTS; i++) @@ -766,7 +780,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) "ehci: PERIODIC list base register set while periodic schedule\n" " is enabled and HC is enabled\n"); } - DPRINTF("ehci_mem_writel: P-LIST BASE set to 0x%08X\n", val); break; case ASYNCLISTADDR: @@ -775,7 +788,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) "ehci: ASYNC list address register set while async schedule\n" " is enabled and HC is enabled\n"); } - DPRINTF("ehci_mem_writel: A-LIST ADDR set to 0x%08X\n", val); break; } @@ -1227,7 +1239,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async, int *state) /* set reclamation flag at start event (4.8.6) */ if (async) { - ehci->usbsts |= USBSTS_REC; + ehci_set_usbsts(ehci, USBSTS_REC); } /* Find the head of the list (4.9.1.1) */ @@ -1334,7 +1346,7 @@ static int ehci_state_fetchqh(EHCIState *ehci, int async, int *state) /* EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */ if (ehci->usbsts & USBSTS_REC) { - ehci->usbsts &= ~USBSTS_REC; + ehci_clear_usbsts(ehci, USBSTS_REC); } else { DPRINTF("FETCHQH: QH 0x%08x. H-bit set, reclamation status reset" " - done processing\n", ehci->qhaddr); @@ -1534,7 +1546,7 @@ static int ehci_state_execute(EHCIState *ehci, int async, int *state) } if (async) { - ehci->usbsts |= USBSTS_REC; + ehci_set_usbsts(ehci, USBSTS_REC); } ehci->exec_status = ehci_execute(ehci, qh); @@ -1734,13 +1746,13 @@ static void ehci_advance_async_state(EHCIState *ehci) if (!(ehci->usbcmd & USBCMD_ASE)) { break; } - ehci->usbsts |= USBSTS_ASS; + ehci_set_usbsts(ehci, USBSTS_ASS); ehci->astate = EST_ACTIVE; // No break, fall through to ACTIVE case EST_ACTIVE: if ( !(ehci->usbcmd & USBCMD_ASE)) { - ehci->usbsts &= ~USBSTS_ASS; + ehci_clear_usbsts(ehci, USBSTS_ASS); ehci->astate = EST_INACTIVE; break; } @@ -1800,8 +1812,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) switch(ehci->pstate) { case EST_INACTIVE: if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) { - DPRINTF("PERIODIC going active\n"); - ehci->usbsts |= USBSTS_PSS; + ehci_set_usbsts(ehci, USBSTS_PSS); ehci->pstate = EST_ACTIVE; // No break, fall through to ACTIVE } else @@ -1809,8 +1820,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) case EST_ACTIVE: if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) { - DPRINTF("PERIODIC going inactive\n"); - ehci->usbsts &= ~USBSTS_PSS; + ehci_clear_usbsts(ehci, USBSTS_PSS); ehci->pstate = EST_INACTIVE; break; } diff --git a/trace-events b/trace-events index e0e9574d21fc3d614d2b7c4e7348f59fd5d09135..c87a86ef351616cdc016cbffb54433317d7afbaa 100644 --- a/trace-events +++ b/trace-events @@ -194,6 +194,12 @@ disable sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "g disable sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x" disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64"" +# hw/usb-ehci.c +disable usb_ehci_reset(void) "=== RESET ===" +disable usb_ehci_mmio_readl(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x" +disable usb_ehci_mmio_writel(uint32_t addr, const char *str, uint32_t val, uint32_t oldval) "wr mmio %04x [%s] = %x (old: %x)" +disable usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d" + # hw/usb-desc.c disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"