static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) { EHCIState *s = ptr; uint32_t *mmio = (uint32_t *)(&s->mmio[addr]); uint32_t old = *mmio; int i; trace_usb_ehci_mmio_writel(addr, addr2str(addr), val); /* Only aligned reads are allowed on OHCI */ if (addr & 3) { fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x" TARGET_FMT_plx "\n", addr); return; } if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) { handle_port_status_write(s, (addr-PORTSC)/4, val); trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); return; } if (addr < OPREGBASE) { fprintf(stderr, "usb-ehci: write attempt to read-only register" TARGET_FMT_plx "\n", addr); return; } /* Do any register specific pre-write processing here. */ switch(addr) { case USBCMD: if (val & USBCMD_HCRESET) { ehci_reset(s); val = s->usbcmd; break; } if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) != ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) { if (!ehci_enabled(s)) { qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock)); SET_LAST_RUN_CLOCK(s); } ehci_update_halt(s); } /* 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", val & USBCMD_FLS); val &= ~USBCMD_FLS; } break; case USBSTS: val &= USBSTS_RO_MASK; // bits 6 through 31 are RO ehci_clear_usbsts(s, val); // bits 0 through 5 are R/WC val = s->usbsts; ehci_set_interrupt(s, 0); break; case USBINTR: val &= USBINTR_MASK; break; case FRINDEX: val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */ break; case CONFIGFLAG: val &= 0x1; if (val) { for(i = 0; i < NB_PORTS; i++) handle_port_owner_write(s, i, 0); } break; case PERIODICLISTBASE: if (ehci_periodic_enabled(s)) { fprintf(stderr, "ehci: PERIODIC list base register set while periodic schedule\n" " is enabled and HC is enabled\n"); } break; case ASYNCLISTADDR: if (ehci_async_enabled(s)) { fprintf(stderr, "ehci: ASYNC list address register set while async schedule\n" " is enabled and HC is enabled\n"); } break; } *mmio = val; trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old); }