static int ehci_pci_resume(device_t self) { ehci_softc_t *sc = device_get_softc(self); ehci_pci_takecontroller(self); ehci_power(PWR_RESUME, sc); bus_generic_resume(self); return 0; }
int ehci_pci_activate(struct device *self, int act) { struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self; /* On resume, take ownership from the BIOS */ switch (act) { case DVACT_RESUME: ehci_pci_takecontroller(sc, 1); break; } return ehci_activate(self, act); }
int ehci_pci_activate(struct device *self, int act) { struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self; int rv; switch (act) { case DVACT_RESUME: ehci_pci_takecontroller(sc, 1); break; } rv = ehci_activate(self, act); #if 0 switch (act) { case DVACT_POWERDOWN: ehci_pci_givecontroller(sc); break; } #endif return (rv); }
void ehci_pci_attach(struct device *parent, struct device *self, void *aux) { struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; char const *intrstr; pci_intr_handle_t ih; const char *vendor; char *devname = sc->sc.sc_bus.bdev.dv_xname; usbd_status r; int s; /* Map I/O registers */ if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0, &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size, 0)) { printf(": can't map mem space\n"); return; } sc->sc_pc = pc; sc->sc_tag = tag; sc->sc.sc_bus.dmatag = pa->pa_dmat; /* Disable interrupts, so we don't get any spurious ones. */ s = splhardusb(); sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); DPRINTF(("%s: offs=%d\n", devname, sc->sc.sc_offs)); EOWRITE2(&sc->sc, EHCI_USBINTR, 0); /* Handle quirks */ switch (PCI_VENDOR(pa->pa_id)) { case PCI_VENDOR_ATI: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_EHCI || (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB700_EHCI && pci_find_device(NULL, ehci_sb700_match))) { pcireg_t value; /* apply the ATI SB600/SB700 workaround */ value = pci_conf_read(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG); pci_conf_write(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG, value | EHCI_SBx00_WORKAROUND_ENABLE); } break; case PCI_VENDOR_VIATECH: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT6202 && (PCI_REVISION(pa->pa_class) & 0xf0) == 0x60) { pcireg_t value; /* * The VT6202 defaults to a 1 usec EHCI sleep time * which hogs the PCI bus *badly*. Setting bit 5 of * the register makes that sleep time use the conventional * 10 usec. */ value = pci_conf_read(sc->sc_pc, sc->sc_tag, EHCI_VT6202_WORKAROUND_REG); pci_conf_write(sc->sc_pc, sc->sc_tag, EHCI_VT6202_WORKAROUND_REG, value | 0x20000000); } break; } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); goto unmap_ret; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB | IPL_MPSAFE, ehci_intr, sc, devname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto unmap_ret; } printf(": %s\n", intrstr); switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) { case PCI_USBREV_PRE_1_0: case PCI_USBREV_1_0: case PCI_USBREV_1_1: sc->sc.sc_bus.usbrev = USBREV_UNKNOWN; printf("%s: pre-2.0 USB rev\n", devname); goto disestablish_ret; case PCI_USBREV_2_0: sc->sc.sc_bus.usbrev = USBREV_2_0; break; default: sc->sc.sc_bus.usbrev = USBREV_UNKNOWN; break; } /* Figure out vendor for root hub descriptor. */ vendor = pci_findvendor(pa->pa_id); sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id); if (vendor) strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor)); else snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor), "vendor 0x%04x", PCI_VENDOR(pa->pa_id)); /* Enable workaround for dropped interrupts as required */ if (sc->sc.sc_id_vendor == PCI_VENDOR_VIATECH) sc->sc.sc_flags |= EHCIF_DROPPED_INTR_WORKAROUND; ehci_pci_takecontroller(sc, 0); r = ehci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { printf("%s: init failed, error=%d\n", devname, r); goto disestablish_ret; } /* Attach usb device. */ config_found(self, &sc->sc.sc_bus, usbctlprint); splx(s); return; disestablish_ret: pci_intr_disestablish(sc->sc_pc, sc->sc_ih); unmap_ret: bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); splx(s); }
static int ehci_pci_attach(device_t self) { ehci_softc_t *sc = device_get_softc(self); devclass_t dc; device_t parent; device_t *neighbors; device_t *nbus; struct usbd_bus *bsc; int err; int rid; int ncomp; int count, buscount; int slot, function; int res; int i; switch(pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) { case PCI_USBREV_PRE_1_0: case PCI_USBREV_1_0: case PCI_USBREV_1_1: device_printf(self, "pre-2.0 USB rev\n"); if (pci_get_devid(self) == PCI_EHCI_DEVICEID_CS5536) { sc->sc_bus.usbrev = USBREV_2_0; device_printf(self, "Quirk for CS5536 USB 2.0 enabled\n"); break; } sc->sc_bus.usbrev = USBREV_UNKNOWN; return ENXIO; case PCI_USBREV_2_0: sc->sc_bus.usbrev = USBREV_2_0; break; default: sc->sc_bus.usbrev = USBREV_UNKNOWN; break; } pci_enable_busmaster(self); rid = PCI_CBMEM; sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->io_res) { device_printf(self, "Could not map memory\n"); return ENXIO; } sc->iot = rman_get_bustag(sc->io_res); sc->ioh = rman_get_bushandle(sc->io_res); rid = 0; sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); ehci_pci_detach(self); return ENXIO; } sc->sc_bus.bdev = device_add_child(self, "usb", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); ehci_pci_detach(self); return ENOMEM; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); /* ehci_pci_match will never return NULL if ehci_pci_probe succeeded */ device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self)); switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_ACERLABS: sprintf(sc->sc_vendor, "AcerLabs"); break; case PCI_EHCI_VENDORID_AMD: sprintf(sc->sc_vendor, "AMD"); break; case PCI_EHCI_VENDORID_APPLE: sprintf(sc->sc_vendor, "Apple"); break; case PCI_EHCI_VENDORID_ATI: sprintf(sc->sc_vendor, "ATI"); break; case PCI_EHCI_VENDORID_CMDTECH: sprintf(sc->sc_vendor, "CMDTECH"); break; case PCI_EHCI_VENDORID_INTEL: sprintf(sc->sc_vendor, "Intel"); break; case PCI_EHCI_VENDORID_NEC: sprintf(sc->sc_vendor, "NEC"); break; case PCI_EHCI_VENDORID_OPTI: sprintf(sc->sc_vendor, "OPTi"); break; case PCI_EHCI_VENDORID_SIS: sprintf(sc->sc_vendor, "SiS"); break; case PCI_EHCI_VENDORID_NVIDIA: case PCI_EHCI_VENDORID_NVIDIA2: sprintf(sc->sc_vendor, "nVidia"); break; case PCI_EHCI_VENDORID_VIA: sprintf(sc->sc_vendor, "VIA"); break; default: if (bootverbose) device_printf(self, "(New EHCI DeviceId=0x%08x)\n", pci_get_devid(self)); sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); } err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, NULL, (driver_intr_t *)ehci_intr, sc, &sc->ih); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->ih = NULL; ehci_pci_detach(self); return ENXIO; } /* Enable workaround for dropped interrupts as required */ switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_ATI: case PCI_EHCI_VENDORID_VIA: sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG; if (bootverbose) device_printf(self, "Dropped interrupts workaround enabled\n"); break; default: break; } /* * Find companion controllers. According to the spec they always * have lower function numbers so they should be enumerated already. */ parent = device_get_parent(self); res = device_get_children(parent, &neighbors, &count); if (res != 0) { device_printf(self, "Error finding companion busses\n"); ehci_pci_detach(self); return ENXIO; } ncomp = 0; dc = devclass_find("usb"); slot = pci_get_slot(self); function = pci_get_function(self); for (i = 0; i < count; i++) { if (pci_get_slot(neighbors[i]) == slot && \ pci_get_function(neighbors[i]) < function) { res = device_get_children(neighbors[i], &nbus, &buscount); if (res != 0) continue; if (buscount != 1) { free(nbus, M_TEMP); continue; } if (device_get_devclass(nbus[0]) != dc) { free(nbus, M_TEMP); continue; } bsc = device_get_softc(nbus[0]); free(nbus, M_TEMP); DPRINTF(("ehci_pci_attach: companion %s\n", device_get_nameunit(bsc->bdev))); sc->sc_comps[ncomp++] = bsc; if (ncomp >= EHCI_COMPANION_MAX) break; } } sc->sc_ncomp = ncomp; /* Allocate a parent dma tag for DMA maps */ err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_bus.parent_dmatag); if (err) { device_printf(self, "Could not allocate parent DMA tag (%d)\n", err); ehci_pci_detach(self); return ENXIO; } /* Allocate a dma tag for transfer buffers */ err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); if (err) { device_printf(self, "Could not allocate buffer DMA tag (%d)\n", err); ehci_pci_detach(self); return ENXIO; } ehci_pci_takecontroller(self); err = ehci_init(sc); if (!err) { sc->sc_flags |= EHCI_SCFLG_DONEINIT; err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(self, "USB init failed err=%d\n", err); ehci_pci_detach(self); return EIO; } return 0; }