/** Initialize UHCI hc hw resources. * * @param[in] instance UHCI structure to use. * For magic values see UHCI Design Guide */ void hc_init_hw(const hc_t *instance) { assert(instance); uhci_regs_t *registers = instance->registers; /* Reset everything, who knows what touched it before us */ pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); async_usleep(50000); /* 50ms according to USB spec(root hub reset) */ pio_write_16(®isters->usbcmd, 0); /* Reset hc, all states and counters. Hope that hw is not broken */ pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); do { async_usleep(10); } while ((pio_read_16(®isters->usbcmd) & UHCI_CMD_HCRESET) != 0); /* Set frame to exactly 1ms */ pio_write_8(®isters->sofmod, 64); /* Set frame list pointer */ const uint32_t pa = addr_to_phys(instance->frame_list); pio_write_32(®isters->flbaseadd, pa); if (instance->hw_interrupts) { /* Enable all interrupts, but resume interrupt */ pio_write_16(&instance->registers->usbintr, UHCI_INTR_ALLOW_INTERRUPTS); } const uint16_t cmd = pio_read_16(®isters->usbcmd); if (cmd != 0) usb_log_warning("Previous command value: %x.\n", cmd); /* Start the hc with large(64B) packet FSBR */ pio_write_16(®isters->usbcmd, UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); }
/** Polling function, emulates interrupts. * * @param[in] arg UHCI hc structure to use. * @return EOK (should never return) */ int hc_interrupt_emulator(void* arg) { usb_log_debug("Started interrupt emulator.\n"); hc_t *instance = arg; assert(instance); while (1) { /* Read and clear status register */ uint16_t status = pio_read_16(&instance->registers->usbsts); pio_write_16(&instance->registers->usbsts, status); if (status != 0) usb_log_debug2("UHCI status: %x.\n", status); hc_interrupt(instance, status); async_usleep(UHCI_INT_EMULATOR_TIMEOUT); } return EOK; }
void hda_reg16_write(uint16_t *r, uint16_t val) { pio_write_16(r, host2uint16_t_le(val)); }