/* disable root hub */ static void uhci_rh_disable_port (usbdev_t *dev, int port) { hci_t *controller = dev->controller; if (port == 1) port = PORTSC1; else if (port == 2) port = PORTSC2; else { usb_debug("Invalid port %d\n", port); return; } uhci_reg_write16(controller, port, uhci_reg_read16(controller, port) & ~4); u16 value; /* wait for controller to disable port */ /* TOTEST: how long to wait? 100ms for now */ int timeout = 200; /* time out after 200 * 500us == 100ms */ do { value = uhci_reg_read16 (controller, port); udelay(500); timeout--; } while (((value & (1 << 2)) != 0) && timeout); if (!timeout) usb_debug("Warning: uhci_rh: port disabling timed out.\n"); }
static void uhci_rh_scanport (usbdev_t *dev, int port) { int portsc, offset; if (port == 1) { portsc = PORTSC1; offset = 0; } else if (port == 2) { portsc = PORTSC2; offset = 1; } else { usb_debug("Invalid port %d\n", port); return; } int devno = RH_INST (dev)->port[offset]; if ((dev->controller->devices[devno] != 0) && (devno != -1)) { usb_detach_device(dev->controller, devno); RH_INST (dev)->port[offset] = -1; } uhci_reg_write16(dev->controller, portsc, uhci_reg_read16(dev->controller, portsc) | (1 << 3) | (1 << 2)); // clear port state change, enable port mdelay(100); // wait for signal to stabilize if ((uhci_reg_read16 (dev->controller, portsc) & 1) != 0) { // device attached uhci_rh_disable_port (dev, port); uhci_rh_enable_port (dev, port); int speed = ((uhci_reg_read16 (dev->controller, portsc) >> 8) & 1); RH_INST (dev)->port[offset] = usb_attach_device(dev->controller, dev->address, portsc, speed); }
static void uhci_reset (hci_t *controller) { /* reset */ uhci_reg_write16 (controller, USBCMD, 4); mdelay (50); uhci_reg_write16 (controller, USBCMD, 0); mdelay (10); uhci_reg_write16 (controller, USBCMD, 2); while ((uhci_reg_read16 (controller, USBCMD) & 2) != 0) mdelay (1); uhci_reg_write32 (controller, FLBASEADD, (u32) virt_to_phys (UHCI_INST (controller)-> framelistptr)); //debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr); /* disable irqs */ uhci_reg_write16 (controller, USBINTR, 0); /* reset framelist index */ uhci_reg_write16 (controller, FRNUM, 0); uhci_reg_mask16 (controller, USBCMD, ~0, 0xc0); // max packets, configure flag uhci_start (controller); }
static void uhci_rh_enable_port (usbdev_t *dev, int port) { u16 value; hci_t *controller = dev->controller; if (port == 1) port = PORTSC1; else if (port == 2) port = PORTSC2; else { debug("Invalid port %d\n", port); return; } uhci_reg_mask16 (controller, port, ~(1 << 12), 0); /* wakeup */ uhci_reg_mask16 (controller, port, ~0, 1 << 9); /* reset */ mdelay (30); // >10ms uhci_reg_mask16 (controller, port, ~(1 << 9), 0); mdelay (1); // >5.3us per spec, <3ms because some devices make trouble uhci_reg_mask16 (controller, port, ~0, 1 << 2); /* enable */ do { value = uhci_reg_read16 (controller, port); mdelay (1); } while (((value & (1 << 2)) == 0) && (value & 0x01)); }
/* disable root hub */ static void uhci_rh_disable_port (usbdev_t *dev, int port) { hci_t *controller = dev->controller; port = PORTSC2; if (port == 1) port = PORTSC1; uhci_reg_mask16 (controller, port, ~4, 0); int value; do { value = uhci_reg_read16 (controller, port); mdelay (1); } while ((value & (1 << 2)) != 0); }
static void uhci_rh_enable_port (usbdev_t *dev, int port) { u16 value; hci_t *controller = dev->controller; if (port == 1) port = PORTSC1; else if (port == 2) port = PORTSC2; else { usb_debug("Invalid port %d\n", port); return; } uhci_reg_write16(controller, port, uhci_reg_read16(controller, port) & ~(1 << 12)); /* wakeup */ uhci_reg_write16(controller, port, uhci_reg_read16(controller, port) | 1 << 9); /* reset */ mdelay (30); // >10ms uhci_reg_write16(controller, port, uhci_reg_read16(controller, port) & ~(1 << 9)); mdelay (1); // >5.3us per spec, <3ms because some devices make trouble uhci_reg_write16(controller, port, uhci_reg_read16(controller, port) | 1 << 2); /* enable */ /* wait for controller to enable port */ /* TOTEST: how long to wait? 100ms for now */ int timeout = 200; /* time out after 200 * 500us == 100ms */ do { value = uhci_reg_read16 (controller, port); udelay(500); timeout--; } while (((value & (1 << 2)) == 0) && (value & 0x01) && timeout); if (!timeout) usb_debug("Warning: uhci_rh: port enabling timed out.\n"); }
static td_t * wait_for_completed_qh (hci_t *controller, qh_t *qh) { int timeout = 1000; /* max 30 ms. */ void *current = GET_TD (qh->elementlinkptr); while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) { if (current != GET_TD (qh->elementlinkptr)) { current = GET_TD (qh->elementlinkptr); timeout = 1000; } uhci_reg_write16(controller, USBSTS, uhci_reg_read16(controller, USBSTS) | 0); // clear resettable registers udelay (30); } return (GET_TD (qh->elementlinkptr) == 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr)); }
static void uhci_reset (hci_t *controller) { /* reset */ uhci_reg_write16 (controller, USBCMD, 4); /* Global Reset */ mdelay (50); /* uhci spec 2.1.1: at least 10ms */ uhci_reg_write16 (controller, USBCMD, 0); mdelay (10); uhci_reg_write16 (controller, USBCMD, 2); /* Host Controller Reset */ /* wait for controller to finish reset */ /* TOTEST: how long to wait? 100ms for now */ int timeout = 200; /* time out after 200 * 500us == 100ms */ while (((uhci_reg_read16 (controller, USBCMD) & 2) != 0) && timeout--) udelay (500); if (timeout < 0) usb_debug ("Warning: uhci: host controller reset timed out.\n"); }
/* dump uhci */ static void uhci_dump (hci_t *controller) { usb_debug ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD)); usb_debug ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS)); usb_debug ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR)); usb_debug ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM)); usb_debug ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD)); usb_debug ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD)); usb_debug ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1)); usb_debug ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2)); }
static void uhci_shutdown (hci_t *controller) { if (controller == 0) return; detach_controller (controller); UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)-> roothub); uhci_reg_write16(controller, USBCMD, uhci_reg_read16(controller, USBCMD) & 0); // stop work free (UHCI_INST (controller)->framelistptr); free (UHCI_INST (controller)->qh_prei); free (UHCI_INST (controller)->qh_intr); free (UHCI_INST (controller)->qh_data); free (UHCI_INST (controller)->qh_last); free (UHCI_INST (controller)); free (controller); }
static void uhci_reinit (hci_t *controller) { uhci_reg_write32 (controller, FLBASEADD, (u32) virt_to_phys (UHCI_INST (controller)-> framelistptr)); //usb_debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr); /* disable irqs */ uhci_reg_write16 (controller, USBINTR, 0); /* reset framelist index */ uhci_reg_write16 (controller, FRNUM, 0); uhci_reg_write16(controller, USBCMD, uhci_reg_read16(controller, USBCMD) | 0xc0); // max packets, configure flag uhci_start (controller); }
static void uhci_stop (hci_t *controller) { uhci_reg_write16(controller, USBCMD, uhci_reg_read16(controller, USBCMD) & ~1); // stop work on schedule }
void uhci_reg_mask16 (hci_t *ctrl, usbreg reg, u16 andmask, u16 ormask) { uhci_reg_write16 (ctrl, reg, (uhci_reg_read16 (ctrl, reg) & andmask) | ormask); }