static int ig4iic_acpi_detach(device_t dev) { ig4iic_softc_t *sc = device_get_softc(dev); int error; if (sc->pci_attached) { error = ig4iic_detach(sc); if (error) return error; sc->pci_attached = 0; } if (sc->intr_res) { bus_release_resource(dev, SYS_RES_IRQ, sc->intr_rid, sc->intr_res); sc->intr_res = NULL; } if (sc->regs_res) { bus_release_resource(dev, SYS_RES_MEMORY, sc->regs_rid, sc->regs_res); sc->regs_res = NULL; } sc->regs_t = 0; sc->regs_h = 0; pci_set_powerstate(dev, PCI_POWERSTATE_D3); return 0; }
static int atiixp_pci_suspend(device_t dev) { struct atiixp_info *sc = pcm_getdevinfo(dev); uint32_t value; /* quickly disable interrupts and save channels active state */ atiixp_lock(sc); atiixp_disable_interrupts(sc); value = atiixp_rd(sc, ATI_REG_CMD); sc->pch.active = (value & ATI_REG_CMD_SEND_EN) ? 1 : 0; sc->rch.active = (value & ATI_REG_CMD_RECEIVE_EN) ? 1 : 0; atiixp_unlock(sc); /* stop everything */ if (sc->pch.channel && sc->pch.active) atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP); if (sc->rch.channel && sc->rch.active) atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP); /* power down aclink and pci bus */ atiixp_lock(sc); value = atiixp_rd(sc, ATI_REG_CMD); value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET; atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN); pci_set_powerstate(dev, PCI_POWERSTATE_D3); atiixp_unlock(sc); return 0; }
static int vga_pci_set_powerstate(device_t dev, device_t child, int state) { device_printf(dev, "child %s requested pci_set_powerstate\n", device_get_nameunit(child)); return (pci_set_powerstate(dev, state)); }
static int rtw_pci_attach(device_t dev) { struct rtw_softc *sc = device_get_softc(dev); struct rtw_regs *regs = &sc->sc_regs; int i, error; /* * No power management hooks. * XXX Maybe we should add some! */ sc->sc_flags |= RTW_F_ENABLED; sc->sc_rev = pci_get_revid(dev); #ifndef BURN_BRIDGES if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { uint32_t mem, port, irq; mem = pci_read_config(dev, RTW_PCI_MMBA, 4); port = pci_read_config(dev, RTW_PCI_IOBA, 4); irq = pci_read_config(dev, PCIR_INTLINE, 4); device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); pci_write_config(dev, RTW_PCI_MMBA, mem, 4); pci_write_config(dev, RTW_PCI_IOBA, port, 4); pci_write_config(dev, PCIR_INTLINE, irq, 4); } #endif /* !BURN_BRIDGES */ /* Enable PCI bus master */ pci_enable_busmaster(dev); /* Allocate IO memory/port */ for (i = 0; i < NELEM(rtw_pci_regs); ++i) { regs->r_rid = rtw_pci_regs[i].reg_rid; regs->r_type = rtw_pci_regs[i].reg_type; regs->r_res = bus_alloc_resource_any(dev, regs->r_type, ®s->r_rid, RF_ACTIVE); if (regs->r_res != NULL) break; } if (regs->r_res == NULL) { device_printf(dev, "can't allocate IO mem/port\n"); return ENXIO; } regs->r_bh = rman_get_bushandle(regs->r_res); regs->r_bt = rman_get_bustag(regs->r_res); error = rtw_attach(dev); if (error) rtw_pci_detach(dev); return error; }
static int ral_pci_attach(device_t dev) { struct ral_pci_softc *psc = device_get_softc(dev); struct rt2560_softc *sc = &psc->u.sc_rt2560; int error; if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); } /* enable bus-mastering */ pci_enable_busmaster(dev); psc->sc_opns = (pci_get_device(dev) == 0x0201) ? &ral_rt2560_opns : &ral_rt2661_opns; psc->mem_rid = RAL_PCI_BAR0; psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid, RF_ACTIVE); if (psc->mem == NULL) { device_printf(dev, "could not allocate memory resource\n"); return ENXIO; } sc->sc_st = rman_get_bustag(psc->mem); sc->sc_sh = rman_get_bushandle(psc->mem); sc->sc_invalid = 1; psc->irq_rid = 0; psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid, RF_ACTIVE | RF_SHAREABLE); if (psc->irq == NULL) { device_printf(dev, "could not allocate interrupt resource\n"); return ENXIO; } error = (*psc->sc_opns->attach)(dev, pci_get_device(dev)); if (error != 0) return error; /* * Hook our interrupt after all initialization is complete. */ error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, psc->sc_opns->intr, psc, &psc->sc_ih); if (error != 0) { device_printf(dev, "could not set up interrupt\n"); return error; } sc->sc_invalid = 0; return 0; }
void rtsx_pci_attach(struct device *parent, struct device *self, void *aux) { struct rtsx_pci_softc *sc = (struct rtsx_pci_softc *)self; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; char const *intrstr; bus_space_tag_t iot; bus_space_handle_t ioh; bus_size_t size; int flags; if ((pci_conf_read(pa->pa_pc, pa->pa_tag, RTSX_CFG_PCI) & RTSX_CFG_ASIC) != 0) { printf("%s: no asic\n", sc->sc.sc_dev.dv_xname); return; } if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC, rtsx_intr, sc, sc->sc.sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt\n"); return; } printf(": %s\n", intrstr); if (pci_mem_find(pa->pa_pc, pa->pa_tag, RTSX_PCI_BAR, NULL, NULL, NULL) != 0) { printf("%s: can't find registers\n", sc->sc.sc_dev.dv_xname); return; } if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0, &iot, &ioh, NULL, &size, 0)) { printf("%s: can't map registers\n", sc->sc.sc_dev.dv_xname); return; } pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209) flags = RTSX_F_5209; else flags = RTSX_F_5229; if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0) printf("%s: can't initialize chip\n", sc->sc.sc_dev.dv_xname); }
int acpi_pci_suspend(device_t dev) { int dstate, error, i, numdevs; device_t acpi_dev, child, *devlist; struct pci_devinfo *dinfo; acpi_dev = devclass_get_device(devclass_find("acpi"), 0); device_get_children(dev, &devlist, &numdevs); /* * Save the PCI configuration space for each child and set the * device in the appropriate power state for this sleep state. */ for (i = 0; i < numdevs; i++) { child = devlist[i]; dinfo = (struct pci_devinfo *)device_get_ivars(child); pci_cfg_save(child, dinfo, 0); } /* * Suspend devices before potentially powering them down. */ error = bus_generic_suspend(dev); if (error) { kfree(devlist, M_TEMP); return (error); } /* * Always set the device to D3. If ACPI suggests a different * power state, use it instead. If ACPI is not present, the * firmware is responsible for managing device power. Skip * children who aren't attached since they are powered down * separately. Only manage type 0 devices for now. */ for (i = 0; acpi_dev && i < numdevs; i++) { child = devlist[i]; dinfo = (struct pci_devinfo *)device_get_ivars(child); if (device_is_attached(child) && dinfo->cfg.hdrtype == 0) { dstate = PCI_POWERSTATE_D3; ACPI_PWR_FOR_SLEEP(acpi_dev, child, &dstate); pci_set_powerstate(child, dstate); } } kfree(devlist, M_TEMP); return (0); }
static int ohci_pci_take_controller(device_t self) { uint32_t reg; uint32_t int_line; if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { device_printf(self, "chip is in D%d mode " "-- setting to D0\n", pci_get_powerstate(self)); reg = pci_read_config(self, PCI_CBMEM, 4); int_line = pci_read_config(self, PCIR_INTLINE, 4); pci_set_powerstate(self, PCI_POWERSTATE_D0); pci_write_config(self, PCI_CBMEM, reg, 4); pci_write_config(self, PCIR_INTLINE, int_line, 4); } return (0); }
static int atiixp_pci_resume(device_t dev) { struct atiixp_info *sc = pcm_getdevinfo(dev); atiixp_lock(sc); /* power up pci bus */ pci_set_powerstate(dev, PCI_POWERSTATE_D0); pci_enable_io(dev, SYS_RES_MEMORY); pci_enable_busmaster(dev); /* reset / power up aclink */ atiixp_reset_aclink(sc); atiixp_unlock(sc); if (mixer_reinit(dev) == -1) { device_printf(dev, "unable to reinitialize the mixer\n"); return ENXIO; } /* * Resume channel activities. Reset channel format regardless * of its previous state. */ if (sc->pch.channel) { if (sc->pch.fmt) atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt); if (sc->pch.active) atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START); } if (sc->rch.channel) { if (sc->rch.fmt) atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt); if (sc->rch.active) atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START); } /* enable interrupts */ atiixp_lock(sc); atiixp_enable_interrupts(sc); atiixp_unlock(sc); return 0; }
static int ohci_pci_resume(device_t self) { ohci_softc_t *sc = device_get_softc(self); uint32_t reg, int_line; if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { device_printf(self, "chip is in D%d mode " "-- setting to D0\n", pci_get_powerstate(self)); reg = pci_read_config(self, PCI_CBMEM, 4); int_line = pci_read_config(self, PCIR_INTLINE, 4); pci_set_powerstate(self, PCI_POWERSTATE_D0); pci_write_config(self, PCI_CBMEM, reg, 4); pci_write_config(self, PCIR_INTLINE, int_line, 4); } ohci_resume(sc); bus_generic_resume(self); return (0); }
static int ig4iic_acpi_attach(device_t dev) { ig4iic_softc_t *sc = device_get_softc(dev); int error; lwkt_serialize_init(&sc->slz); sc->dev = dev; /* All the HIDs matched are Atom SOCs. */ sc->version = IG4_ATOM; sc->regs_rid = 0; sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regs_rid, RF_ACTIVE); if (sc->regs_res == NULL) { device_printf(dev, "unable to map registers"); ig4iic_acpi_detach(dev); return (ENXIO); } sc->intr_rid = 0; sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->intr_rid, RF_ACTIVE); if (sc->intr_res == NULL) { device_printf(dev, "unable to map interrupt"); ig4iic_acpi_detach(dev); return (ENXIO); } sc->regs_t = rman_get_bustag(sc->regs_res); sc->regs_h = rman_get_bushandle(sc->regs_res); sc->pci_attached = 1; /* power up the controller */ pci_set_powerstate(dev, PCI_POWERSTATE_D0); error = ig4iic_attach(sc); if (error) ig4iic_acpi_detach(dev); return error; }
/* * Still need this because the pci code only does power for type 0 * header devices. */ static void cbb_powerstate_d0(device_t dev) { u_int32_t membase, irq; if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { /* Save important PCI config data. */ membase = pci_read_config(dev, CBBR_SOCKBASE, 4); irq = pci_read_config(dev, PCIR_INTLINE, 4); /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); /* Restore PCI config data. */ pci_write_config(dev, CBBR_SOCKBASE, membase, 4); pci_write_config(dev, PCIR_INTLINE, irq, 4); } }
void pcidevdetached(device_t self, device_t child) { struct pci_softc *sc = device_private(self); int d, f; pcitag_t tag; struct pci_child *c; d = device_locator(child, PCICF_DEV); f = device_locator(child, PCICF_FUNCTION); c = &sc->PCI_SC_DEVICESC(d, f); KASSERT(c->c_dev == child); tag = pci_make_tag(sc->sc_pc, sc->sc_bus, d, f); if (c->c_psok) pci_set_powerstate(sc->sc_pc, tag, c->c_powerstate); pci_conf_restore(sc->sc_pc, tag, &c->c_conf); c->c_dev = NULL; }
int pci_activate(pci_chipset_tag_t pc, pcitag_t tag, device_t dev, int (*wakefun)(pci_chipset_tag_t, pcitag_t, device_t, pcireg_t)) { pcireg_t pmode; int error; if ((error = pci_get_powerstate(pc, tag, &pmode))) return error; switch (pmode) { case PCI_PMCSR_STATE_D0: break; case PCI_PMCSR_STATE_D3: if (wakefun == NULL) { /* * The card has lost all configuration data in * this state, so punt. */ aprint_error_dev(dev, "unable to wake up from power state D3\n"); return EOPNOTSUPP; } /*FALLTHROUGH*/ default: if (wakefun) { error = (*wakefun)(pc, tag, dev, pmode); if (error) return error; } aprint_normal_dev(dev, "waking up from power state D%d\n", pmode); if ((error = pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0))) return error; } return 0; }
static int ohci_pci_resume(device_t self) { ohci_softc_t *sc = device_get_softc(self); #ifndef BURN_BRIDGES uint32_t reg, int_line; if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) { device_printf(self, "chip is in D%d mode " "-- setting to D0\n", pci_get_powerstate(self)); reg = pci_read_config(self, PCI_CBMEM, 4); int_line = pci_read_config(self, PCIR_INTLINE, 4); pci_set_powerstate(self, PCI_POWERSTATE_D0); pci_write_config(self, PCI_CBMEM, reg, 4); pci_write_config(self, PCIR_INTLINE, int_line, 4); } #endif /* !BURN_BRIDGES */ ohci_power(PWR_RESUME, sc); bus_generic_resume(self); return 0; }
int acpi_pci_resume(device_t dev) { int i, numdevs; device_t acpi_dev, child, *devlist; struct pci_devinfo *dinfo; acpi_dev = devclass_get_device(devclass_find("acpi"), 0); device_get_children(dev, &devlist, &numdevs); /* * Set each child to D0 and restore its PCI configuration space. */ for (i = 0; i < numdevs; i++) { /* * Notify ACPI we're going to D0 but ignore the result. If * ACPI is not present, the firmware is responsible for * managing device power. Only manage type 0 devices for now. */ child = devlist[i]; dinfo = (struct pci_devinfo *) device_get_ivars(child); if (acpi_dev && device_is_attached(child) && dinfo->cfg.hdrtype == 0) { ACPI_PWR_FOR_SLEEP(acpi_dev, child, NULL); pci_set_powerstate(child, PCI_POWERSTATE_D0); } /* * Now the device is powered up, restore its config space. */ pci_cfg_restore(child, dinfo); } kfree(devlist, M_TEMP); return (bus_generic_resume(dev)); }
static int atiixp_pci_attach(device_t dev) { struct atiixp_info *sc; int i; sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); sc->dev = dev; /* * Default DMA segments per playback / recording channel */ sc->dma_segs = ATI_IXP_DMA_CHSEGS; pci_set_powerstate(dev, PCI_POWERSTATE_D0); pci_enable_busmaster(dev); sc->regid = PCIR_BAR(0); sc->regtype = SYS_RES_MEMORY; sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid, RF_ACTIVE); if (!sc->reg) { device_printf(dev, "unable to allocate register space\n"); goto bad; } sc->st = rman_get_bustag(sc->reg); sc->sh = rman_get_bushandle(sc->reg); sc->bufsz = pcm_getbuffersize(dev, 4096, ATI_IXP_DEFAULT_BUFSZ, 65536); sc->irqid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, RF_ACTIVE | RF_SHAREABLE); if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, atiixp_intr, sc, &sc->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } /* * Let the user choose the best DMA segments. */ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "dma_segs", &i) == 0) { if (i < ATI_IXP_DMA_CHSEGS_MIN) i = ATI_IXP_DMA_CHSEGS_MIN; if (i > ATI_IXP_DMA_CHSEGS_MAX) i = ATI_IXP_DMA_CHSEGS_MAX; sc->dma_segs = i; } /* * round the value to the nearest ^2 */ i = 0; while (sc->dma_segs >> i) i++; sc->dma_segs = 1 << (i - 1); if (sc->dma_segs < ATI_IXP_DMA_CHSEGS_MIN) sc->dma_segs = ATI_IXP_DMA_CHSEGS_MIN; else if (sc->dma_segs > ATI_IXP_DMA_CHSEGS_MAX) sc->dma_segs = ATI_IXP_DMA_CHSEGS_MAX; /* * DMA tag for scatter-gather buffers and link pointers */ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, &sc->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/sc->dma_segs * ATI_IXP_NCHANS * sizeof(struct atiixp_dma_op), /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, &sc->sgd_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table, BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1) goto bad; if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table, sc->dma_segs * ATI_IXP_NCHANS * sizeof(struct atiixp_dma_op), atiixp_dma_cb, sc, 0)) goto bad; atiixp_chip_pre_init(sc); sc->delayed_attach.ich_func = atiixp_chip_post_init; sc->delayed_attach.ich_arg = sc; sc->delayed_attach.ich_desc = "snd_atiixp"; if (cold == 0 || config_intrhook_establish(&sc->delayed_attach) != 0) { sc->delayed_attach.ich_func = NULL; atiixp_chip_post_init(sc); } return 0; bad: atiixp_release_resource(sc); return ENXIO; }
void sf_pci_attach(struct device *parent, struct device *self, void *aux) { struct sf_pci_softc *psc = (void *) self; struct sf_softc *sc = &psc->sc_starfire; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; int state, ioh_valid, memh_valid; bus_size_t iosize, memsize; pcireg_t reg; state = pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); if (state == PCI_PMCSR_STATE_D3) { printf(": unable to wake up from power state D3, " "reboot required.\n"); return; } /* * Map the device. */ reg = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SF_PCI_MEMBA); switch (reg) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: memh_valid = (pci_mapreg_map(pa, SF_PCI_MEMBA, reg, 0, &memt, &memh, &memsize, NULL, 0) == 0); break; default: memh_valid = 0; } ioh_valid = (pci_mapreg_map(pa, (reg == (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) ? SF_PCI_IOBA : SF_PCI_IOBA - 0x04, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &iosize, NULL, 0) == 0); if (memh_valid) { sc->sc_st = memt; sc->sc_sh = memh; sc->sc_iomapped = 0; } else if (ioh_valid) { sc->sc_st = iot; sc->sc_sh = ioh; sc->sc_iomapped = 1; } else { printf(": unable to map device registers\n"); return; } sc->sc_dmat = pa->pa_dmat; /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": unable to map interrupt\n"); goto out; } intrstr = pci_intr_string(pa->pa_pc, ih); psc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, sf_intr, sc, self->dv_xname); if (psc->sc_ih == NULL) { printf(": unable to establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto out; } printf(": %s", intrstr); /* * Finish off the attach. */ sf_attach(sc); return; out: if (ioh_valid) bus_space_unmap(iot, ioh, iosize); if (memh_valid) bus_space_unmap(memt, memh, memsize); }
void rtw_pci_attach(struct device *parent, struct device *self, void *aux) { struct rtw_pci_softc *psc = (void *) self; struct rtw_softc *sc = &psc->psc_rtw; struct rtw_regs *regs = &sc->sc_regs; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; bus_size_t iosize, memsize; int ioh_valid, memh_valid; psc->psc_pc = pa->pa_pc; psc->psc_pcitag = pa->pa_tag; /* * No power management hooks. * XXX Maybe we should add some! */ sc->sc_flags |= RTW_F_ENABLED; /* * Get revision info, and set some chip-specific variables. */ sc->sc_rev = PCI_REVISION(pa->pa_class); pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* * Map the device. */ ioh_valid = (pci_mapreg_map(pa, RTW_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize, 0) == 0); memh_valid = (pci_mapreg_map(pa, RTW_PCI_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &memsize, 0) == 0); if (memh_valid) { regs->r_bt = memt; regs->r_bh = memh; psc->psc_mapsize = memsize; } else if (ioh_valid) { regs->r_bt = iot; regs->r_bh = ioh; psc->psc_mapsize = iosize; } else { printf(": unable to map device registers\n"); return; } sc->sc_dmat = pa->pa_dmat; /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &psc->psc_ih)) { printf(": unable to map interrupt\n"); return; } intrstr = pci_intr_string(pc, psc->psc_ih); psc->psc_intrcookie = pci_intr_establish(pc, psc->psc_ih, IPL_NET, rtw_intr, sc, sc->sc_dev.dv_xname); if (psc->psc_intrcookie == NULL) { printf(": unable to establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); sc->sc_enable = rtw_pci_enable; sc->sc_disable = rtw_pci_disable; /* * Finish off the attach. */ rtw_attach(sc); }
void stge_attach(struct device *parent, struct device *self, void *aux) { struct stge_softc *sc = (struct stge_softc *) self; struct pci_attach_args *pa = aux; struct ifnet *ifp = &sc->sc_arpcom.ac_if; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; bus_dma_segment_t seg; bus_size_t iosize; int ioh_valid, memh_valid; int i, rseg, error; timeout_set(&sc->sc_timeout, stge_tick, sc); sc->sc_rev = PCI_REVISION(pa->pa_class); /* * Map the device. */ ioh_valid = (pci_mapreg_map(pa, STGE_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize, 0) == 0); memh_valid = (pci_mapreg_map(pa, STGE_PCI_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &iosize, 0) == 0); if (memh_valid) { sc->sc_st = memt; sc->sc_sh = memh; } else if (ioh_valid) { sc->sc_st = iot; sc->sc_sh = ioh; } else { printf(": unable to map device registers\n"); return; } sc->sc_dmat = pa->pa_dmat; /* Get it out of power save mode if needed. */ pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": unable to map interrupt\n"); goto fail_0; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, stge_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto fail_0; } printf(": %s", intrstr); /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct stge_control_data), PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { printf("%s: unable to allocate control data, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_0; } if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct stge_control_data), (caddr_t *)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { printf("%s: unable to map control data, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_1; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct stge_control_data), 1, sizeof(struct stge_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf("%s: unable to create control data DMA map, " "error = %d\n", sc->sc_dev.dv_xname, error); goto fail_2; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct stge_control_data), NULL, 0)) != 0) { printf("%s: unable to load control data DMA map, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_3; } /* * Create the transmit buffer DMA maps. Note that rev B.3 * and earlier seem to have a bug regarding multi-fragment * packets. We need to limit the number of Tx segments on * such chips to 1. */ for (i = 0; i < STGE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, STGE_JUMBO_FRAMELEN, STGE_NTXFRAGS, MCLBYTES, 0, 0, &sc->sc_txsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create tx DMA map %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_4; } } /* * Create the receive buffer DMA maps. */ for (i = 0; i < STGE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create rx DMA map %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_5; } sc->sc_rxsoft[i].ds_mbuf = NULL; } /* * Determine if we're copper or fiber. It affects how we * reset the card. */ if (CSR_READ_4(sc, STGE_AsicCtrl) & AC_PhyMedia) sc->sc_usefiber = 1; else sc->sc_usefiber = 0; /* * Reset the chip to a known state. */ stge_reset(sc); /* * Reading the station address from the EEPROM doesn't seem * to work, at least on my sample boards. Instead, since * the reset sequence does AutoInit, read it from the station * address registers. For Sundance 1023 you can only read it * from EEPROM. */ if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_SUNDANCE_ST1023) { sc->sc_arpcom.ac_enaddr[0] = CSR_READ_2(sc, STGE_StationAddress0) & 0xff; sc->sc_arpcom.ac_enaddr[1] = CSR_READ_2(sc, STGE_StationAddress0) >> 8; sc->sc_arpcom.ac_enaddr[2] = CSR_READ_2(sc, STGE_StationAddress1) & 0xff; sc->sc_arpcom.ac_enaddr[3] = CSR_READ_2(sc, STGE_StationAddress1) >> 8; sc->sc_arpcom.ac_enaddr[4] = CSR_READ_2(sc, STGE_StationAddress2) & 0xff; sc->sc_arpcom.ac_enaddr[5] = CSR_READ_2(sc, STGE_StationAddress2) >> 8; sc->sc_stge1023 = 0; } else {
static int cs4281_pci_attach(device_t dev) { struct sc_info *sc; struct ac97_info *codec = NULL; u_int32_t data; char status[SND_STATUSLEN]; if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { device_printf(dev, "cannot allocate softc\n"); return ENXIO; } bzero(sc, sizeof(*sc)); sc->dev = dev; sc->type = pci_get_devid(dev); data = pci_read_config(dev, PCIR_COMMAND, 2); data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); pci_write_config(dev, PCIR_COMMAND, data, 2); data = pci_read_config(dev, PCIR_COMMAND, 2); #if __FreeBSD_version > 500000 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); } #endif sc->regid = PCIR_MAPS; sc->regtype = SYS_RES_MEMORY; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { sc->regtype = SYS_RES_IOPORT; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { device_printf(dev, "unable to allocate register space\n"); goto bad; } } sc->st = rman_get_bustag(sc->reg); sc->sh = rman_get_bushandle(sc->reg); sc->memid = PCIR_MAPS + 4; sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0, ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE); if (sc->mem == NULL) { device_printf(dev, "unable to allocate fifo space\n"); goto bad; } sc->irqid = 0; sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); if (!sc->irq) { device_printf(dev, "unable to allocate interrupt\n"); goto bad; } if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, cs4281_intr, sc, &sc->ih)) { device_printf(dev, "unable to setup interrupt\n"); goto bad; } if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/CS4281_BUFFER_SIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, &sc->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } /* power up */ cs4281_power(sc, 0); /* init chip */ if (cs4281_init(sc) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; } /* create/init mixer */ codec = AC97_CREATE(dev, sc, cs4281_ac97); if (codec == NULL) goto bad; mixer_init(dev, ac97_getmixerclass(), codec); if (pcm_register(dev, sc, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc); pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc); snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", rman_get_start(sc->reg), rman_get_start(sc->irq)); pcm_setstatus(dev, status); return 0; bad: if (codec) ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); if (sc->mem) bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return ENXIO; }
int ppbactivate(struct device *self, int act) { struct ppb_softc *sc = (void *)self; pci_chipset_tag_t pc = sc->sc_pc; pcitag_t tag = sc->sc_tag; pcireg_t blr, reg; int off, rv = 0; switch (act) { case DVACT_QUIESCE: rv = config_activate_children(self, act); break; case DVACT_SUSPEND: rv = config_activate_children(self, act); /* Save registers that may get lost. */ sc->sc_csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); sc->sc_bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); sc->sc_bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO); sc->sc_bcr = pci_conf_read(pc, tag, PPB_REG_BRIDGECONTROL); sc->sc_int = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); if (sc->sc_cap_off) sc->sc_slcsr = pci_conf_read(pc, tag, sc->sc_cap_off + PCI_PCIE_SLCSR); if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®)) { sc->sc_msi_ma = pci_conf_read(pc, tag, off + PCI_MSI_MA); if (reg & PCI_MSI_MC_C64) { sc->sc_msi_mau32 = pci_conf_read(pc, tag, off + PCI_MSI_MAU32); sc->sc_msi_md = pci_conf_read(pc, tag, off + PCI_MSI_MD64); } else { sc->sc_msi_md = pci_conf_read(pc, tag, off + PCI_MSI_MD32); } sc->sc_msi_mc = reg; } if (pci_dopm) { /* Place the bridge into D3. */ sc->sc_pmcsr_state = pci_get_powerstate(pc, tag); pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D3); } break; case DVACT_RESUME: if (pci_dopm) { /* Restore power. */ pci_set_powerstate(pc, tag, sc->sc_pmcsr_state); } /* Restore the registers saved above. */ pci_conf_write(pc, tag, PCI_BHLC_REG, sc->sc_bhlcr); pci_conf_write(pc, tag, PPB_REG_BUSINFO, sc->sc_bir); pci_conf_write(pc, tag, PPB_REG_BRIDGECONTROL, sc->sc_bcr); pci_conf_write(pc, tag, PCI_INTERRUPT_REG, sc->sc_int); if (sc->sc_cap_off) pci_conf_write(pc, tag, sc->sc_cap_off + PCI_PCIE_SLCSR, sc->sc_slcsr); /* Restore I/O window. */ blr = pci_conf_read(pc, tag, PPB_REG_IOSTATUS); blr &= 0xffff0000; blr |= sc->sc_iolimit & PPB_IO_MASK; blr |= (sc->sc_iobase >> PPB_IO_SHIFT); pci_conf_write(pc, tag, PPB_REG_IOSTATUS, blr); blr = (sc->sc_iobase & 0xffff0000) >> 16; blr |= sc->sc_iolimit & 0xffff0000; pci_conf_write(pc, tag, PPB_REG_IO_HI, blr); /* Restore memory mapped I/O window. */ blr = sc->sc_memlimit & PPB_MEM_MASK; blr |= (sc->sc_membase >> PPB_MEM_SHIFT); pci_conf_write(pc, tag, PPB_REG_MEM, blr); /* Restore prefetchable MMI/O window. */ blr = sc->sc_pmemlimit & PPB_MEM_MASK; blr |= (sc->sc_pmembase >> PPB_MEM_SHIFT); pci_conf_write(pc, tag, PPB_REG_PREFMEM, blr); #ifdef __LP64__ pci_conf_write(pc, tag, PPB_REG_PREFBASE_HI32, sc->sc_pmembase >> 32); pci_conf_write(pc, tag, PPB_REG_PREFLIM_HI32, sc->sc_pmemlimit >> 32); #endif if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®)) { pci_conf_write(pc, tag, off + PCI_MSI_MA, sc->sc_msi_ma); if (reg & PCI_MSI_MC_C64) { pci_conf_write(pc, tag, off + PCI_MSI_MAU32, sc->sc_msi_mau32); pci_conf_write(pc, tag, off + PCI_MSI_MD64, sc->sc_msi_md); } else { pci_conf_write(pc, tag, off + PCI_MSI_MD32, sc->sc_msi_md); } pci_conf_write(pc, tag, off + PCI_MSI_MC, sc->sc_msi_mc); } /* * Restore command register last to avoid exposing * uninitialised windows. */ reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, (reg & 0xffff0000) | (sc->sc_csr & 0x0000ffff)); rv = config_activate_children(self, act); break; } return (rv); }
static int via_attach(device_t dev) { struct via_info *via = NULL; char status[SND_STATUSLEN]; int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum; uint32_t revid; via = kmalloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO); via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc"); pci_set_powerstate(dev, PCI_POWERSTATE_D0); pci_enable_busmaster(dev); via->regid = PCIR_BAR(0); via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid, RF_ACTIVE); if (!via->reg) { device_printf(dev, "cannot allocate bus resource."); goto bad; } via->st = rman_get_bustag(via->reg); via->sh = rman_get_bushandle(via->reg); via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); via->irqid = 0; via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, RF_ACTIVE | RF_SHAREABLE); if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } /* DMA tag for buffers */ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, &via->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } /* * DMA tag for SGD table. The 686 uses scatter/gather DMA and * requires a list in memory of work to do. We need only 16 bytes * for this list, and it is wasteful to allocate 16K. */ if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/NSEGS * sizeof(struct via_dma_op), /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, &via->sgd_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1) goto bad; if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0)) goto bad; if (via_chip_init(dev)) goto bad; via->codec = AC97_CREATE(dev, via, via_ac97); if (!via->codec) goto bad; mixer_init(dev, ac97_getmixerclass(), via->codec); via->codec_caps = ac97_getextcaps(via->codec); /* Try to set VRA without generating an error, VRM not reqrd yet */ if (via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) { u_int16_t ext = ac97_getextmode(via->codec); ext |= (via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); ext &= ~AC97_EXTCAP_DRA; ac97_setextmode(via->codec, ext); } ksnprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", rman_get_start(via->reg), rman_get_start(via->irq),PCM_KLDSTRING(snd_via8233)); revid = pci_get_revid(dev); /* * VIA8251 lost its interrupt after DMA EOL, and need * a gentle spank on its face within interrupt handler. */ if (revid == VIA8233_REV_ID_8251) via->dma_eol_wake = 1; else via->dma_eol_wake = 0; /* * Decide whether DXS had to be disabled or not */ if (revid == VIA8233_REV_ID_8233A) { /* * DXS channel is disabled. Reports from multiple users * that it plays at half-speed. Do not see this behaviour * on available 8233C or when emulating 8233A register set * on 8233C (either with or without ac97 VRA). */ via_dxs_disabled = 1; } else if (resource_int_value(device_get_name(dev), device_get_unit(dev), "via_dxs_disabled", &via_dxs_disabled) == 0) via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0; else via_dxs_disabled = 0; if (via_dxs_disabled) { via_dxs_chnum = 0; via_sgd_chnum = 1; } else { if (resource_int_value(device_get_name(dev), device_get_unit(dev), "via_dxs_channels", &via_dxs_chnum) != 0) via_dxs_chnum = NDXSCHANS; if (resource_int_value(device_get_name(dev), device_get_unit(dev), "via_sgd_channels", &via_sgd_chnum) != 0) via_sgd_chnum = NMSGDCHANS; } if (via_dxs_chnum > NDXSCHANS) via_dxs_chnum = NDXSCHANS; else if (via_dxs_chnum < 0) via_dxs_chnum = 0; if (via_sgd_chnum > NMSGDCHANS) via_sgd_chnum = NMSGDCHANS; else if (via_sgd_chnum < 0) via_sgd_chnum = 0; if (via_dxs_chnum + via_sgd_chnum < 1) { /* Minimalist ? */ via_dxs_chnum = 1; via_sgd_chnum = 0; } if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev), device_get_unit(dev), "via_dxs_src", &via_dxs_src) == 0) via->dxs_src = (via_dxs_src > 0) ? 1 : 0; else via->dxs_src = 0; /* Register */ if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS)) goto bad; for (i = 0; i < via_dxs_chnum; i++) pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); for (i = 0; i < via_sgd_chnum; i++) pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); for (i = 0; i < NWRCHANS; i++) pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); if (via_dxs_chnum > 0) via_init_sysctls(dev); device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n", (via_dxs_chnum > 0) ? "En" : "Dis", (via->dxs_src) ? "(SRC)" : "", via_dxs_chnum, via_sgd_chnum, NWRCHANS); pcm_setstatus(dev, status); return 0; bad: if (via->codec) ac97_destroy(via->codec); if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); if (via->lock) snd_mtxfree(via->lock); if (via) kfree(via, M_DEVBUF); return ENXIO; }
/* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ void dc_pci_attach(struct device *parent, struct device *self, void *aux) { const char *intrstr = NULL; pcireg_t command; struct dc_pci_softc *psc = (struct dc_pci_softc *)self; struct dc_softc *sc = &psc->psc_softc; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; int found = 0; psc->psc_pc = pa->pa_pc; sc->sc_dmat = pa->pa_dmat; pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG); /* * Map control/status registers. */ #ifdef DC_USEIOSPACE if (pci_mapreg_map(pa, DC_PCI_CFBIO, PCI_MAPREG_TYPE_IO, 0, &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) { printf(": can't map i/o space\n"); return; } #else if (pci_mapreg_map(pa, DC_PCI_CFBMA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->dc_btag, &sc->dc_bhandle, NULL, &psc->psc_mapsize, 0)) { printf(": can't map mem space\n"); return; } #endif /* Allocate interrupt */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); goto fail_1; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc, self->dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto fail_1; } printf(": %s", intrstr); /* Need this info to decide on a chip type. */ sc->dc_revision = PCI_REVISION(pa->pa_class); /* Get the eeprom width, if possible */ if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LITEON && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC)) ; /* PNIC has non-standard eeprom */ else if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_XIRCOM && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143)) ; /* XIRCOM has non-standard eeprom */ else dc_eeprom_width(sc); switch (PCI_VENDOR(pa->pa_id)) { case PCI_VENDOR_DEC: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21140 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) { found = 1; sc->dc_type = DC_TYPE_21143; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL; dc_read_srom(sc, sc->dc_romwidth); } break; case PCI_VENDOR_INTEL: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_21145) { found = 1; sc->dc_type = DC_TYPE_21145; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL; dc_read_srom(sc, sc->dc_romwidth); } break; case PCI_VENDOR_DAVICOM: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9009) { found = 1; sc->dc_type = DC_TYPE_DM9102; sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS; sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD; sc->dc_flags |= DC_TX_ALIGN; sc->dc_pmode = DC_PMODE_MII; /* Increase the latency timer value. */ command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT); command &= 0xFFFF00FF; command |= 0x00008000; pci_conf_write(pc, pa->pa_tag, DC_PCI_CFLT, command); } break; case PCI_VENDOR_ADMTEK: case PCI_VENDOR_3COM: case PCI_VENDOR_MICROSOFT: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) { found = 1; sc->dc_type = DC_TYPE_AL981; sc->dc_flags |= DC_TX_USE_TX_INTR; sc->dc_flags |= DC_TX_ADMTEK_WAR; sc->dc_pmode = DC_PMODE_MII; dc_read_srom(sc, sc->dc_romwidth); } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9511 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_ADM9513 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3COM_3CSHO100BTX || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MICROSOFT_MN130) { found = 1; sc->dc_type = DC_TYPE_AN983; sc->dc_flags |= DC_TX_USE_TX_INTR; sc->dc_flags |= DC_TX_ADMTEK_WAR; sc->dc_flags |= DC_64BIT_HASH; sc->dc_pmode = DC_PMODE_MII; /* Don't read SROM for - auto-loaded on reset */ } break; case PCI_VENDOR_MACRONIX: case PCI_VENDOR_ACCTON: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN2242) { found = 1; sc->dc_type = DC_TYPE_AN983; sc->dc_flags |= DC_TX_USE_TX_INTR; sc->dc_flags |= DC_TX_ADMTEK_WAR; sc->dc_flags |= DC_64BIT_HASH; sc->dc_pmode = DC_PMODE_MII; /* Don't read SROM for - auto-loaded on reset */ } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) { found = 1; if (sc->dc_revision < DC_REVISION_98713A) sc->dc_type = DC_TYPE_98713; if (sc->dc_revision >= DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713A; sc->dc_flags |= DC_21143_NWAY; } sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) { found = 1; if (sc->dc_revision >= DC_REVISION_98715AEC_C && sc->dc_revision < DC_REVISION_98725) sc->dc_flags |= DC_128BIT_HASH; sc->dc_type = DC_TYPE_987x5; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98727) { found = 1; sc->dc_type = DC_TYPE_987x5; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; } break; case PCI_VENDOR_COMPEX: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) { found = 1; if (sc->dc_revision < DC_REVISION_98713A) { sc->dc_type = DC_TYPE_98713; sc->dc_flags |= DC_REDUCED_MII_POLL; } if (sc->dc_revision >= DC_REVISION_98713A) sc->dc_type = DC_TYPE_98713A; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; } break; case PCI_VENDOR_LITEON: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) { found = 1; sc->dc_type = DC_TYPE_PNICII; sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; sc->dc_flags |= DC_128BIT_HASH; } if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) { found = 1; sc->dc_type = DC_TYPE_PNIC; sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS; sc->dc_flags |= DC_PNIC_RX_BUG_WAR; sc->dc_pnic_rx_buf = malloc(ETHER_MAX_DIX_LEN * 5, M_DEVBUF, M_NOWAIT); if (sc->dc_pnic_rx_buf == NULL) panic("dc_pci_attach"); if (sc->dc_revision < DC_REVISION_82C169) sc->dc_pmode = DC_PMODE_SYM; } break; case PCI_VENDOR_ASIX: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) { found = 1; sc->dc_type = DC_TYPE_ASIX; sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG; sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_pmode = DC_PMODE_MII; } break; case PCI_VENDOR_CONEXANT: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONEXANT_RS7112) { found = 1; sc->dc_type = DC_TYPE_CONEXANT; sc->dc_flags |= DC_TX_INTR_ALWAYS; sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_pmode = DC_PMODE_MII; dc_read_srom(sc, sc->dc_romwidth); } break; case PCI_VENDOR_XIRCOM: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143) { found = 1; sc->dc_type = DC_TYPE_XIRCOM; sc->dc_flags |= DC_TX_INTR_ALWAYS; sc->dc_flags |= DC_TX_COALESCE; sc->dc_flags |= DC_TX_ALIGN; sc->dc_pmode = DC_PMODE_MII; } break; } if (found == 0) { /* This shouldn't happen if probe has done its job... */ printf(": unknown device: %x:%x\n", PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); goto fail_2; } /* Save the cache line size. */ if (DC_IS_DAVICOM(sc)) sc->dc_cachesize = 0; else sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFLT) & 0xFF; /* Reset the adapter. */ dc_reset(sc); /* Take 21143 out of snooze mode */ if (DC_IS_INTEL(sc) || DC_IS_XIRCOM(sc)) { command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command); } /* * If we discover later (in dc_attach) that we have an * MII with no PHY, we need to have the 21143 drive the LEDs. * Except there are some systems like the NEC VersaPro NoteBook PC * which have no LEDs, and twiddling these bits has adverse effects * on them. (I.e. you suddenly can't get a link.) * * If mii_attach() returns an error, we leave the DC_TULIP_LEDS * bit set, else we clear it. Since our dc(4) driver is split into * bus-dependent and bus-independent parts, we must do set this bit * here while we are able to do PCI configuration reads. */ if (DC_IS_INTEL(sc)) { if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033) sc->dc_flags |= DC_TULIP_LEDS; } /* * Try to learn something about the supported media. * We know that ASIX and ADMtek and Davicom devices * will *always* be using MII media, so that's a no-brainer. * The tricky ones are the Macronix/PNIC II and the * Intel 21143. */ if (DC_IS_INTEL(sc)) dc_parse_21143_srom(sc); else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { if (sc->dc_type == DC_TYPE_98713) sc->dc_pmode = DC_PMODE_MII; else sc->dc_pmode = DC_PMODE_SYM; } else if (!sc->dc_pmode) sc->dc_pmode = DC_PMODE_MII; #ifdef __sparc64__ { extern void myetheraddr(u_char *); if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address", sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0) myetheraddr(sc->sc_arpcom.ac_enaddr); if (sc->sc_arpcom.ac_enaddr[0] == 0x00 && sc->sc_arpcom.ac_enaddr[1] == 0x03 && sc->sc_arpcom.ac_enaddr[2] == 0xcc) sc->dc_flags |= DC_MOMENCO_BOTCH; sc->sc_hasmac = 1; } #endif #ifdef SRM_MEDIA sc->dc_srm_media = 0; /* Remember the SRM console media setting */ if (DC_IS_INTEL(sc)) { command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); switch ((command >> 8) & 0xff) { case 3: sc->dc_srm_media = IFM_10_T; break; case 4: sc->dc_srm_media = IFM_10_T | IFM_FDX; break; case 5: sc->dc_srm_media = IFM_100_TX; break; case 6: sc->dc_srm_media = IFM_100_TX | IFM_FDX; break; } if (sc->dc_srm_media) sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER; } #endif dc_attach(sc); return; fail_2: pci_intr_disestablish(pc, sc->sc_ih); fail_1: bus_space_unmap(sc->dc_btag, sc->dc_bhandle, psc->psc_mapsize); }
void rtwn_pci_attach(struct device *parent, struct device *self, void *aux) { struct rtwn_pci_softc *sc = (struct rtwn_pci_softc*)self; struct pci_attach_args *pa = aux; struct ifnet *ifp; int i, error; pcireg_t memtype; pci_intr_handle_t ih; const char *intrstr; sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; timeout_set(&sc->calib_to, rtwn_calib_to, sc); timeout_set(&sc->scan_to, rtwn_scan_to, sc); pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* Map control/status registers. */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RTWN_PCI_MMBA); error = pci_mapreg_map(pa, RTWN_PCI_MMBA, memtype, 0, &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_mapsize, 0); if (error != 0) { printf(": can't map mem space\n"); return; } if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(sc->sc_pc, ih); sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET, rtwn_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); /* Disable PCIe Active State Power Management (ASPM). */ if (pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL)) { uint32_t lcsr = pci_conf_read(sc->sc_pc, sc->sc_tag, sc->sc_cap_off + PCI_PCIE_LCSR); lcsr &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1); pci_conf_write(sc->sc_pc, sc->sc_tag, sc->sc_cap_off + PCI_PCIE_LCSR, lcsr); } /* Allocate Tx/Rx buffers. */ error = rtwn_alloc_rx_list(sc); if (error != 0) { printf("%s: could not allocate Rx buffers\n", sc->sc_dev.dv_xname); return; } for (i = 0; i < RTWN_NTXQUEUES; i++) { error = rtwn_alloc_tx_list(sc, i); if (error != 0) { printf("%s: could not allocate Tx buffers\n", sc->sc_dev.dv_xname); rtwn_free_rx_list(sc); return; } } /* Attach the bus-agnostic driver. */ sc->sc_sc.sc_ops.cookie = sc; sc->sc_sc.sc_ops.write_1 = rtwn_pci_write_1; sc->sc_sc.sc_ops.write_2 = rtwn_pci_write_2; sc->sc_sc.sc_ops.write_4 = rtwn_pci_write_4; sc->sc_sc.sc_ops.read_1 = rtwn_pci_read_1; sc->sc_sc.sc_ops.read_2 = rtwn_pci_read_2; sc->sc_sc.sc_ops.read_4 = rtwn_pci_read_4; sc->sc_sc.sc_ops.tx = rtwn_tx; sc->sc_sc.sc_ops.power_on = rtwn_power_on; sc->sc_sc.sc_ops.dma_init = rtwn_dma_init; sc->sc_sc.sc_ops.load_firmware = rtwn_pci_load_firmware; sc->sc_sc.sc_ops.fw_loadpage = rtwn_fw_loadpage; sc->sc_sc.sc_ops.mac_init = rtwn_mac_init; sc->sc_sc.sc_ops.bb_init = rtwn_bb_init; sc->sc_sc.sc_ops.alloc_buffers = rtwn_alloc_buffers; sc->sc_sc.sc_ops.init = rtwn_pci_init; sc->sc_sc.sc_ops.stop = rtwn_pci_stop; sc->sc_sc.sc_ops.is_oactive = rtwn_is_oactive; sc->sc_sc.sc_ops.next_calib = rtwn_next_calib; sc->sc_sc.sc_ops.cancel_calib = rtwn_cancel_calib; sc->sc_sc.sc_ops.next_scan = rtwn_pci_next_scan; sc->sc_sc.sc_ops.cancel_scan = rtwn_cancel_scan; sc->sc_sc.sc_ops.wait_async = rtwn_wait_async; error = rtwn_attach(&sc->sc_dev, &sc->sc_sc, RTWN_CHIP_88C | RTWN_CHIP_PCI); if (error != 0) { rtwn_free_rx_list(sc); for (i = 0; i < RTWN_NTXQUEUES; i++) rtwn_free_tx_list(sc, i); return; } /* ifp is now valid */ ifp = &sc->sc_sc.sc_ic.ic_if; #if NBPFILTER > 0 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO, sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN); sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); sc->sc_rxtap.wr_ihdr.it_present = htole32(RTWN_RX_RADIOTAP_PRESENT); sc->sc_txtap_len = sizeof(sc->sc_txtapu); sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(RTWN_TX_RADIOTAP_PRESENT); #endif }
static void rtsx_pci_attach(device_t parent, device_t self, void *aux) { struct rtsx_pci_softc *sc = device_private(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; pcireg_t reg; char const *intrstr; bus_space_tag_t iot; bus_space_handle_t ioh; bus_size_t size; uint32_t flags; char intrbuf[PCI_INTRSTR_LEN]; sc->sc.sc_dev = self; sc->sc_pc = pc; pci_aprint_devinfo(pa, NULL); if ((pci_conf_read(pc, tag, RTSX_CFG_PCI) & RTSX_CFG_ASIC) != 0) { aprint_error_dev(self, "no asic\n"); return; } if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0, &iot, &ioh, NULL, &size)) { aprint_error_dev(self, "couldn't map registers\n"); return; } if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, sc->sc_pihp[0], intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(pc, sc->sc_pihp[0], IPL_SDMMC, rtsx_intr, &sc->sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); /* Enable the device */ reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); reg |= PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); /* Power up the device */ pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0); switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_REALTEK_RTS5209: flags = RTSX_F_5209; break; case PCI_PRODUCT_REALTEK_RTS5227: flags = RTSX_F_5227; break; case PCI_PRODUCT_REALTEK_RTS5229: flags = RTSX_F_5229; break; case PCI_PRODUCT_REALTEK_RTL8402: flags = RTSX_F_8402; break; case PCI_PRODUCT_REALTEK_RTL8411: flags = RTSX_F_8411; break; case PCI_PRODUCT_REALTEK_RTL8411B: flags = RTSX_F_8411B; break; default: flags = 0; break; } if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0) { aprint_error_dev(self, "couldn't initialize chip\n"); return; } if (!pmf_device_register1(self, rtsx_suspend, rtsx_resume, rtsx_shutdown)) aprint_error_dev(self, "couldn't establish powerhook\n"); }
static int cs4281_pci_attach(device_t dev) { struct sc_info *sc; struct ac97_info *codec = NULL; char status[SND_STATUSLEN]; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); sc->dev = dev; sc->type = pci_get_devid(dev); pci_enable_busmaster(dev); #if __FreeBSD_version > 500000 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); } #else data = pci_read_config(dev, CS4281PCI_PMCS_OFFSET, 4); if (data & CS4281PCI_PMCS_PS_MASK) { /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", data & CS4281PCI_PMCS_PS_MASK); pci_write_config(dev, CS4281PCI_PMCS_OFFSET, data & ~CS4281PCI_PMCS_PS_MASK, 4); } #endif sc->regid = PCIR_BAR(0); sc->regtype = SYS_RES_MEMORY; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { sc->regtype = SYS_RES_IOPORT; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { device_printf(dev, "unable to allocate register space\n"); goto bad; } } sc->st = rman_get_bustag(sc->reg); sc->sh = rman_get_bushandle(sc->reg); sc->memid = PCIR_BAR(1); sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0, ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE); if (sc->mem == NULL) { device_printf(dev, "unable to allocate fifo space\n"); goto bad; } sc->irqid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, RF_ACTIVE | RF_SHAREABLE); if (!sc->irq) { device_printf(dev, "unable to allocate interrupt\n"); goto bad; } if (snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)) { device_printf(dev, "unable to setup interrupt\n"); goto bad; } sc->bufsz = pcm_getbuffersize(dev, 4096, CS4281_DEFAULT_BUFSZ, 65536); if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &sc->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } /* power up */ cs4281_power(sc, 0); /* init chip */ if (cs4281_init(sc) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; } /* create/init mixer */ codec = AC97_CREATE(dev, sc, cs4281_ac97); if (codec == NULL) goto bad; mixer_init(dev, ac97_getmixerclass(), codec); if (pcm_register(dev, sc, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc); pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc); snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281)); pcm_setstatus(dev, status); return 0; bad: if (codec) ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); if (sc->mem) bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return ENXIO; }
void cs4280_attach(struct device *parent, struct device *self, void *aux) { struct cs4280_softc *sc = (struct cs4280_softc *) self; struct pci_attach_args *pa = (struct pci_attach_args *) aux; pci_chipset_tag_t pc = pa->pa_pc; char const *intrstr; pci_intr_handle_t ih; u_int32_t mem; /* Map I/O register */ if (pci_mapreg_map(pa, CSCC_PCI_BA0, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) { printf(": can't map BA0 space\n"); return; } if (pci_mapreg_map(pa, CSCC_PCI_BA1, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) { printf(": can't map BA1 space\n"); return; } sc->sc_dmatag = pa->pa_dmat; /* Get out of power save mode if needed. */ pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* LATENCY_TIMER setting */ mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if ( PCI_LATTIMER(mem) < 32 ) { mem &= 0xffff00ff; mem |= 0x00002000; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, cs4280_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); /* Initialization */ if (cs4280_init(sc, 1) != 0) return; mountroothook_establish(cs4280_attachhook, sc); /* AC 97 attachement */ sc->host_if.arg = sc; sc->host_if.attach = cs4280_attach_codec; sc->host_if.read = cs4280_read_codec; sc->host_if.write = cs4280_write_codec; sc->host_if.reset = cs4280_reset_codec; if (ac97_attach(&sc->host_if) != 0) { printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); return; } }