int pci_get_ht_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, int *offset, pcireg_t *value) { pcireg_t reg; unsigned int ofs; if (pci_get_capability(pc, tag, PCI_CAP_LDT, &ofs, NULL) == 0) return 0; while (ofs != 0) { #ifdef DIAGNOSTIC if ((ofs & 3) || (ofs < 0x40)) panic("pci_get_ht_capability"); #endif reg = pci_conf_read(pc, tag, ofs); if (PCI_HT_CAP(reg) == capid) { if (offset) *offset = ofs; if (value) *value = reg; return 1; } ofs = PCI_CAPLIST_NEXT(reg); } return 0; }
int che_read_eeprom(struct cheg_softc *sc, struct pci_attach_args *pa, pcireg_t addr, pcireg_t *dp) { pcireg_t rv, base; int i = 4; if (!pci_get_capability(pa->pa_pc, pa->pa_tag, CHE_PCI_CAP_ID_VPD, &base, NULL)) { printf("%s: VPD EEPROM not found\n", DEVNAME(sc), addr); return EIO; } addr <<= 16; pci_conf_write(pa->pa_pc, pa->pa_tag, base, addr); while(i--) { delay(10); rv = pci_conf_read(pa->pa_pc, pa->pa_tag, base); if (rv & CHE_PCI_F_VPD_ADDR) break; } if (!(rv & CHE_PCI_F_VPD_ADDR)) { printf("%s: reading EEPROM address 0x%x failed\n", DEVNAME(sc), addr); return EIO; } *dp = pci_conf_read(pa->pa_pc, pa->pa_tag, base + CHE_PCI_VPD_DATA); return (0); }
/* * Get chip out of power-saving mode, init registers */ void re_cardbus_setup(struct rl_softc *sc) { struct re_cardbus_softc *csc = (struct re_cardbus_softc *)sc; cardbus_devfunc_t ct = csc->ct; cardbus_chipset_tag_t cc = ct->ct_cc; pci_chipset_tag_t pc = csc->sc_pc; pcireg_t reg, command; int pmreg; /* Handle power management nonsense */ if (pci_get_capability(pc, csc->sc_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { command = pci_conf_read(pc, csc->sc_tag, pmreg + PCI_PMCSR); if (command & RL_PSTATE_MASK) { pcireg_t iobase, membase, irq; /* Save important PCI config data */ iobase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOIO); membase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOMEM); irq = pci_conf_read(pc, csc->sc_tag, RL_PCI_INTLINE); /* Reset the power state */ printf("%s: chip is in D%d power mode " "-- setting to D0\n", sc->sc_dev.dv_xname, command & RL_PSTATE_MASK); command &= RL_PSTATE_MASK; pci_conf_write(pc, csc->sc_tag, pmreg + PCI_PMCSR, command); /* Restore PCI config data */ pci_conf_write(pc, csc->sc_tag, RL_PCI_LOIO, iobase); pci_conf_write(pc, csc->sc_tag, RL_PCI_LOMEM, membase); pci_conf_write(pc, csc->sc_tag, RL_PCI_INTLINE, irq); } } /* Make sure the right access type is on the Cardbus bridge */ (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben); (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); /* Program the BAR */ pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val); /* Enable proper bits in CARDBUS CSR */ reg = pci_conf_read(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG); reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE); reg |= csc->sc_csr; pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg); /* Make sure the latency timer is set to some reasonable value */ reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG); if (PCI_LATTIMER(reg) < 0x20) { reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); reg |= (0x20 << PCI_LATTIMER_SHIFT); pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg); } }
void dc_cardbus_setup(struct dc_cardbus_softc *csc) { cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; pci_chipset_tag_t pc = csc->sc_pc; pcireg_t reg; int r; /* wakeup the card if needed */ reg = pci_conf_read(pc, csc->sc_tag, PCI_CFDA); if (reg | (DC_CFDA_SUSPEND|DC_CFDA_STANDBY)) { pci_conf_write(pc, csc->sc_tag, PCI_CFDA, reg & ~(DC_CFDA_SUSPEND|DC_CFDA_STANDBY)); } if (pci_get_capability(csc->sc_pc, csc->sc_tag, PCI_CAP_PWRMGMT, &r, 0)) { r = pci_conf_read(csc->sc_pc, csc->sc_tag, r + 4) & 3; if (r) { printf("%s: awakening from state D%d\n", csc->sc_dc.sc_dev.dv_xname, r); pci_conf_write(csc->sc_pc, csc->sc_tag, r + 4, 0); } } (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_actype); (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); reg = pci_conf_read(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG); reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; pci_conf_write(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg); reg = pci_conf_read(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG); }
void rtw_cardbus_setup(struct rtw_cardbus_softc *csc) { struct rtw_softc *sc = &csc->sc_rtw; cardbus_devfunc_t ct = csc->sc_ct; cardbus_chipset_tag_t cc = ct->ct_cc; pci_chipset_tag_t pc = csc->sc_pc; pcireg_t reg; int pmreg; if (pci_get_capability(pc, csc->sc_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { reg = pci_conf_read(pc, csc->sc_tag, pmreg + 4) & 0x03; #if 1 /* XXX Probably not right for CardBus. */ if (reg == 3) { /* * The card has lost all configuration data in * this state, so punt. */ printf("%s: unable to wake up from power state D3\n", sc->sc_dev.dv_xname); return; } #endif if (reg != 0) { printf("%s: waking up from power state D%d\n", sc->sc_dev.dv_xname, reg); pci_conf_write(pc, csc->sc_tag, pmreg + 4, 0); } } /* Program the BAR. */ pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val); /* Make sure the right access type is on the CardBus bridge. */ (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben); (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); /* Enable the appropriate bits in the PCI CSR. */ reg = pci_conf_read(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG); reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE); reg |= csc->sc_csr; pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg); /* * Make sure the latency timer is set to some reasonable * value. */ reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG); if (PCI_LATTIMER(reg) < 0x20) { reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); reg |= (0x20 << PCI_LATTIMER_SHIFT); pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg); } }
void pchbattach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; char devinfo[256]; #if NAGP > 0 struct agpbus_attach_args apa; #endif volatile unsigned char *python; uint32_t v; aprint_normal("\n"); /* * All we do is print out a description. Eventually, we * might want to add code that does something that's * possibly chipset-specific. */ pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo, PCI_REVISION(pa->pa_class)); switch (PCI_VENDOR(pa->pa_id)) { case PCI_VENDOR_IBM: switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_IBM_82660: ibm82660_print(pa, self); break; case PCI_PRODUCT_IBM_PYTHON: python = mapiodev(0xfeff6000, 0x60); v = 0x88b78e01; /* taken from linux */ out32rb(python+0x30, v); v = in32rb(python+0x30); aprint_debug("Reset python reg 30 to 0x%x\n", v); break; } break; case PCI_VENDOR_MOT: switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_MOT_MPC105: mpc105_print(pa, self); break; case PCI_PRODUCT_MOT_MPC106: mpc106_print(pa, self); break; } break; } #if NAGP > 0 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) != 0) { apa.apa_pci_args = *pa; config_found_ia(self, "agpbus", &apa, agpbusprint); } #endif /* NAGP */ }
int pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state) { int offset; pcireg_t value; if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) return EOPNOTSUPP; return pci_get_powerstate_int(pc, tag, state, offset); }
void msi_delroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = pin; pcireg_t reg; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®) == 0) panic("%s: no msi capability", __func__); pci_conf_write(pc, tag, off, reg & ~PCI_MSI_MC_MSIE); }
void * pci_msi_establish(struct pci_attach_args *pa, int level, int (*func)(void *), void *arg) { int co; struct intrhand *ih; struct msi_hdl *msih; struct cpu_info *ci; struct intrsource *is; pcireg_t reg; if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &co, 0)) return NULL; ih = intr_establish(-1, &msi_pic, -1, IST_EDGE, level, func, arg, 0); if (ih == NULL) return NULL; msih = malloc(sizeof(*msih), M_DEVBUF, M_WAITOK); msih->ih = ih; msih->pc = pa->pa_pc; msih->tag = pa->pa_tag; msih->co = co; ci = ih->ih_cpu; is = ci->ci_isources[ih->ih_slot]; reg = pci_conf_read(pa->pa_pc, pa->pa_tag, co + PCI_MSI_CTL); pci_conf_write(pa->pa_pc, pa->pa_tag, co + PCI_MSI_MADDR64_LO, LAPIC_MSIADDR_BASE | __SHIFTIN(ci->ci_cpuid, LAPIC_MSIADDR_DSTID_MASK)); if (reg & PCI_MSI_CTL_64BIT_ADDR) { pci_conf_write(pa->pa_pc, pa->pa_tag, co + PCI_MSI_MADDR64_HI, 0); /* XXX according to the manual, ASSERT is unnecessary if * EDGE */ pci_conf_write(pa->pa_pc, pa->pa_tag, co + PCI_MSI_MDATA64, __SHIFTIN(is->is_idtvec, LAPIC_MSIDATA_VECTOR_MASK) | LAPIC_MSIDATA_TRGMODE_EDGE | LAPIC_MSIDATA_LEVEL_ASSERT | LAPIC_MSIDATA_DM_FIXED); } else { /* XXX according to the manual, ASSERT is unnecessary if * EDGE */ pci_conf_write(pa->pa_pc, pa->pa_tag, co + PCI_MSI_MDATA, __SHIFTIN(is->is_idtvec, LAPIC_MSIDATA_VECTOR_MASK) | LAPIC_MSIDATA_TRGMODE_EDGE | LAPIC_MSIDATA_LEVEL_ASSERT | LAPIC_MSIDATA_DM_FIXED); } pci_conf_write(pa->pa_pc, pa->pa_tag, co + PCI_MSI_CTL, PCI_MSI_CTL_MSI_ENABLE); return msih; }
/* * return number of the devices's MSI-X vectors * return 0 if the device does not support MSI-X */ int pci_msix_count(pci_chipset_tag_t pc, pcitag_t tag) { pcireg_t reg; int offset; if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &offset, NULL) == 0) return 0; reg = pci_conf_read(pc, tag, offset + PCI_MSIX_CTL); return PCI_MSIX_CTL_TBLSIZE(reg); }
int pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) { int offset; pcireg_t value; if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) { printf("pci_set_powerstate not supported\n"); return EOPNOTSUPP; } return pci_set_powerstate_int(pc, tag, state, offset, value); }
int pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || mp_busses == NULL || pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0) return 1; ihp->tag = tag; ihp->line = APIC_INT_VIA_MSG; ihp->pin = 0; return 0; }
/* * return number of the devices's MSI vectors * return 0 if the device does not support MSI */ int pci_msi_count(pci_chipset_tag_t pc, pcitag_t tag) { pcireg_t reg; uint32_t mmc; int count, offset; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &offset, NULL) == 0) return 0; reg = pci_conf_read(pc, tag, offset + PCI_MSI_CTL); mmc = PCI_MSI_CTL_MMC(reg); count = 1 << mmc; if (count > PCI_MSI_MAX_VECTORS) { aprint_error("detect an illegal device! The device use reserved MMC values.\n"); return 0; } return count; }
void msi_addroute(struct pic *pic, struct cpu_info *ci, int pin, int vec, int type) { pci_chipset_tag_t pc = NULL; /* XXX */ pcitag_t tag = pin; pcireg_t reg, addr; int off; if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®) == 0) panic("%s: no msi capability", __func__); addr = 0xfee00000UL | (ci->ci_apicid << 12); if (reg & PCI_MSI_MC_C64) { pci_conf_write(pc, tag, off + PCI_MSI_MA, addr); pci_conf_write(pc, tag, off + PCI_MSI_MAU32, 0); pci_conf_write(pc, tag, off + PCI_MSI_MD64, vec); } else { pci_conf_write(pc, tag, off + PCI_MSI_MA, addr); pci_conf_write(pc, tag, off + PCI_MSI_MD32, vec); } pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE); }
int pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, pcireg_t *data) { pcireg_t reg; int ofs, i, j; KASSERT(data != NULL); KASSERT((offset + count) < 0x7fff); if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) return 1; for (i = 0; i < count; offset += sizeof(*data), i++) { pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), data[i]); reg &= 0x0000ffff; reg |= PCI_VPD_OPFLAG; reg |= PCI_VPD_ADDRESS(offset); pci_conf_write(pc, tag, ofs, reg); /* * PCI 2.2 does not specify how long we should poll * for completion nor whether the operation can fail. */ j = 0; do { if (j++ == 20) return 1; delay(1); reg = pci_conf_read(pc, tag, ofs); } while (reg & PCI_VPD_OPFLAG); } return 0; }
static bool pci_child_register(device_t child) { device_t self = device_parent(child); struct pci_softc *sc = device_private(self); struct pci_child_power *priv; int device, function, off; pcireg_t reg; priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK); device = device_locator(child, PCICF_DEV); function = device_locator(child, PCICF_FUNCTION); priv->p_pc = sc->sc_pc; priv->p_tag = pci_make_tag(priv->p_pc, sc->sc_bus, device, function); priv->p_class = pci_conf_read(priv->p_pc, priv->p_tag, PCI_CLASS_REG); priv->p_csr = pci_conf_read(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG); if (pci_get_capability(priv->p_pc, priv->p_tag, PCI_CAP_PWRMGMT, &off, ®)) { priv->p_has_pm = true; priv->p_pm_offset = off; priv->p_pm_cap = reg; } else { priv->p_has_pm = false; priv->p_pm_offset = -1; } device_pmf_bus_register(child, priv, pci_child_suspend, pci_child_resume, pci_child_shutdown, pci_child_deregister); return true; }
void athn_pci_attach(struct device *parent, struct device *self, void *aux) { struct athn_pci_softc *psc = (struct athn_pci_softc *)self; struct athn_softc *sc = &psc->sc_sc; struct pci_attach_args *pa = aux; const char *intrstr; pci_intr_handle_t ih; pcireg_t memtype, reg; pci_product_id_t subsysid; int error; sc->sc_dmat = pa->pa_dmat; psc->sc_pc = pa->pa_pc; psc->sc_tag = pa->pa_tag; sc->ops.read = athn_pci_read; sc->ops.write = athn_pci_write; sc->ops.write_barrier = athn_pci_write_barrier; /* * Get the offset of the PCI Express Capability Structure in PCI * Configuration Space (Linux hardcodes it as 0x60.) */ error = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, &psc->sc_cap_off, NULL); if (error != 0) { /* Found. */ sc->sc_disable_aspm = athn_pci_disable_aspm; sc->flags |= ATHN_FLAG_PCIE; } /* * Clear device-specific "PCI retry timeout" register (41h) to prevent * PCI Tx retries from interfering with C3 CPU state. */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40); if (reg & 0xff00) pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, reg & ~0xff00); /* * Set the cache line size to a reasonable value if it is 0. * Change latency timer; default value yields poor results. */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if (PCI_CACHELINE(reg) == 0) { reg &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT); reg |= 8 << PCI_CACHELINE_SHIFT; } reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); reg |= 168 << PCI_LATTIMER_SHIFT; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, reg); /* Determine if bluetooth is also supported (combo chip.) */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); subsysid = PCI_PRODUCT(reg); if (subsysid == PCI_SUBSYSID_ATHEROS_COEX3WIRE_SA || subsysid == PCI_SUBSYSID_ATHEROS_COEX3WIRE_DA) sc->flags |= ATHN_FLAG_BTCOEX3WIRE; else if (subsysid == PCI_SUBSYSID_ATHEROS_COEX2WIRE) sc->flags |= ATHN_FLAG_BTCOEX2WIRE; /* Map control/status registers. */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); error = pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &psc->sc_st, &psc->sc_sh, NULL, &psc->sc_mapsize, 0); if (error != 0) { printf(": can't map mem space\n"); return; } if (pci_intr_map(pa, &ih) != 0) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(psc->sc_pc, ih); psc->sc_ih = pci_intr_establish(psc->sc_pc, ih, IPL_NET, athn_intr, sc, sc->sc_dev.dv_xname); if (psc->sc_ih == NULL) { printf(": can't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); athn_attach(sc); }
/* * Generic PCI bus enumeration routine. Used unless machine-dependent * code needs to provide something else. */ int pci_enumerate_bus(struct pci_softc *sc, const int *locators, int (*match)(const struct pci_attach_args *), struct pci_attach_args *pap) { pci_chipset_tag_t pc = sc->sc_pc; int device, function, nfunctions, ret; const struct pci_quirkdata *qd; pcireg_t id, bhlcr; pcitag_t tag; uint8_t devs[32]; int i, n; n = pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs, __arraycount(devs)); for (i = 0; i < n; i++) { device = devs[i]; if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) && (locators[PCICF_DEV] != device)) continue; tag = pci_make_tag(pc, sc->sc_bus, device, 0); bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlcr) > 2) continue; id = pci_conf_read(pc, tag, PCI_ID_REG); /* Invalid vendor ID value? */ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) continue; /* XXX Not invalid, but we've done this ~forever. */ if (PCI_VENDOR(id) == 0) continue; qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id)); if (qd != NULL && (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0) nfunctions = 8; else if (qd != NULL && (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0) nfunctions = 1; else nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; #ifdef __PCI_DEV_FUNCORDER char funcs[8]; int j; for (j = 0; j < nfunctions; j++) { funcs[j] = j; } if (j < __arraycount(funcs)) funcs[j] = -1; if (nfunctions > 1) { pci_dev_funcorder(sc->sc_pc, sc->sc_bus, device, nfunctions, funcs); } for (j = 0; j < 8 && (function = funcs[j]) < 8 && function >= 0; j++) { #else for (function = 0; function < nfunctions; function++) { #endif if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT) && (locators[PCICF_FUNCTION] != function)) continue; if (qd != NULL && (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0) continue; tag = pci_make_tag(pc, sc->sc_bus, device, function); ret = pci_probe_device(sc, tag, match, pap); if (match != NULL && ret != 0) return ret; } } return 0; } #endif /* PCI_MACHDEP_ENUMERATE_BUS */ /* * Vital Product Data (PCI 2.2) */ int pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, pcireg_t *data) { uint32_t reg; int ofs, i, j; KASSERT(data != NULL); KASSERT((offset + count) < 0x7fff); if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) return 1; for (i = 0; i < count; offset += sizeof(*data), i++) { reg &= 0x0000ffff; reg &= ~PCI_VPD_OPFLAG; reg |= PCI_VPD_ADDRESS(offset); pci_conf_write(pc, tag, ofs, reg); /* * PCI 2.2 does not specify how long we should poll * for completion nor whether the operation can fail. */ j = 0; do { if (j++ == 20) return 1; delay(4); reg = pci_conf_read(pc, tag, ofs); } while ((reg & PCI_VPD_OPFLAG) == 0); data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs)); } return 0; }
static void bce_attach(device_t parent, device_t self, void *aux) { struct bce_softc *sc = device_private(self); struct pci_attach_args *pa = aux; const struct bce_product *bp; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; uint32_t command; pcireg_t memtype, pmode; bus_addr_t memaddr; bus_size_t memsize; void *kva; bus_dma_segment_t seg; int error, i, pmreg, rseg; struct ifnet *ifp; char intrbuf[PCI_INTRSTR_LEN]; sc->bce_dev = self; bp = bce_lookup(pa); KASSERT(bp != NULL); sc->bce_pa = *pa; /* BCM440x can only address 30 bits (1GB) */ if (bus_dmatag_subregion(pa->pa_dmat, 0, (1 << 30), &(sc->bce_dmatag), BUS_DMA_NOWAIT) != 0) { aprint_error_dev(self, "WARNING: failed to restrict dma range," " falling back to parent bus dma range\n"); sc->bce_dmatag = pa->pa_dmat; } aprint_naive(": Ethernet controller\n"); aprint_normal(": %s\n", bp->bp_name); /* * Map control/status registers. */ command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); if (!(command & PCI_COMMAND_MEM_ENABLE)) { aprint_error_dev(self, "failed to enable memory mapping!\n"); return; } memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0); switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag, &sc->bce_bhandle, &memaddr, &memsize) == 0) break; default: aprint_error_dev(self, "unable to find mem space\n"); return; } /* Get it out of power save mode if needed. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, NULL)) { pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3; if (pmode == 3) { /* * The card has lost all configuration data in * this state, so punt. */ aprint_error_dev(self, "unable to wake up from power state D3\n"); return; } if (pmode != 0) { aprint_normal_dev(self, "waking up from power state D%d\n", pmode); pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0); } } if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc); if (sc->bce_intrhand == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); /* reset the chip */ bce_reset(sc); /* * Allocate DMA-safe memory for ring descriptors. * The receive, and transmit rings can not share the same * 4k space, however both are allocated at once here. */ /* * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but * due to the limition above. ?? */ if ((error = bus_dmamem_alloc(sc->bce_dmatag, 2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE, &seg, 1, &rseg, BUS_DMA_NOWAIT))) { aprint_error_dev(self, "unable to alloc space for ring descriptors, error = %d\n", error); return; } /* map ring space to kernel */ if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg, 2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) { aprint_error_dev(self, "unable to map DMA buffers, error = %d\n", error); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* create a dma map for the ring */ if ((error = bus_dmamap_create(sc->bce_dmatag, 2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->bce_ring_map))) { aprint_error_dev(self, "unable to create ring DMA map, error = %d\n", error); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* connect the ring space to the dma map */ if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva, 2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) { bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* save the ring space in softc */ sc->bce_rx_ring = (struct bce_dma_slot *) kva; sc->bce_tx_ring = (struct bce_dma_slot *) ((char *)kva + PAGE_SIZE); /* Create the transmit buffer DMA maps. */ for (i = 0; i < BCE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) { aprint_error_dev(self, "unable to create tx DMA map, error = %d\n", error); } sc->bce_cdata.bce_tx_chain[i] = NULL; } /* Create the receive buffer DMA maps. */ for (i = 0; i < BCE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) { aprint_error_dev(self, "unable to create rx DMA map, error = %d\n", error); } sc->bce_cdata.bce_rx_chain[i] = NULL; } /* Set up ifnet structure */ ifp = &sc->ethercom.ec_if; strcpy(ifp->if_xname, device_xname(self)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bce_ioctl; ifp->if_start = bce_start; ifp->if_watchdog = bce_watchdog; ifp->if_init = bce_init; ifp->if_stop = bce_stop; IFQ_SET_READY(&ifp->if_snd); /* Initialize our media structures and probe the MII. */ sc->bce_mii.mii_ifp = ifp; sc->bce_mii.mii_readreg = bce_mii_read; sc->bce_mii.mii_writereg = bce_mii_write; sc->bce_mii.mii_statchg = bce_statchg; sc->ethercom.ec_mii = &sc->bce_mii; ifmedia_init(&sc->bce_mii.mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_FORCEANEG|MIIF_DOPAUSE); if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) { ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO); /* get the phy */ sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_PHY) & 0x1f; /* * Enable activity led. * XXX This should be in a phy driver, but not currently. */ bce_mii_write(sc->bce_dev, 1, 26, /* MAGIC */ bce_mii_read(sc->bce_dev, 1, 26) & 0x7fff); /* MAGIC */ /* enable traffic meter led mode */ bce_mii_write(sc->bce_dev, 1, 27, /* MAGIC */ bce_mii_read(sc->bce_dev, 1, 27) | (1 << 6)); /* MAGIC */ /* Attach the interface */ if_attach(ifp); sc->enaddr[0] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET0); sc->enaddr[1] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET1); sc->enaddr[2] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET2); sc->enaddr[3] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET3); sc->enaddr[4] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET4); sc->enaddr[5] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET5); aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(sc->enaddr)); ether_ifattach(ifp, sc->enaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, 0); callout_init(&sc->bce_timeout, 0); if (pmf_device_register(self, NULL, bce_resume)) pmf_class_network_register(self, ifp); else aprint_error_dev(self, "couldn't establish power handler\n"); }
void ppbattach(struct device *parent, struct device *self, void *aux) { struct ppb_softc *sc = (struct ppb_softc *)self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; struct pcibus_attach_args pba; pci_intr_handle_t ih; pcireg_t busdata, reg, blr; char *name; int pin; sc->sc_pc = pc; sc->sc_tag = pa->pa_tag; busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO); if (PPB_BUSINFO_SECONDARY(busdata) == 0) { printf(": not configured by system firmware\n"); return; } #if 0 /* * XXX can't do this, because we're not given our bus number * (we shouldn't need it), and because we've no way to * decompose our tag. */ /* sanity check. */ if (pa->pa_bus != PPB_BUSINFO_PRIMARY(busdata)) panic("ppbattach: bus in tag (%d) != bus in reg (%d)", pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata)); #endif /* Check for PCI Express capabilities and setup hotplug support. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, ®) && (reg & PCI_PCIE_XCAP_SI)) { #ifdef __i386__ if (pci_intr_map(pa, &ih) == 0) sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO, ppb_intr, sc, self->dv_xname); #else if (pci_intr_map_msi(pa, &ih) == 0 || pci_intr_map(pa, &ih) == 0) sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO, ppb_intr, sc, self->dv_xname); #endif if (sc->sc_intrhand) { printf(": %s", pci_intr_string(pc, ih)); /* Enable hotplug interrupt. */ reg = pci_conf_read(pc, pa->pa_tag, sc->sc_cap_off + PCI_PCIE_SLCSR); reg |= (PCI_PCIE_SLCSR_HPE | PCI_PCIE_SLCSR_PDE); pci_conf_write(pc, pa->pa_tag, sc->sc_cap_off + PCI_PCIE_SLCSR, reg); timeout_set(&sc->sc_to, ppb_hotplug_insert_finish, sc); } } printf("\n"); if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BA_HPB && PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BAM_HPB)) ppb_alloc_resources(sc, pa); for (pin = PCI_INTERRUPT_PIN_A; pin <= PCI_INTERRUPT_PIN_D; pin++) { pa->pa_intrpin = pa->pa_rawintrpin = pin; pa->pa_intrline = 0; pci_intr_map(pa, &sc->sc_ih[pin - PCI_INTERRUPT_PIN_A]); } /* * The UltraSPARC-IIi APB doesn't implement the standard * address range registers. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_SIMBA) goto attach; /* Figure out the I/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IOSTATUS); sc->sc_iobase = (blr & 0x000000f0) << 8; sc->sc_iolimit = (blr & 0x000f000) | 0x00000fff; blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IO_HI); sc->sc_iobase |= (blr & 0x0000ffff) << 16; sc->sc_iolimit |= (blr & 0xffff0000); if (sc->sc_iolimit > sc->sc_iobase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pciio", sc->sc_dev.dv_xname); sc->sc_ioex = extent_create(name, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_ioex, sc->sc_iobase, sc->sc_iolimit - sc->sc_iobase + 1, EX_NOWAIT); } } /* Figure out the memory mapped I/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_MEM); sc->sc_membase = (blr & 0x0000fff0) << 16; sc->sc_memlimit = (blr & 0xfff00000) | 0x000fffff; if (sc->sc_memlimit > sc->sc_membase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pcimem", sc->sc_dev.dv_xname); sc->sc_memex = extent_create(name, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_memex, sc->sc_membase, sc->sc_memlimit - sc->sc_membase + 1, EX_NOWAIT); } } /* Figure out the prefetchable MMI/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFMEM); sc->sc_pmembase = (blr & 0x0000fff0) << 16; sc->sc_pmemlimit = (blr & 0xfff00000) | 0x000fffff; #ifdef __LP64__ /* XXX because extents use long... */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFBASE_HI32); sc->sc_pmembase |= ((uint64_t)blr) << 32; blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFLIM_HI32); sc->sc_pmemlimit |= ((uint64_t)blr) << 32; #endif if (sc->sc_pmemlimit > sc->sc_pmembase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pcipmem", sc->sc_dev.dv_xname); sc->sc_pmemex = extent_create(name, 0, (u_long)-1L, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_pmemex, sc->sc_pmembase, sc->sc_pmemlimit - sc->sc_pmembase + 1, EX_NOWAIT); } } /* * The Intel 82801BAM Hub-to-PCI can decode subtractively. * XXX We probably should handle subtractive decode bridges * in general. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BA_HPB || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_HPB)) { if (sc->sc_ioex == NULL) sc->sc_ioex = pa->pa_ioex; if (sc->sc_memex == NULL) sc->sc_memex = pa->pa_memex; } attach: /* * Attach the PCI bus that hangs off of it. * * XXX Don't pass-through Memory Read Multiple. Should we? * XXX Consult the spec... */ bzero(&pba, sizeof(pba)); pba.pba_busname = "pci"; pba.pba_iot = pa->pa_iot; pba.pba_memt = pa->pa_memt; pba.pba_dmat = pa->pa_dmat; pba.pba_pc = pc; pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY; pba.pba_ioex = sc->sc_ioex; pba.pba_memex = sc->sc_memex; pba.pba_pmemex = sc->sc_pmemex; pba.pba_domain = pa->pa_domain; pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata); pba.pba_bridgeih = sc->sc_ih; pba.pba_bridgetag = &sc->sc_tag; pba.pba_intrswiz = pa->pa_intrswiz; pba.pba_intrtag = pa->pa_intrtag; sc->sc_psc = config_found(self, &pba, ppbprint); }
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); }
/** * radeon_driver_load_kms - Main load function for KMS. * * @dev: drm dev pointer * @flags: device flags * * This is the main load function for KMS (all asics). * It calls radeon_device_init() to set up the non-display * parts of the chip (asic init, CP, writeback, etc.), and * radeon_modeset_init() to set up the display parts * (crtcs, encoders, hotplug detect, etc.). * Returns 0 on success, error on failure. */ void radeondrm_attach_kms(struct device *parent, struct device *self, void *aux) { struct radeon_device *rdev = (struct radeon_device *)self; struct drm_device *dev; struct pci_attach_args *pa = aux; const struct drm_pcidev *id_entry; int is_agp; pcireg_t type; uint8_t iobar; #if defined(__sparc64__) || defined(__macppc__) extern int fbnode; #endif id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist); rdev->flags = id_entry->driver_data; rdev->pc = pa->pa_pc; rdev->pa_tag = pa->pa_tag; rdev->iot = pa->pa_iot; rdev->memt = pa->pa_memt; rdev->dmat = pa->pa_dmat; #if defined(__sparc64__) || defined(__macppc__) if (fbnode == PCITAG_NODE(rdev->pa_tag)) rdev->console = 1; #else if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA && (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) { rdev->console = 1; #if NVGA > 0 vga_console_attached = 1; #endif } #endif #define RADEON_PCI_MEM 0x10 #define RADEON_PCI_IO 0x14 #define RADEON_PCI_MMIO 0x18 #define RADEON_PCI_IO2 0x20 type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM); if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM || pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) { printf(": can't get frambuffer info\n"); return; } if (PCI_MAPREG_MEM_TYPE(type) != PCI_MAPREG_MEM_TYPE_64BIT) iobar = RADEON_PCI_IO; else iobar = RADEON_PCI_IO2; if (pci_mapreg_map(pa, iobar, PCI_MAPREG_TYPE_IO, 0, NULL, &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0)) { printf(": can't map IO space\n"); return; } type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MMIO); if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM || pci_mapreg_map(pa, RADEON_PCI_MMIO, type, 0, NULL, &rdev->rmmio, &rdev->rmmio_base, &rdev->rmmio_size, 0)) { printf(": can't map mmio space\n"); return; } if (pci_intr_map(pa, &rdev->intrh) != 0) { printf(": couldn't map interrupt\n"); return; } printf(": %s\n", pci_intr_string(pa->pa_pc, rdev->intrh)); #ifdef notyet mtx_init(&rdev->swi_lock, IPL_TTY); #endif /* update BUS flag */ if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) { rdev->flags |= RADEON_IS_AGP; } else if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, NULL, NULL)) { rdev->flags |= RADEON_IS_PCIE; } else { rdev->flags |= RADEON_IS_PCI; } DRM_DEBUG("%s card detected\n", ((rdev->flags & RADEON_IS_AGP) ? "AGP" : (((rdev->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL); dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp, self); rdev->ddev = dev; rdev->irqh = pci_intr_establish(pa->pa_pc, rdev->intrh, IPL_TTY, radeon_driver_irq_handler_kms, rdev->ddev, rdev->dev.dv_xname); if (rdev->irqh == NULL) { printf("%s: couldn't establish interrupt\n", rdev->dev.dv_xname); return; } #ifdef __sparc64__ { struct rasops_info *ri; int node, console; node = PCITAG_NODE(pa->pa_tag); console = (fbnode == node); fb_setsize(&rdev->sf, 8, 1152, 900, node, 0); /* * The firmware sets up the framebuffer such that at starts at * an offset from the start of video memory. */ rdev->fb_offset = bus_space_read_4(rdev->memt, rdev->rmmio, RADEON_CRTC_OFFSET); if (bus_space_map(rdev->memt, rdev->fb_aper_offset + rdev->fb_offset, rdev->sf.sf_fbsize, BUS_SPACE_MAP_LINEAR, &rdev->memh)) { printf("%s: can't map video memory\n", rdev->dev.dv_xname); return; } ri = &rdev->sf.sf_ro; ri->ri_bits = bus_space_vaddr(rdev->memt, rdev->memh); ri->ri_hw = rdev; ri->ri_updatecursor = NULL; fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console); if (console) fbwscons_console_init(&rdev->sf, -1); } #endif rdev->shutdown = true; if (rootvp == NULL) mountroothook_establish(radeondrm_attachhook, rdev); else radeondrm_attachhook(rdev); }
void pci_attach_hook(struct device *parent, struct device *self, struct pcibus_attach_args *pba) { pci_chipset_tag_t pc = pba->pba_pc; pcitag_t tag; pcireg_t id, class; if (pba->pba_bus != 0) return; /* * In order to decide whether the system supports MSI we look * at the host bridge, which should be device 0 function 0 on * bus 0. It is better to not enable MSI on systems that * support it than the other way around, so be conservative * here. So we don't enable MSI if we don't find a host * bridge there. We also deliberately don't enable MSI on * chipsets from low-end manifacturers like VIA and SiS. */ tag = pci_make_tag(pc, 0, 0, 0); id = pci_conf_read(pc, tag, PCI_ID_REG); class = pci_conf_read(pc, tag, PCI_CLASS_REG); if (PCI_CLASS(class) != PCI_CLASS_BRIDGE || PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST) return; switch (PCI_VENDOR(id)) { case PCI_VENDOR_INTEL: /* * In the wonderful world of virtualization you can * have the latest 64-bit AMD multicore CPU behind a * prehistoric Intel host bridge. Give them what they * deserve. */ switch (PCI_PRODUCT(id)) { case PCI_PRODUCT_INTEL_82441FX: /* QEMU */ case PCI_PRODUCT_INTEL_82443BX: /* VMWare */ break; default: pba->pba_flags |= PCI_FLAGS_MSI_ENABLED; break; } break; case PCI_VENDOR_NVIDIA: case PCI_VENDOR_AMD: pba->pba_flags |= PCI_FLAGS_MSI_ENABLED; break; } /* * Don't enable MSI on a HyperTransport bus. In order to * determine that bus 0 is a HyperTransport bus, we look at * device 24 function 0, which is the HyperTransport * host/primary interface integrated on most 64-bit AMD CPUs. * If that device has a HyperTransport capability, bus 0 must * be a HyperTransport bus and we disable MSI. */ tag = pci_make_tag(pc, 0, 24, 0); if (pci_get_capability(pc, tag, PCI_CAP_HT, NULL, NULL)) pba->pba_flags &= ~PCI_FLAGS_MSI_ENABLED; }
static void ahd_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct ahd_softc *ahd = device_private(self); const struct ahd_pci_identity *entry; uint32_t devconfig; pcireg_t command; int error; pcireg_t subid; uint16_t subvendor; pcireg_t reg; int ioh_valid, ioh2_valid, memh_valid; pcireg_t memtype; pci_intr_handle_t ih; const char *intrstr; struct ahd_pci_busdata *bd; ahd->sc_dev = self; ahd_set_name(ahd, device_xname(self)); ahd->parent_dmat = pa->pa_dmat; command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); entry = ahd_find_pci_device(pa->pa_id, subid); if (entry == NULL) return; /* Keep information about the PCI bus */ bd = malloc(sizeof (struct ahd_pci_busdata), M_DEVBUF, M_NOWAIT); if (bd == NULL) { aprint_error("%s: unable to allocate bus-specific data\n", ahd_name(ahd)); return; } memset(bd, 0, sizeof(struct ahd_pci_busdata)); bd->pc = pa->pa_pc; bd->tag = pa->pa_tag; bd->func = pa->pa_function; bd->dev = pa->pa_device; ahd->bus_data = bd; ahd->description = entry->name; ahd->seep_config = malloc(sizeof(*ahd->seep_config), M_DEVBUF, M_NOWAIT); if (ahd->seep_config == NULL) { aprint_error("%s: cannot malloc seep_config!\n", ahd_name(ahd)); return; } memset(ahd->seep_config, 0, sizeof(*ahd->seep_config)); LIST_INIT(&ahd->pending_scbs); ahd_timer_init(&ahd->reset_timer); ahd_timer_init(&ahd->stat_timer); ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT; ahd->int_coalescing_stop_threshold = AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT; if (ahd_platform_alloc(ahd, NULL) != 0) { ahd_free(ahd); return; } /* * Record if this is an HP board. */ subvendor = PCI_VENDOR(subid); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; error = entry->setup(ahd, pa); if (error != 0) return; devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ ahd->bugs &= ~AHD_PCIX_BUG_MASK; } else { ahd->chip |= AHD_PCIX; } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; memh_valid = ioh_valid = ioh2_valid = 0; if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX, &bd->pcix_off, NULL)) { if (ahd->chip & AHD_PCIX) aprint_error_dev(self, "warning: can't find PCI-X capability\n"); ahd->chip &= ~AHD_PCIX; ahd->chip |= AHD_PCI; ahd->bugs &= ~AHD_PCIX_BUG_MASK; } /* * Map PCI Registers */ if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) { memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHD_PCI_MEMADDR); switch (memtype) { 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, AHD_PCI_MEMADDR, memtype, 0, &ahd->tags[0], &ahd->bshs[0], NULL, NULL) == 0); if (memh_valid) { ahd->tags[1] = ahd->tags[0]; bus_space_subregion(ahd->tags[0], ahd->bshs[0], /*offset*/0x100, /*size*/0x100, &ahd->bshs[1]); if (ahd_pci_test_register_access(ahd) != 0) memh_valid = 0; } break; default: memh_valid = 0; aprint_error("%s: unknown memory type: 0x%x\n", ahd_name(ahd), memtype); break; } if (memh_valid) { command &= ~PCI_COMMAND_IO_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); } #ifdef AHD_DEBUG printf("%s: doing memory mapping shs0 0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); #endif } if (command & PCI_COMMAND_IO_ENABLE) { /* First BAR */ ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR, PCI_MAPREG_TYPE_IO, 0, &ahd->tags[0], &ahd->bshs[0], NULL, NULL) == 0); /* 2nd BAR */ ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1, PCI_MAPREG_TYPE_IO, 0, &ahd->tags[1], &ahd->bshs[1], NULL, NULL) == 0); if (ioh_valid && ioh2_valid) { KASSERT(memh_valid == 0); command &= ~PCI_COMMAND_MEM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); } #ifdef AHD_DEBUG printf("%s: doing io mapping shs0 0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); #endif } if (memh_valid == 0 && (ioh_valid == 0 || ioh2_valid == 0)) { aprint_error("%s: unable to map registers\n", ahd_name(ahd)); return; } aprint_normal("\n"); aprint_naive("\n"); /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null)) && error != EOPNOTSUPP) { aprint_error_dev(self, "cannot activate %d\n", error); return; } /* * Should we bother disabling 39Bit addressing * based on installed memory? */ if (sizeof(bus_addr_t) > 4) ahd->flags |= AHD_39BIT_ADDRESSING; /* * If we need to support high memory, enable dual * address cycles. This bit must be set to enable * high address bit generation even if we are on a * 64bit bus (PCI64BIT set in devconfig). */ if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { uint32_t dvconfig; aprint_normal("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); dvconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); dvconfig |= DACEN; pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, dvconfig); } /* Ensure busmastering is enabled */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg | PCI_COMMAND_MASTER_ENABLE); ahd_softc_init(ahd); /* * Map the interrupt routines */ ahd->bus_intr = ahd_pci_intr; error = ahd_reset(ahd, /*reinit*/FALSE); if (error != 0) { ahd_free(ahd); return; } if (pci_intr_map(pa, &ih)) { aprint_error("%s: couldn't map interrupt\n", ahd_name(ahd)); ahd_free(ahd); return; } intrstr = pci_intr_string(pa->pa_pc, ih); ahd->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahd_intr, ahd); if (ahd->ih == NULL) { aprint_error("%s: couldn't establish interrupt", ahd_name(ahd)); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); ahd_free(ahd); return; } if (intrstr != NULL) aprint_normal("%s: interrupting at %s\n", ahd_name(ahd), intrstr); /* Get the size of the cache */ ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); ahd->pci_cachesize *= 4; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); /* See if we have a SEEPROM and perform auto-term */ error = ahd_check_extport(ahd); if (error != 0) return; /* Core initialization */ error = ahd_init(ahd); if (error != 0) return; /* * Link this softc in with all other ahd instances. */ ahd_attach(ahd); }
int agp_via_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; struct agp_softc *sc = device_private(self); struct agp_via_softc *asc; struct agp_gatt *gatt; pcireg_t agpsel, capval; asc = malloc(sizeof *asc, M_AGP, M_NOWAIT|M_ZERO); if (asc == NULL) { aprint_error(": can't allocate chipset-specific softc\n"); return ENOMEM; } sc->as_chipc = asc; sc->as_methods = &agp_via_methods; pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, &sc->as_capoff, &capval); if (PCI_CAP_AGP_MAJOR(capval) >= 3) { agpsel = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_VIA_AGPSEL); if ((agpsel & (1 << 9)) == 0) { asc->regs = via_v3_regs; aprint_debug(" (v3)"); } else { asc->regs = via_v2_regs; aprint_debug(" (v2 compat mode)"); } } else { asc->regs = via_v2_regs; aprint_debug(" (v2)"); } if (agp_map_aperture(pa, sc, AGP_APBASE) != 0) { aprint_error(": can't map aperture\n"); free(asc, M_AGP); return ENXIO; } asc->initial_aperture = AGP_GET_APERTURE(sc); for (;;) { gatt = agp_alloc_gatt(sc); if (gatt) break; /* * Probably contigmalloc failure. Try reducing the * aperture so that the gatt size reduces. */ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) { agp_generic_detach(sc); aprint_error(": can't set aperture size\n"); return ENOMEM; } } asc->gatt = gatt; if (asc->regs == via_v2_regs) { /* Install the gatt. */ pci_conf_write(pa->pa_pc, pa->pa_tag, asc->regs[REG_ATTBASE], gatt->ag_physical | 3); /* Enable the aperture. */ pci_conf_write(pa->pa_pc, pa->pa_tag, asc->regs[REG_GARTCTRL], 0x0000000f); } else { pcireg_t gartctrl; /* Install the gatt. */ pci_conf_write(pa->pa_pc, pa->pa_tag, asc->regs[REG_ATTBASE], gatt->ag_physical); /* Enable the aperture. */ gartctrl = pci_conf_read(pa->pa_pc, pa->pa_tag, asc->regs[REG_GARTCTRL]); pci_conf_write(pa->pa_pc, pa->pa_tag, asc->regs[REG_GARTCTRL], gartctrl | (3 << 7)); } return 0; }
void pchbattach(struct device *parent, struct device *self, void *aux) { struct pchb_softc *sc = (struct pchb_softc *)self; struct pci_attach_args *pa = aux; int has_agp = 0, i, r; switch (PCI_VENDOR(pa->pa_id)) { case PCI_VENDOR_AMD: printf("\n"); switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_AMD_AMD64_0F_HT: case PCI_PRODUCT_AMD_AMD64_10_HT: case PCI_PRODUCT_AMD_AMD64_11_HT: for (i = 0; i < AMD64HT_NUM_LDT; i++) pchb_amd64ht_attach(self, pa, i); break; } break; case PCI_VENDOR_INTEL: switch (PCI_PRODUCT(pa->pa_id)) { /* * As for Intel AGP, the host bridge is either in GFX mode * (internal graphics) or in AGP mode. In GFX mode, we pretend * to have AGP because the graphics memory access is very * similar and the AGP GATT code will deal with this. In the * latter case, the pci_get_capability(PCI_CAP_AGP) test below * will fire, so we do no harm by already setting the flag. */ /* AGP only */ case PCI_PRODUCT_INTEL_82915GM_HB: case PCI_PRODUCT_INTEL_82945GM_HB: case PCI_PRODUCT_INTEL_82945GME_HB: case PCI_PRODUCT_INTEL_82G965_HB: case PCI_PRODUCT_INTEL_82Q965_HB: case PCI_PRODUCT_INTEL_82GM965_HB: case PCI_PRODUCT_INTEL_82G33_HB: case PCI_PRODUCT_INTEL_82G35_HB: has_agp = 1; break; /* AGP + RNG */ case PCI_PRODUCT_INTEL_82915G_HB: case PCI_PRODUCT_INTEL_82945G_HB: has_agp = 1; /* FALLTHROUGH */ case PCI_PRODUCT_INTEL_82925X_HB: case PCI_PRODUCT_INTEL_82955X_HB: sc->sc_bt = pa->pa_memt; if (bus_space_map(sc->sc_bt, I82802_IOBASE, I82802_IOSIZE, 0, &sc->sc_bh)) break; /* probe and init rng */ if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_HWST) & I82802_RNG_HWST_PRESENT)) break; /* enable RNG */ bus_space_write_1(sc->sc_bt, sc->sc_bh, I82802_RNG_HWST, bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_HWST) | I82802_RNG_HWST_ENABLE); /* see if we can read anything */ for (i = 1000; i-- && !(bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV); ) DELAY(10); if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV)) break; r = bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_DATA); timeout_set(&sc->sc_rng_to, pchb_rnd, sc); sc->sc_rng_i = 4; pchb_rnd(sc); break; } printf("\n"); break; default: printf("\n"); break; } #if NAGP > 0 /* * If we haven't detected AGP yet (via a product ID), * then check for AGP capability on the device. */ if (has_agp || pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) != 0) { agp_set_pchb(pa); } #endif }
void bce_attach(struct device *parent, struct device *self, void *aux) { struct bce_softc *sc = (struct bce_softc *) self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; caddr_t kva; bus_dma_segment_t seg; int rseg; struct ifnet *ifp; pcireg_t memtype; bus_addr_t memaddr; bus_size_t memsize; int pmreg; pcireg_t pmode; int error; int i; sc->bce_pa = *pa; sc->bce_dmatag = pa->pa_dmat; /* * Map control/status registers. */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0); if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag, &sc->bce_bhandle, &memaddr, &memsize, 0)) { printf(": unable to find mem space\n"); return; } /* Get it out of power save mode if needed. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3; if (pmode == 3) { /* * The card has lost all configuration data in * this state, so punt. */ printf(": unable to wake up from power state D3\n"); return; } if (pmode != 0) { printf(": waking up from power state D%d\n", pmode); pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0); } } if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc, self->dv_xname); if (sc->bce_intrhand == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } /* reset the chip */ bce_reset(sc); /* * Allocate DMA-safe memory for ring descriptors. * The receive, and transmit rings can not share the same * 4k space, however both are allocated at once here. */ /* * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but * due to the limition above. ?? */ if ((error = bus_dmamem_alloc(sc->bce_dmatag, 2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE, &seg, 1, &rseg, BUS_DMA_NOWAIT))) { printf(": unable to alloc space for ring descriptors, " "error = %d\n", error); return; } /* map ring space to kernel */ if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg, 2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) { printf(": unable to map DMA buffers, error = %d\n", error); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* create a dma map for the ring */ if ((error = bus_dmamap_create(sc->bce_dmatag, 2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->bce_ring_map))) { printf(": unable to create ring DMA map, error = %d\n", error); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* connect the ring space to the dma map */ if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva, 2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) { printf(": unable to load ring DMA map\n"); bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* save the ring space in softc */ sc->bce_rx_ring = (struct bce_dma_slot *) kva; sc->bce_tx_ring = (struct bce_dma_slot *) (kva + PAGE_SIZE); /* Create the transmit buffer DMA maps. */ for (i = 0; i < BCE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) { printf(": unable to create tx DMA map, error = %d\n", error); } sc->bce_cdata.bce_tx_chain[i] = NULL; } /* Create the receive buffer DMA maps. */ for (i = 0; i < BCE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) { printf(": unable to create rx DMA map, error = %d\n", error); } sc->bce_cdata.bce_rx_chain[i] = NULL; } /* Set up ifnet structure */ ifp = &sc->bce_ac.ac_if; strlcpy(ifp->if_xname, sc->bce_dev.dv_xname, IF_NAMESIZE); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bce_ioctl; ifp->if_start = bce_start; ifp->if_watchdog = bce_watchdog; ifp->if_init = bce_init; IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = IFCAP_VLAN_MTU; /* MAC address */ sc->bce_ac.ac_enaddr[0] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET0); sc->bce_ac.ac_enaddr[1] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET1); sc->bce_ac.ac_enaddr[2] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET2); sc->bce_ac.ac_enaddr[3] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET3); sc->bce_ac.ac_enaddr[4] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET4); sc->bce_ac.ac_enaddr[5] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET5); printf(": %s, address %s\n", intrstr, ether_sprintf(sc->bce_ac.ac_enaddr)); /* Initialize our media structures and probe the MII. */ sc->bce_mii.mii_ifp = ifp; sc->bce_mii.mii_readreg = bce_mii_read; sc->bce_mii.mii_writereg = bce_mii_write; sc->bce_mii.mii_statchg = bce_statchg; ifmedia_init(&sc->bce_mii.mii_media, 0, bce_mediachange, bce_mediastatus); mii_attach(&sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) { ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO); /* get the phy */ sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_PHY) & 0x1f; /* * Enable activity led. * XXX This should be in a phy driver, but not currently. */ bce_mii_write((struct device *) sc, 1, 26, /* MAGIC */ bce_mii_read((struct device *) sc, 1, 26) & 0x7fff); /* MAGIC */ /* enable traffic meter led mode */ bce_mii_write((struct device *) sc, 1, 27, /* MAGIC */ bce_mii_read((struct device *) sc, 1, 27) | (1 << 6)); /* MAGIC */ /* Attach the interface */ if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->bce_timeout, bce_tick, sc); }
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; pcireg_t reg; int pmreg, ioh_valid, memh_valid; if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { reg = pci_conf_read(pa->pa_pc, pa->pa_tag, pmreg + PCI_PMCSR); switch (reg & PCI_PMCSR_STATE_MASK) { case PCI_PMCSR_STATE_D1: case PCI_PMCSR_STATE_D2: printf(": waking up from power state D%d\n%s", reg & PCI_PMCSR_STATE_MASK, sc->sc_dev.dv_xname); pci_conf_write(pa->pa_pc, pa->pa_tag, pmreg + PCI_PMCSR, (reg & ~PCI_PMCSR_STATE_MASK) | PCI_PMCSR_STATE_D0); break; case PCI_PMCSR_STATE_D3: printf("%s: unable to wake up from power state D3\n", sc->sc_dev.dv_xname); pci_conf_write(pa->pa_pc, pa->pa_tag, pmreg + PCI_PMCSR, (reg & ~PCI_PMCSR_STATE_MASK) | PCI_PMCSR_STATE_D0); 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, NULL, 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, NULL, 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("%s: unable to map device registers\n", sc->sc_dev.dv_xname); return; } sc->sc_dmat = pa->pa_dmat; /* Make sure bus mastering is enabled. */ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE); /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname); return; } 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("%s: unable to establish interrupt", sc->sc_dev.dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); return; } printf(": %s", intrstr); /* * Finish off the attach. */ sf_attach(sc); }
void puc_cardbus_attach(struct device *parent, struct device *self, void *aux) { struct puc_cardbus_softc *csc = (struct puc_cardbus_softc *)self; struct puc_softc *sc = &csc->sc_psc; struct cardbus_attach_args *ca = aux; struct cardbus_devfunc *ct = ca->ca_ct; cardbus_chipset_tag_t cc = ct->ct_cc; pci_chipset_tag_t pc = ca->ca_pc; cardbus_function_tag_t cf = ct->ct_cf; struct puc_attach_args paa; pcireg_t reg; int i; Cardbus_function_enable(ct); csc->ct = ct; reg = pci_conf_read(pc, ca->ca_tag, PCI_SUBSYS_ID_REG); sc->sc_desc = puc_find_description(PCI_VENDOR(ca->ca_id), PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg)); puc_print_ports(sc->sc_desc); /* the fifth one is some memory we dunno */ for (i = 0; i < PUC_NBARS; i++) { pcireg_t type; int bar; sc->sc_bar_mappings[i].mapped = 0; bar = PCI_MAPREG_START + 4 * i; if (!pci_mapreg_probe(pc, ca->ca_tag, bar, &type)) continue; if (!(sc->sc_bar_mappings[i].mapped = !Cardbus_mapreg_map(ct, bar, type, 0, &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h, &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s))) printf("%s: couldn't map BAR at offset 0x%lx\n", sc->sc_dev.dv_xname, (long)bar); sc->sc_bar_mappings[i].type = type; } csc->intrline = ca->ca_intrline; if (pci_get_capability(pc, ca->ca_tag, PCI_CAP_PWRMGMT, ®, 0)) { reg = pci_conf_read(pc, ca->ca_tag, reg + 4) & 3; if (reg) { printf("%s: awakening from state D%d\n", sc->sc_dev.dv_xname, reg); pci_conf_write(pc, ca->ca_tag, reg + 4, 0); } } (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); paa.puc = sc; paa.hwtype = COM_UART_OX16C950; /* XXX */ paa.intr_string = &puc_cardbus_intr_string; paa.intr_establish = &puc_cardbus_intr_establish; puc_common_attach(sc, &paa); }
void radeondrm_attach(struct device *parent, struct device *self, void *aux) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)self; struct pci_attach_args *pa = aux; struct vga_pci_bar *bar; const struct drm_pcidev *id_entry; int is_agp; id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist); dev_priv->flags = id_entry->driver_private; dev_priv->pc = pa->pa_pc; dev_priv->bst = pa->pa_memt; bar = vga_pci_bar_info((struct vga_pci_softc *)parent, 0); if (bar == NULL) { printf(": can't get frambuffer info\n"); return; } dev_priv->fb_aper_offset = bar->base; dev_priv->fb_aper_size = bar->maxsize; bar = vga_pci_bar_info((struct vga_pci_softc *)parent, 2); if (bar == NULL) { printf(": can't get BAR info\n"); return; } dev_priv->regs = vga_pci_bar_map((struct vga_pci_softc *)parent, bar->addr, 0, 0); if (dev_priv->regs == NULL) { printf(": can't map mmio space\n"); return; } if (pci_intr_map(pa, &dev_priv->ih) != 0) { printf(": couldn't map interrupt\n"); return; } printf(": %s\n", pci_intr_string(pa->pa_pc, dev_priv->ih)); mtx_init(&dev_priv->swi_lock, IPL_TTY); switch (dev_priv->flags & RADEON_FAMILY_MASK) { case CHIP_R100: case CHIP_RV200: case CHIP_R200: case CHIP_R300: case CHIP_R350: case CHIP_R420: case CHIP_R423: case CHIP_RV410: case CHIP_RV515: case CHIP_R520: case CHIP_RV570: case CHIP_R580: dev_priv->flags |= RADEON_HAS_HIERZ; break; default: /* all other chips have no hierarchical z buffer */ break; } dev_priv->chip_family = dev_priv->flags & RADEON_FAMILY_MASK; if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) dev_priv->flags |= RADEON_IS_AGP; else if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, NULL, NULL)) dev_priv->flags |= RADEON_IS_PCIE; else dev_priv->flags |= RADEON_IS_PCI; DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL); TAILQ_INIT(&dev_priv->gart_heap); TAILQ_INIT(&dev_priv->fb_heap); dev_priv->drmdev = drm_attach_pci(&radeondrm_driver, pa, is_agp, self); }