/* * Prepare dev->bars to be used for information. we do this at startup * so we can do the whole array at once, dealing with 64-bit BARs correctly. */ void vga_pci_bar_init(struct vga_pci_softc *dev, struct pci_attach_args *pa) { pcireg_t type; int addr = PCI_MAPREG_START, i = 0; memcpy(&dev->pa, pa, sizeof(dev->pa)); while (i < VGA_PCI_MAX_BARS) { dev->bars[i] = malloc(sizeof((*dev->bars[i])), M_DEVBUF, M_NOWAIT | M_ZERO); if (dev->bars[i] == NULL) { return; } dev->bars[i]->addr = addr; type = dev->bars[i]->maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, addr); if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, addr, dev->bars[i]->maptype, &dev->bars[i]->base, &dev->bars[i]->maxsize, &dev->bars[i]->flags) != 0) { free(dev->bars[i], M_DEVBUF); dev->bars[i] = NULL; } if (type == PCI_MAPREG_MEM_TYPE_64BIT) { addr += 8; i += 2; } else { addr += 4; i++; } } }
/* * Init memory and i/o bus space tags. Map device registers. * Use memory space mapped i/o space access for i/o registers * for CyberPro cards. */ static int igsfb_pci_map_regs(struct igsfb_devconfig *dc, bus_space_tag_t iot, bus_space_tag_t memt, pci_chipset_tag_t pc, pcitag_t tag, pci_product_id_t id) { dc->dc_id = id; /* * Configure memory space first since for CyberPro we use * memory-mapped i/o access. Note that we are NOT mapping any * of it yet. (XXX: search for memory BAR?) */ #define IGS_MEM_MAPREG (PCI_MAPREG_START + 0) dc->dc_memt = memt; if (pci_mapreg_info(pc, tag, IGS_MEM_MAPREG, PCI_MAPREG_TYPE_MEM, &dc->dc_memaddr, &dc->dc_memsz, &dc->dc_memflags) != 0) { printf("unable to configure memory space\n"); return 1; } /* * Configure I/O space. On CyberPro use MMIO. IGS 168x doesn't * have a BAR for its i/o space, so we have to hardcode it. */ if (id >= PCI_PRODUCT_INTEGRAPHICS_CYBERPRO2000) { dc->dc_iot = dc->dc_memt; dc->dc_iobase = dc->dc_memaddr | IGS_MEM_MMIO_SELECT; dc->dc_ioflags = dc->dc_memflags; } else { dc->dc_iot = iot; dc->dc_iobase = 0; dc->dc_ioflags = 0; } /* * Map I/O registers. This is done in bus glue, not in common * code because on e.g. ISA bus we'd need to access registers * to obtain/program linear memory location. */ if (bus_space_map(dc->dc_iot, dc->dc_iobase + IGS_REG_BASE, IGS_REG_SIZE, dc->dc_ioflags, &dc->dc_ioh) != 0) { printf("unable to map I/O registers\n"); return 1; } return 0; }
void mq200_pci_attach(struct device *parent, struct device *self, void *aux) { struct mq200_pci_softc *psc = (void *) self; struct mq200_softc *sc = &psc->sc_mq200; struct pci_attach_args *pa = aux; int res; psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; /* check whether it is disabled by firmware */ if (!(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) & PCI_COMMAND_MEM_ENABLE)) { printf("%s: disabled\n", sc->sc_dev.dv_xname); return; } /* Base Address Register 0: base address of control registers */ res = pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_iot, &sc->sc_ioh, NULL, NULL); if (res != 0) { printf("%s: can't map registers\n", sc->sc_dev.dv_xname); return; } /* Base Address Register 1: base address of frame buffer */ res = pci_mapreg_info(psc->sc_pc, psc->sc_pcitag, PCI_MAPREG_START+4, PCI_MAPREG_TYPE_MEM, &sc->sc_baseaddr, NULL, NULL); if (res != 0) { printf("%s: can't map frame buffer\n", sc->sc_dev.dv_xname); return; } mq200_attach(sc); }
static void b3_617_attach(device_t parent, device_t self, void *aux) { struct b3_617_softc *sc = device_private(self); struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr; struct vmebus_attach_args vaa; sc->sc_dev = self; sc->sc_pc = pc; sc->sc_dmat = pa->pa_dmat; pci_aprint_devinfo_fancy(pa, "VME bus adapter", "BIT3 PCI-VME 617", 1); /* * Map CSR and mapping table spaces. * Don't map VME window; parts are mapped as needed to * save kernel virtual memory space */ if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->csrt, &sc->csrh, NULL, NULL) && pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->csrt, &sc->csrh, NULL, NULL)) { aprint_error_dev(self, "can't map CSR space\n"); return; } if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->mapt, &sc->maph, NULL, NULL)) { aprint_error_dev(self, "can't map map space\n"); return; } if (pci_mapreg_info(pc, pa->pa_tag, 0x1c, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, &sc->vmepbase, 0, 0)) { aprint_error_dev(self, "can't get VME range\n"); return; } sc->sc_vmet = pa->pa_memt; /* XXX needed for VME mappings */ /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); /* * Use a low interrupt level (the lowest?). * We will raise before calling a subdevice's handler. */ sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, b3_617_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); if (b3_617_init(sc)) return; /* * set up all the tags for use by VME devices */ sc->sc_vct.cookie = self; sc->sc_vct.vct_probe = b3_617_vme_probe; sc->sc_vct.vct_map = b3_617_map_vme; sc->sc_vct.vct_unmap = b3_617_unmap_vme; sc->sc_vct.vct_int_map = b3_617_map_vmeint; sc->sc_vct.vct_int_establish = b3_617_establish_vmeint; sc->sc_vct.vct_int_disestablish = b3_617_disestablish_vmeint; sc->sc_vct.vct_dmamap_create = b3_617_dmamap_create; sc->sc_vct.vct_dmamap_destroy = b3_617_dmamap_destroy; sc->sc_vct.vct_dmamem_alloc = b3_617_dmamem_alloc; sc->sc_vct.vct_dmamem_free = b3_617_dmamem_free; vaa.va_vct = &(sc->sc_vct); vaa.va_bdt = pa->pa_dmat; vaa.va_slaveconfig = b3_617_slaveconfig; sc->csrwindow.offset = -1; sc->dmawindow24.offset = -1; sc->dmawindow32.offset = -1; config_found(self, &vaa, 0); }
void puc_pci_attach(struct device *parent, struct device *self, void *aux) { struct puc_pci_softc *psc = (struct puc_pci_softc *)self; struct puc_softc *sc = &psc->sc_psc; struct pci_attach_args *pa = aux; struct puc_attach_args paa; pcireg_t subsys; int i; subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); sc->sc_desc = puc_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys)); puc_print_ports(sc->sc_desc); 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(pa->pa_pc, pa->pa_tag, bar, &type)) continue; sc->sc_bar_mappings[i].mapped = (pci_mapreg_map(pa, 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, 0) == 0); if (sc->sc_bar_mappings[i].mapped) continue; /* * If a port on this card is used as serial console, * mapping the associated BAR will fail because the * bus space is already mapped. In that case, we try * to re-use the already existing mapping. * Unfortunately this means that if a BAR is used to * support multiple ports, only the first port will * work. */ if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, type, &sc->sc_bar_mappings[i].a, NULL, NULL) == 0 && pa->pa_iot == comconsiot && sc->sc_bar_mappings[i].a == comconsaddr) { sc->sc_bar_mappings[i].t = comconsiot; sc->sc_bar_mappings[i].h = comconsioh; sc->sc_bar_mappings[i].s = COM_NPORTS; sc->sc_bar_mappings[i].mapped = 1; continue; } printf("%s: couldn't map BAR at offset 0x%lx\n", sc->sc_dev.dv_xname, (long)bar); } /* Map interrupt. */ psc->pc = pa->pa_pc; if (pci_intr_map(pa, &psc->ih)) { printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); return; } paa.puc = sc; paa.intr_string = &puc_pci_intr_string; paa.intr_establish = &puc_pci_intr_establish; puc_common_attach(sc, &paa); }
/*static*/ void ndis_attach_pci(device_t parent, device_t self, void *aux) { struct ndis_softc *sc = device_private(self); struct pci_attach_args *pa = aux; #ifdef NDIS_DBG char devinfo[256]; #endif pci_intr_handle_t ih; pcireg_t type; bus_addr_t base; bus_size_t size; int flags; ndis_resource_list *rl = NULL; struct cm_partial_resource_desc *prd = NULL; #ifdef NDIS_DBG struct pci_conf_state conf_state; int revision, i; #endif int bar; size_t rllen; printf("in ndis_attach_pci()\n"); /* initalize the softc */ //sc->ndis_hardware_type = NDIS_PCI; sc->ndis_dev = self; sc->ndis_iftype = PCIBus; sc->ndis_res_pc = pa->pa_pc; sc->ndis_res_pctag = pa->pa_tag; /* TODO: is this correct? All are just pa->pa_dmat? */ sc->ndis_mtag = pa->pa_dmat; sc->ndis_ttag = pa->pa_dmat; sc->ndis_parent_tag = pa->pa_dmat; sc->ndis_res_io = NULL; sc->ndis_res_mem = NULL; sc->ndis_res_altmem = NULL; sc->ndis_block = NULL; sc->ndis_shlist = NULL; ndis_in_isr = FALSE; printf("sc->ndis_mtag = %x\n", (unsigned int)sc->ndis_mtag); rllen = sizeof(ndis_resource_list) + sizeof(cm_partial_resource_desc) * (MAX_RESOURCES - 1); rl = malloc(rllen, M_DEVBUF, M_NOWAIT|M_ZERO); if(rl == NULL) { sc->error = ENOMEM; //printf("error: out of memory\n"); return; } rl->cprl_version = 5; rl->cprl_version = 1; rl->cprl_count = 0; prd = rl->cprl_partial_descs; #ifdef NDIS_DBG pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof devinfo); revision = PCI_REVISION(pa->pa_class); printf(": %s (rev. 0x%02x)\n", devinfo, revision); pci_conf_print(sc->ndis_res_pc, sc->ndis_res_pctag, NULL); pci_conf_capture(sc->ndis_res_pc, sc->ndis_res_pctag, &conf_state); for(i=0; i<16; i++) { printf("conf_state.reg[%d] = %x\n", i, conf_state.reg[i]); } #endif /* just do the conversion work in attach instead of calling ndis_convert_res() */ for(bar = 0x10; bar <= 0x24; bar += 0x04) { type = pci_mapreg_type(sc->ndis_res_pc, sc->ndis_res_pctag, bar); if(pci_mapreg_info(sc->ndis_res_pc, sc->ndis_res_pctag, bar, type, &base, &size, &flags)) { printf("pci_mapreg_info() failed on BAR 0x%x!\n", bar); } else { switch(type) { case PCI_MAPREG_TYPE_IO: prd->cprd_type = CmResourceTypePort; prd->cprd_flags = CM_RESOURCE_PORT_IO; prd->u.cprd_port.cprd_start.np_quad = (uint64_t)base; prd->u.cprd_port.cprd_len = (uint32_t)size; if((sc->ndis_res_io = malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { //printf("error: out of memory\n"); sc->error = ENOMEM; goto out; } sc->ndis_res_io->res_base = base; sc->ndis_res_io->res_size = size; sc->ndis_res_io->res_tag = x86_bus_space_io; bus_space_map(sc->ndis_res_io->res_tag, sc->ndis_res_io->res_base, sc->ndis_res_io->res_size, flags, &sc->ndis_res_io->res_handle); break; case PCI_MAPREG_TYPE_MEM: prd->cprd_type = CmResourceTypeMemory; prd->cprd_flags = CM_RESOURCE_MEMORY_READ_WRITE; prd->u.cprd_mem.cprd_start.np_quad = (uint64_t)base; prd->u.cprd_mem.cprd_len = (uint32_t)size; if(sc->ndis_res_mem != NULL && sc->ndis_res_altmem != NULL) { printf("too many resources\n"); sc->error = ENXIO; goto out; } if(sc->ndis_res_mem) { if((sc->ndis_res_altmem = malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { sc->error = ENOMEM; return; } sc->ndis_res_altmem->res_base = base; sc->ndis_res_altmem->res_size = size; sc->ndis_res_altmem->res_tag = x86_bus_space_mem; if(bus_space_map(sc->ndis_res_altmem->res_tag, sc->ndis_res_altmem->res_base, sc->ndis_res_altmem->res_size, flags|BUS_SPACE_MAP_LINEAR, &sc->ndis_res_altmem->res_handle)) { printf("bus_space_map failed\n"); } } else { if((sc->ndis_res_mem = malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { sc->error = ENOMEM; goto out; } sc->ndis_res_mem->res_base = base; sc->ndis_res_mem->res_size = size; sc->ndis_res_mem->res_tag = x86_bus_space_mem; if(bus_space_map(sc->ndis_res_mem->res_tag, sc->ndis_res_mem->res_base, sc->ndis_res_mem->res_size, flags|BUS_SPACE_MAP_LINEAR, &sc->ndis_res_mem->res_handle)) { printf("bus_space_map failed\n"); } } break; default: printf("unknown type\n"); } prd->cprd_sharedisp = CmResourceShareDeviceExclusive; rl->cprl_count++; prd++; } } /* add the interrupt to the list */ prd->cprd_type = CmResourceTypeInterrupt; prd->cprd_flags = 0; /* TODO: is this all we need to save for the interrupt? */ prd->u.cprd_intr.cprd_level = pa->pa_intrline; prd->u.cprd_intr.cprd_vector = pa->pa_intrline; prd->u.cprd_intr.cprd_affinity = 0; rl->cprl_count++; pci_intr_map(pa, &ih); sc->ndis_intrhand = pci_intr_establish(pa->pa_pc, ih, IPL_NET /*| PCATCH*/, ndis_intr, sc); sc->ndis_irq = (void *)sc->ndis_intrhand; printf("pci interrupt: %s\n", pci_intr_string(pa->pa_pc, ih)); /* save resource list in the softc */ sc->ndis_rl = rl; sc->ndis_rescnt = rl->cprl_count; kthread_create(PRI_NONE, 0, NULL, ndis_attach, (void *)sc, NULL, "ndis_attach"); return; out: free(rl, M_DEVBUF); return; }
int pci_probe_device(struct pci_softc *sc, pcitag_t tag, int (*match)(const struct pci_attach_args *), struct pci_attach_args *pap) { pci_chipset_tag_t pc = sc->sc_pc; struct pci_attach_args pa; pcireg_t id, /* csr, */ pciclass, intr, bhlcr, bar, endbar; #ifdef __HAVE_PCI_MSI_MSIX pcireg_t cap; int off; #endif int ret, pin, bus, device, function, i, width; int locs[PCICF_NLOCS]; pci_decompose_tag(pc, tag, &bus, &device, &function); /* a driver already attached? */ if (sc->PCI_SC_DEVICESC(device, function).c_dev != NULL && !match) return 0; bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); if (PCI_HDRTYPE_TYPE(bhlcr) > 2) return 0; id = pci_conf_read(pc, tag, PCI_ID_REG); /* csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); */ pciclass = pci_conf_read(pc, tag, PCI_CLASS_REG); /* Invalid vendor ID value? */ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) return 0; /* XXX Not invalid, but we've done this ~forever. */ if (PCI_VENDOR(id) == 0) return 0; /* Collect memory range info */ memset(sc->PCI_SC_DEVICESC(device, function).c_range, 0, sizeof(sc->PCI_SC_DEVICESC(device, function).c_range)); i = 0; switch (PCI_HDRTYPE_TYPE(bhlcr)) { case PCI_HDRTYPE_PPB: endbar = PCI_MAPREG_PPB_END; break; case PCI_HDRTYPE_PCB: endbar = PCI_MAPREG_PCB_END; break; default: endbar = PCI_MAPREG_END; break; } for (bar = PCI_MAPREG_START; bar < endbar; bar += width) { struct pci_range *r; pcireg_t type; width = 4; if (pci_mapreg_probe(pc, tag, bar, &type) == 0) continue; if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) { if (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT) width = 8; r = &sc->PCI_SC_DEVICESC(device, function).c_range[i++]; if (pci_mapreg_info(pc, tag, bar, type, &r->r_offset, &r->r_size, &r->r_flags) != 0) break; if ((PCI_VENDOR(id) == PCI_VENDOR_ATI) && (bar == 0x10) && (r->r_size == 0x1000000)) { struct pci_range *nr; /* * this has to be a mach64 * split things up so each half-aperture can * be mapped PREFETCHABLE except the last page * which may contain registers */ r->r_size = 0x7ff000; r->r_flags = BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE; nr = &sc->PCI_SC_DEVICESC(device, function).c_range[i++]; nr->r_offset = r->r_offset + 0x800000; nr->r_size = 0x7ff000; nr->r_flags = BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE; } } } pa.pa_iot = sc->sc_iot; pa.pa_memt = sc->sc_memt; pa.pa_dmat = sc->sc_dmat; pa.pa_dmat64 = sc->sc_dmat64; pa.pa_pc = pc; pa.pa_bus = bus; pa.pa_device = device; pa.pa_function = function; pa.pa_tag = tag; pa.pa_id = id; pa.pa_class = pciclass; /* * Set up memory, I/O enable, and PCI command flags * as appropriate. */ pa.pa_flags = sc->sc_flags; /* * If the cache line size is not configured, then * clear the MRL/MRM/MWI command-ok flags. */ if (PCI_CACHELINE(bhlcr) == 0) { pa.pa_flags &= ~(PCI_FLAGS_MRL_OKAY| PCI_FLAGS_MRM_OKAY|PCI_FLAGS_MWI_OKAY); } if (sc->sc_bridgetag == NULL) { pa.pa_intrswiz = 0; pa.pa_intrtag = tag; } else { pa.pa_intrswiz = sc->sc_intrswiz + device; pa.pa_intrtag = sc->sc_intrtag; } intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); pin = PCI_INTERRUPT_PIN(intr); pa.pa_rawintrpin = pin; if (pin == PCI_INTERRUPT_PIN_NONE) { /* no interrupt */ pa.pa_intrpin = 0; } else { /* * swizzle it based on the number of busses we're * behind and our device number. */ pa.pa_intrpin = /* XXX */ ((pin + pa.pa_intrswiz - 1) % 4) + 1; } pa.pa_intrline = PCI_INTERRUPT_LINE(intr); #ifdef __HAVE_PCI_MSI_MSIX if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSIMAP, &off, &cap)) { /* * XXX Should we enable MSI mapping ourselves on * systems that have it disabled? */ if (cap & PCI_HT_MSI_ENABLED) { uint64_t addr; if ((cap & PCI_HT_MSI_FIXED) == 0) { addr = pci_conf_read(pc, tag, off + PCI_HT_MSI_ADDR_LO); addr |= (uint64_t)pci_conf_read(pc, tag, off + PCI_HT_MSI_ADDR_HI) << 32; } else addr = PCI_HT_MSI_FIXED_ADDR; /* * XXX This will fail to enable MSI on systems * that don't use the canonical address. */ if (addr == PCI_HT_MSI_FIXED_ADDR) { pa.pa_flags |= PCI_FLAGS_MSI_OKAY; pa.pa_flags |= PCI_FLAGS_MSIX_OKAY; } } } #endif if (match != NULL) { ret = (*match)(&pa); if (ret != 0 && pap != NULL) *pap = pa; } else { struct pci_child *c; locs[PCICF_DEV] = device; locs[PCICF_FUNCTION] = function; c = &sc->PCI_SC_DEVICESC(device, function); pci_conf_capture(pc, tag, &c->c_conf); if (pci_get_powerstate(pc, tag, &c->c_powerstate) == 0) c->c_psok = true; else c->c_psok = false; c->c_dev = config_found_sm_loc(sc->sc_dev, "pci", locs, &pa, pciprint, config_stdsubmatch); ret = (c->c_dev != NULL); } return ret; }
void sbbc_attach(struct device *parent, struct device *self, void *aux) { struct sbbc_softc *sc = (void *)self; struct pci_attach_args *pa = aux; struct sbbc_sram_toc *toc; bus_addr_t base; bus_size_t size; pci_intr_handle_t ih; int chosen, iosram; int i; /* XXX Don't byteswap. */ sc->sc_bbt = *pa->pa_memt; sc->sc_bbt.sasi = ASI_PRIMARY; sc->sc_iot = &sc->sc_bbt; if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, SBBC_PCI_BAR, PCI_MAPREG_TYPE_MEM, &base, &size, NULL)) { printf(": can't find register space\n"); return; } if (bus_space_map(sc->sc_iot, base + SBBC_REGS_OFFSET, SBBC_REGS_SIZE, 0, &sc->sc_regs_ioh)) { printf(": can't map register space\n"); return; } if (bus_space_map(sc->sc_iot, base + SBBC_EPLD_OFFSET, SBBC_EPLD_SIZE, 0, &sc->sc_epld_ioh)) { printf(": can't map EPLD registers\n"); goto unmap_regs; } if (bus_space_map(sc->sc_iot, base + SBBC_SRAM_OFFSET, SBBC_SRAM_SIZE, 0, &sc->sc_sram_ioh)) { printf(": can't map SRAM\n"); goto unmap_epld; } if (pci_intr_map(pa, &ih)) { printf(": unable to map interrupt\n"); goto unmap_sram; } printf(": %s\n", pci_intr_string(pa->pa_pc, ih)); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, sbbc_intr, sc, sc->sc_dv.dv_xname); if (sc->sc_ih == NULL) { printf("%s: unable to establish interrupt\n", sc->sc_dv.dv_xname); goto unmap_sram; } bus_space_write_4(sc->sc_iot, sc->sc_regs_ioh, SBBC_PCI_INT_ENABLE, SBBC_PCI_ENABLE_INT_A); /* Check if we are the chosen one. */ chosen = OF_finddevice("/chosen"); if (OF_getprop(chosen, "iosram", &iosram, sizeof(iosram)) <= 0 || PCITAG_NODE(pa->pa_tag) != iosram) return; /* SRAM TOC offset defaults to 0. */ if (OF_getprop(chosen, "iosram-toc", &sc->sc_sram_toc, sizeof(sc->sc_sram_toc)) <= 0) sc->sc_sram_toc = 0; sc->sc_sram = bus_space_vaddr(sc->sc_iot, sc->sc_sram_ioh); toc = (struct sbbc_sram_toc *)(sc->sc_sram + sc->sc_sram_toc); for (i = 0; i < toc->toc_ntags; i++) { if (strcmp(toc->toc_tag[i].tag_key, "SOLSCIE") == 0) sc->sc_sram_solscie = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); if (strcmp(toc->toc_tag[i].tag_key, "SOLSCIR") == 0) sc->sc_sram_solscir = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); if (strcmp(toc->toc_tag[i].tag_key, "SCSOLIE") == 0) sc->sc_sram_scsolie = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); if (strcmp(toc->toc_tag[i].tag_key, "SCSOLIR") == 0) sc->sc_sram_scsolir = (uint32_t *) (sc->sc_sram + toc->toc_tag[i].tag_offset); } for (i = 0; i < toc->toc_ntags; i++) { if (strcmp(toc->toc_tag[i].tag_key, "TODDATA") == 0) sbbc_attach_tod(sc, toc->toc_tag[i].tag_offset); if (strcmp(toc->toc_tag[i].tag_key, "SOLCONS") == 0) sbbc_attach_cons(sc, toc->toc_tag[i].tag_offset); } return; unmap_sram: bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_SRAM_SIZE); unmap_epld: bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_EPLD_SIZE); unmap_regs: bus_space_unmap(sc->sc_iot, sc->sc_sram_ioh, SBBC_REGS_SIZE); }
/** * 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); }
/** * 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__) pcireg_t addr, mask; int s; #endif #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 } #if NEFIFB > 0 if (efifb_is_console(pa)) { rdev->console = 1; efifb_cndetach(); } #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 !defined(__sparc64__) /* * Make sure we have a base address for the ROM such that we * can map it later. */ s = splhigh(); addr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE); mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, addr); splx(s); if (addr == 0 && PCI_ROM_SIZE(mask) != 0 && pa->pa_memex) { bus_size_t size, start, end; bus_addr_t base; size = PCI_ROM_SIZE(mask); start = max(PCI_MEM_START, pa->pa_memex->ex_start); end = min(PCI_MEM_END, pa->pa_memex->ex_end); if (extent_alloc_subregion(pa->pa_memex, start, end, size, size, 0, 0, 0, &base) == 0) pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, base); } #endif #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); printf("\n"); kms_driver.num_ioctls = radeon_max_kms_ioctl; dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp, rdev->console, self); rdev->ddev = dev; rdev->pdev = dev->pdev; rdev->family = rdev->flags & RADEON_FAMILY_MASK; if (!radeon_msi_ok(rdev)) pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED; rdev->msi_enabled = 0; if (pci_intr_map_msi(pa, &rdev->intrh) == 0) rdev->msi_enabled = 1; else if (pci_intr_map(pa, &rdev->intrh) != 0) { printf(": couldn't map interrupt\n"); return; } printf("%s: %s\n", rdev->dev.dv_xname, pci_intr_string(pa->pa_pc, rdev->intrh)); 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; config_mountroot(self, radeondrm_attachhook); }
void gfxp_attach(struct device *parent, struct device *self, void *aux) { struct gfxp_softc *sc = (struct gfxp_softc *)self; struct pci_attach_args *pa = aux; struct rasops_info *ri; int node, console, flags; char *model; sc->sc_pcitag = pa->pa_tag; node = PCITAG_NODE(pa->pa_tag); console = gfxp_is_console(node); printf("\n"); model = getpropstring(node, "model"); printf("%s: %s", self->dv_xname, model); if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PM2_PCI_MEM_LE, PCI_MAPREG_TYPE_MEM, &sc->sc_membase_le, &sc->sc_memsize_le, NULL)) sc->sc_memsize_le = 0; if (pci_mapreg_map(pa, PM2_PCI_MEM_BE, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, &sc->sc_membase_be, &sc->sc_memsize_be, 0)) { printf("\n%s: can't map video memory\n", self->dv_xname); return; } if (pci_mapreg_map(pa, PM2_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, &sc->sc_mmiosize, 0)) { bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize_be); printf("\n%s: can't map mmio\n", self->dv_xname); return; } fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); ri = &sc->sc_sunfb.sf_ro; ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); ri->ri_hw = sc; flags = RI_BSWAP; if (sc->sc_sunfb.sf_depth == 32) { ri->ri_rnum = 8; ri->ri_rpos = 16; ri->ri_gnum = 8; ri->ri_gpos = 8; ri->ri_bnum = 8; ri->ri_bpos = 0; flags &= ~RI_BSWAP; } fbwscons_init(&sc->sc_sunfb, flags, console); fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); sc->sc_mode = WSDISPLAYIO_MODE_EMUL; gfxp_init(sc); ri->ri_ops.copyrows = gfxp_copyrows; ri->ri_ops.copycols = gfxp_copycols; ri->ri_ops.eraserows = gfxp_eraserows; ri->ri_ops.erasecols = gfxp_erasecols; if (console) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &gfxp_accessops, console); }
int pci_mapreg_map(struct pci_attach_args *pa, int reg, pcireg_t type, int busflags, bus_space_tag_t *tagp, bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep, bus_size_t maxsize) { bus_space_tag_t tag; bus_space_handle_t handle; bus_addr_t base; bus_size_t size; pcireg_t csr; int flags; int rv; if ((rv = pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg, type, &base, &size, &flags)) != 0) return (rv); if (base == 0) return (EINVAL); /* disabled because of invalid BAR */ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) csr |= PCI_COMMAND_IO_ENABLE; else csr |= PCI_COMMAND_MEM_ENABLE; /* XXX Should this only be done for devices that do DMA? */ csr |= PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr); if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) { if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0) return (EINVAL); tag = pa->pa_iot; } else { if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0) return (EINVAL); tag = pa->pa_memt; } /* The caller can request limitation of the mapping's size. */ if (maxsize != 0 && size > maxsize) { #ifdef DEBUG printf("pci_mapreg_map: limited PCI mapping from %lx to %lx\n", (u_long)size, (u_long)maxsize); #endif size = maxsize; } if (bus_space_map(tag, base, size, busflags | flags, &handle)) return (1); if (tagp != NULL) *tagp = tag; if (handlep != NULL) *handlep = handle; if (basep != NULL) *basep = base; if (sizep != NULL) *sizep = size; return (0); }