static void usb_hub_port_setup(void *data) { struct usbdevice_s *usbdev = data; struct usbhub_s *hub = usbdev->hub; u32 port = usbdev->port; for (;;) { // Detect if device present (and possibly start reset) int ret = hub->op->detect(hub, port); if (ret > 0) // Device connected. break; if (ret < 0 || timer_check(hub->detectend)) // No device found. goto done; msleep(5); } // XXX - wait USB_TIME_ATTDB time? // Reset port and determine device speed mutex_lock(&hub->cntl->resetlock); int ret = hub->op->reset(hub, port); if (ret < 0) // Reset failed goto resetfail; usbdev->speed = ret; // Set address of port ret = usb_set_address(usbdev); if (ret) { hub->op->disconnect(hub, port); goto resetfail; } mutex_unlock(&hub->cntl->resetlock); // Configure the device int count = configure_usb_device(usbdev); usb_free_pipe(usbdev, usbdev->defpipe); if (!count) hub->op->disconnect(hub, port); hub->devcount += count; done: hub->threads--; free(usbdev); return; resetfail: mutex_unlock(&hub->cntl->resetlock); goto done; }
// Find any devices connected to the root hub. static int check_ohci_ports(struct usb_s *cntl) { // Turn on power for all devices on roothub. u32 rha = readl(&cntl->ohci.regs->roothub_a); rha &= ~(RH_A_PSM | RH_A_OCPM); writel(&cntl->ohci.regs->roothub_status, RH_HS_LPSC); writel(&cntl->ohci.regs->roothub_b, RH_B_PPCM); msleep((rha >> 24) * 2); // Count and reset connected devices int ports = rha & RH_A_NDP; int totalcount = 0; int i; for (i=0; i<ports; i++) if (readl(&cntl->ohci.regs->roothub_portstatus[i]) & RH_PS_CCS) { writel(&cntl->ohci.regs->roothub_portstatus[i], RH_PS_PRS); totalcount++; } if (!totalcount) // No devices connected goto shutdown; msleep(60); // XXX - should poll instead of using timer. totalcount = 0; for (i=0; i<ports; i++) { u32 sts = readl(&cntl->ohci.regs->roothub_portstatus[i]); if ((sts & (RH_PS_CCS|RH_PS_PES)) == (RH_PS_CCS|RH_PS_PES)) { int count = configure_usb_device(cntl, !!(sts & RH_PS_LSDA)); if (! count) // Shutdown port writel(&cntl->ohci.regs->roothub_portstatus[i] , RH_PS_CCS|RH_PS_LSDA); totalcount += count; } } if (!totalcount) goto shutdown; return totalcount; shutdown: // Turn off power to all ports writel(&cntl->ohci.regs->roothub_status, RH_HS_LPS); return 0; }