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 pci_mapreg_info(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) return (pci_io_find(pc, tag, reg, type, basep, sizep, flagsp)); else return (pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp)); }
/* * Decode a BAR register. */ int sti_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region, int bar) { bus_addr_t addr; bus_size_t size; u_int32_t cf; int rc; if (bar == 0) { sc->bases[region] = 0; return (0); } #ifdef DIAGNOSTIC if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) { sti_pci_disable_rom(sc); printf("%s: unexpected bar %02x for region %d\n", sc->sc_dev.dv_xname, bar, region); sti_pci_enable_rom(sc); } #endif cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) rc = pci_io_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size); else rc = pci_mem_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size, NULL); if (rc != 0) { sti_pci_disable_rom(sc); printf("%s: invalid bar %02x for region %d\n", sc->sc_dev.dv_xname, bar, region); sti_pci_enable_rom(sc); return (rc); } sc->bases[region] = addr; return (0); }
int pci_find_rom(struct pci_attach_args *pa, bus_space_tag_t bst, bus_space_handle_t bsh, int type, bus_space_handle_t *romh, bus_size_t *sz) { bus_size_t romsz, offset = 0, imagesz; uint16_t ptr; int done = 0; if (pci_mem_find(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, PCI_MAPREG_TYPE_ROM, NULL, &romsz, NULL)) return 1; /* * no upper bound check; i cannot imagine a 4GB ROM, but * it appears the spec would allow it! */ if (romsz < 1024) return 1; while (offset < romsz && !done){ struct pci_rom_header hdr; struct pci_rom rom; hdr.romh_magic = bus_space_read_2(bst, bsh, offset + offsetof (struct pci_rom_header, romh_magic)); hdr.romh_data_ptr = bus_space_read_2(bst, bsh, offset + offsetof (struct pci_rom_header, romh_data_ptr)); /* no warning: quite possibly ROM is simply not populated */ if (hdr.romh_magic != PCI_ROM_HEADER_MAGIC) return 1; ptr = offset + hdr.romh_data_ptr; if (ptr > romsz) { printf("pci_find_rom: rom data ptr out of range\n"); return 1; } rom.rom_signature = bus_space_read_4(bst, bsh, ptr); rom.rom_vendor = bus_space_read_2(bst, bsh, ptr + offsetof(struct pci_rom, rom_vendor)); rom.rom_product = bus_space_read_2(bst, bsh, ptr + offsetof(struct pci_rom, rom_product)); rom.rom_class = bus_space_read_1(bst, bsh, ptr + offsetof (struct pci_rom, rom_class)); rom.rom_subclass = bus_space_read_1(bst, bsh, ptr + offsetof (struct pci_rom, rom_subclass)); rom.rom_interface = bus_space_read_1(bst, bsh, ptr + offsetof (struct pci_rom, rom_interface)); rom.rom_len = bus_space_read_2(bst, bsh, ptr + offsetof (struct pci_rom, rom_len)); rom.rom_code_type = bus_space_read_1(bst, bsh, ptr + offsetof (struct pci_rom, rom_code_type)); rom.rom_indicator = bus_space_read_1(bst, bsh, ptr + offsetof (struct pci_rom, rom_indicator)); if (rom.rom_signature != PCI_ROM_SIGNATURE) { printf("pci_find_rom: bad rom data signature\n"); return 1; } imagesz = rom.rom_len * 512; if ((rom.rom_vendor == PCI_VENDOR(pa->pa_id)) && (rom.rom_product == PCI_PRODUCT(pa->pa_id)) && (rom.rom_class == PCI_CLASS(pa->pa_class)) && (rom.rom_subclass == PCI_SUBCLASS(pa->pa_class)) && (rom.rom_interface == PCI_INTERFACE(pa->pa_class)) && (rom.rom_code_type == type)) { *sz = imagesz; bus_space_subregion(bst, bsh, offset, imagesz, romh); return 0; } /* last image check */ if (rom.rom_indicator & PCI_ROM_INDICATOR_LAST) return 1; /* offset by size */ offset += imagesz; } return 1; }
int pci_mapreg_submap(struct pci_attach_args *pa, int reg, pcireg_t type, int busflags, bus_size_t maxsize, bus_size_t offset, bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep) { bus_space_tag_t tag; bus_space_handle_t handle; bus_addr_t base; bus_size_t size; int flags; if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) { if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0) return (1); if (pci_io_find(pa->pa_pc, pa->pa_tag, reg, type, &base, &size, &flags)) return (1); tag = pa->pa_iot; } else { if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0) return (1); if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg, type, &base, &size, &flags)) return (1); tag = pa->pa_memt; } if (reg == PCI_MAPREG_ROM) { pcireg_t mask; int s; /* we have to enable the ROM address decoder... */ s = splhigh(); mask = pci_conf_read(pa->pa_pc, pa->pa_tag, reg); mask |= PCI_MAPREG_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, reg, mask); splx(s); } /* If we're called with maxsize/offset of 0, behave like * pci_mapreg_map. */ maxsize = (maxsize && offset) ? maxsize : size; base += offset; if ((maxsize < size && offset + maxsize <= size) || offset != 0) return (1); if (bus_space_map(tag, base, maxsize, busflags | flags, &handle)) return (1); if (tagp != 0) *tagp = tag; if (handlep != 0) *handlep = handle; if (basep != 0) *basep = base; if (sizep != 0) *sizep = maxsize; return (0); }
void sdhc_pci_attach(struct device *parent, struct device *self, void *aux) { struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; char const *intrstr; int slotinfo; int nslots; int usedma; int reg; bus_space_tag_t iot; bus_space_handle_t ioh; bus_size_t size; u_int32_t caps = 0; /* Some TI controllers needs special treatment. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD && pa->pa_function == 4) sdhc_takecontroller(pa); /* ENE controllers break if set to 0V bus power. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENE && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD) sc->sc.sc_flags |= SDHC_F_NOPWR0; /* Some RICOH controllers need to be bumped into the right mode. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823) { /* Enable SD2.0 mode. */ sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0xfc); sdhc_pci_conf_write(pa, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20); sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0x00); /* * Some SD/MMC cards don't work with the default base * clock frequency of 200MHz. Lower it to 50Hz. */ sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x01); sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ, 50); sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00); } if (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, sdhc_intr, sc, sc->sc.sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt\n"); return; } printf(": %s\n", intrstr); /* Enable use of DMA if supported by the interface. */ usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA; /* * Map and attach all hosts supported by the host controller. */ slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag, SDHC_PCI_CONF_SLOT_INFO); nslots = SDHC_PCI_NUM_SLOTS(slotinfo); /* Allocate an array big enough to hold all the possible hosts */ sc->sc.sc_host = malloc(sizeof(struct sdhc_host *) * nslots, M_DEVBUF, M_WAITOK); /* XXX: handle 64-bit BARs */ for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) * sizeof(u_int32_t); reg < SDHC_PCI_BAR_END && nslots > 0; reg += sizeof(u_int32_t), nslots--) { if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg, NULL, NULL, NULL) != 0) continue; if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_MEM, 0, &iot, &ioh, NULL, &size, 0)) { printf("%s at 0x%x: can't map registers\n", sc->sc.sc_dev.dv_xname, reg); continue; } if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, caps) != 0) /* XXX: sc->sc_host leak */ printf("%s at 0x%x: can't initialize host\n", sc->sc.sc_dev.dv_xname, reg); } }