int smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag, pcireg_t id) { long defattr; struct rasops_info *ri; bus_space_handle_t fbh, mmioh; pcireg_t bar; int rc, is5xx; /* filter out unrecognized devices */ switch (id) { default: return ENODEV; case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712): is5xx = 0; break; case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501): is5xx = 1; break; } smfbcn.is5xx = is5xx; bar = pci_conf_read_early(tag, PCI_MAPREG_START); if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM) return EINVAL; rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */, BUS_SPACE_MAP_LINEAR, &fbh); if (rc != 0) return rc; if (smfbcn.is5xx) { bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04); if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM) return EINVAL; rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */, BUS_SPACE_MAP_LINEAR, &mmioh); if (rc != 0) return rc; } else { mmioh = fbh; } rc = smfb_setup(&smfbcn, memt, fbh, memt, mmioh); if (rc != 0) return rc; ri = &smfbcn.ri; ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); wsdisplay_cnattach(&smfbcn.wsd, ri, 0, 0, defattr); return 0; }
bus_addr_t pciaddr_ioaddr(u_int32_t val) { return ((PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM) ? PCI_MAPREG_MEM_ADDR(val) : (PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END)); }
bus_addr_t pciaddr_ioaddr(uint32_t val) { return (PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM) ? PCI_MAPREG_MEM_ADDR(val) : PCI_MAPREG_IO_ADDR(val); }
int pci_func_configure(struct pci_func *f) { uint32_t bar_width; uint32_t bar; for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += bar_width) { uint32_t oldv = pci_conf_read(f, bar); bar_width = 4; pci_conf_write(f, bar, 0xffffffff); uint32_t rv = pci_conf_read(f, bar); if (rv == 0) continue; int regnum = PCI_MAPREG_NUM(bar); uint32_t base, size; if (PCI_MAPREG_TYPE(rv) == PCI_MAPREG_TYPE_MEM) { if (PCI_MAPREG_MEM_TYPE(rv) == PCI_MAPREG_MEM_TYPE_64BIT) bar_width = 8; size = PCI_MAPREG_MEM_SIZE(rv); base = PCI_MAPREG_MEM_ADDR(oldv); if (!base) { /* device is not properly configured, allocate mmio address for it */ base = pci_allocate_memory(size); if (!base) return ENOMEM; oldv = base; } #ifdef SHOW_PCI_VERBOSE_INFO printf("pci: allocated mem region %d: %d bytes at 0x%x\n", regnum, size, base); #endif } else { #ifdef CONFIG_ARCH_HAS_IO_SPACE /* TODO handle IO region */ #endif } pci_conf_write(f, bar, oldv); f->reg_base[regnum] = base; f->reg_size[regnum] = size; } f->irq_line = pci_allocate_irqline(); /* FIXME */ f->irq_pin = PCI_INTERRUPT_PIN_C; pci_conf_write(f, PCI_INTERRUPT_REG, PCI_INTERRUPT_LINE(f->irq_line) | PCI_INTERRUPT_PIN(f->irq_pin)); printf("pci: function %02x:%02x.%d (%04x:%04x) configured\n", f->bus->busno, f->dev, f->func, PCI_VENDOR(f->dev_id), PCI_PRODUCT(f->dev_id)); return 0; }
static int pci_io_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { pcireg_t address, mask; int s; if (reg < PCI_MAPREG_START || #if 0 /* * Can't do this check; some devices have mapping registers * way out in left field. */ reg >= PCI_MAPREG_END || #endif (reg & 3)) panic("pci_io_find: bad request"); /* * Section 6.2.5.1, `Address Maps', tells us that: * * 1) The builtin software should have already mapped the device in a * reasonable way. * * 2) A device which wants 2^n bytes of memory will hardwire the bottom * n bits of the address to 0. As recommended, we write all 1s and see * what we get back. */ s = splhigh(); address = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, 0xffffffff); mask = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); splx(s); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) { aprint_debug("pci_io_find: expected type i/o, found mem\n"); return (1); } if (PCI_MAPREG_IO_SIZE(mask) == 0) { aprint_debug("pci_io_find: void region\n"); return (1); } if (basep != 0) *basep = PCI_MAPREG_IO_ADDR(address); if (sizep != 0) *sizep = PCI_MAPREG_IO_SIZE(mask); if (flagsp != 0) *flagsp = 0; return (0); }
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)); }
/* check if this BAR assigns/requests IO space */ static int bar_is_io(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t address, mask; int s; /* * The splhigh() is not realy necessary at autoconfig time, * but maybe useful if used in lkm context later. */ s = splhigh(); address = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, 0xffffffff); mask = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); splx(s); return (PCI_MAPREG_TYPE(address) == PCI_MAPREG_TYPE_IO && PCI_MAPREG_IO_SIZE(mask) > 0); }
/* * 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); }
void gcu_attach(struct device *parent, struct device *self, void *aux) { struct gcu_softc *sc = (struct gcu_softc *)self; struct pci_attach_args *pa = aux; int val; val = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) { printf(": mmba is not mem space\n"); return; } if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_MEM_TYPE(val), 0, &sc->tag, &sc->handle, &sc->addr, &sc->size, 0)) { printf(": cannot find mem space\n"); return; } mtx_init(&sc->mdio_mtx, IPL_NET); printf("\n"); }
/* * static int cardbus_mem_find(cardbus_chipset_tag_t cc, * cardbus_function_tag_t cf, pcitag_t tag, * int reg, pcireg_t type, bus_addr_t *basep, * bus_size_t *sizep, int *flagsp) * This code is stolen from sys/dev/pci_map.c. */ static int cardbus_mem_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { pcireg_t address, mask; int s; if (reg != CARDBUS_ROM_REG && (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) { panic("cardbus_mem_find: bad request"); } /* * Section 6.2.5.1, `Address Maps', tells us that: * * 1) The builtin software should have already mapped the device in a * reasonable way. * * 2) A device which wants 2^n bytes of memory will hardwire the bottom * n bits of the address to 0. As recommended, we write all 1s and see * what we get back. */ s = splhigh(); address = cardbus_conf_read(cc, cf, tag, reg); cardbus_conf_write(cc, cf, tag, reg, 0xffffffff); mask = cardbus_conf_read(cc, cf, tag, reg); cardbus_conf_write(cc, cf, tag, reg, address); splx(s); if (reg != CARDBUS_ROM_REG) { /* memory space BAR */ if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { printf("cardbus_mem_find: expected type mem, found i/o\n"); return 1; } if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) { printf("cardbus_mem_find: expected mem type %08x, found %08x\n", PCI_MAPREG_MEM_TYPE(type), PCI_MAPREG_MEM_TYPE(address)); return 1; } } if (PCI_MAPREG_MEM_SIZE(mask) == 0) { printf("cardbus_mem_find: void region\n"); return 1; } switch (PCI_MAPREG_MEM_TYPE(address)) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: printf("cardbus_mem_find: 64-bit memory mapping register\n"); return 1; default: printf("cardbus_mem_find: reserved mapping register type\n"); return 1; } if (basep != 0) { *basep = PCI_MAPREG_MEM_ADDR(address); } if (sizep != 0) { *sizep = PCI_MAPREG_MEM_SIZE(mask); } if (flagsp != 0) { *flagsp = PCI_MAPREG_MEM_PREFETCHABLE(address) ? BUS_SPACE_MAP_PREFETCHABLE : 0; } return 0; }
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); }
static bus_addr_t pucprobe_doit(struct consdev *cn) { struct pci_attach_args pa; int bus; static int dev = 0, func = 0; int maxdev, nfunctions = 0, i; /* XXX */ pcireg_t reg, bhlcr, subsys = 0; /* XXX */ int foundport = 0; const struct puc_device_description *desc; pcireg_t base; /* Fetch our tags */ if (cpu_comcnprobe(cn, &pa) != 0) { return 0; } puctag = pa.pa_iot; pci_decompose_tag(pa.pa_pc, pa.pa_tag, &bus, &maxdev, NULL); /* scan through devices */ for (; dev <= maxdev ; dev++) { pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, 0); reg = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG); if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || PCI_VENDOR(reg) == 0) continue; bhlcr = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_BHLC_REG); if (PCI_HDRTYPE_MULTIFN(bhlcr)) { nfunctions = 8; } else { nfunctions = 1; } resume_scan: for (; func < nfunctions; func++) { pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, func); reg = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_CLASS_REG); if (PCI_CLASS(reg) == PCI_CLASS_COMMUNICATIONS && PCI_SUBCLASS(reg) == PCI_SUBCLASS_COMMUNICATIONS_SERIAL) { pa.pa_id = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG); subsys = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_SUBSYS_ID_REG); foundport = 1; break; } } if (foundport) break; func = 0; } if (!foundport) return 0; foundport = 0; desc = puc_find_description(PCI_VENDOR(pa.pa_id), PCI_PRODUCT(pa.pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys)); if (desc == NULL) { func++; goto resume_scan; } for (i = 0; PUC_PORT_VALID(desc, i); i++) { if (desc->ports[i].type != PUC_PORT_TYPE_COM) continue; base = pci_conf_read(pa.pa_pc, pa.pa_tag, desc->ports[i].bar); base += desc->ports[i].offset; if (PCI_MAPREG_TYPE(base) != PCI_MAPREG_TYPE_IO) continue; base = PCI_MAPREG_IO_ADDR(base); if (com_is_console(puctag, base, NULL)) continue; foundport = 1; break; } if (foundport == 0) { func++; goto resume_scan; } cn->cn_pri = CN_REMOTE; return PCI_MAPREG_IO_ADDR(base); }
void device_register(struct device *dev, void *aux) { #if NPCI > 0 extern struct cfdriver pci_cd; #endif #if NCD > 0 || NSD > 0 || NST > 0 extern struct cfdriver scsibus_cd; #endif struct confargs *ca = aux; static struct device *elder = NULL; if (bootdv != NULL) return; /* We already have a winner */ #if NPCI > 0 if (dev->dv_parent && dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) { struct pci_attach_args *pa = aux; pcireg_t addr; int reg; for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) { addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg); if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO) addr = PCI_MAPREG_IO_ADDR(addr); else addr = PCI_MAPREG_MEM_ADDR(addr); if (addr == (pcireg_t)(u_long)PAGE0->mem_boot.pz_hpa) { elder = dev; break; } } } else #endif if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) { /* * If hpa matches, the only thing we know is that the * booted device is either this one or one of its children. * And the children will not necessarily have the correct * hpa value. * Save this elder for now. */ elder = dev; } else if (elder == NULL) { return; /* not the device we booted from */ } /* * Unfortunately, we can not match on pz_class vs dv_class on * older snakes netbooting using the rbootd protocol. * In this case, we'll end up with pz_class == PCL_RANDOM... * Instead, trust the device class from what the kernel attached * now... */ switch (dev->dv_class) { case DV_IFNET: /* * Netboot is the top elder */ if (elder == dev) { bootdv = dev; } return; case DV_DISK: case DV_DULL: if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM) return; break; case DV_TAPE: if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU) return; break; default: /* No idea what we were booted from, but better ask the user */ return; } /* * If control goes here, we are booted from a block device and we * matched a block device. * * We only grok SCSI boot currently. Match on proper device * hierarchy and unit/lun values. */ #if NCD > 0 || NSD > 0 || NST > 0 if (dev->dv_parent && dev->dv_parent->dv_cfdata->cf_driver == &scsibus_cd) { struct scsi_attach_args *sa = aux; struct scsi_link *sl = sa->sa_sc_link; /* * sd/st/cd is attached to scsibus which is attached to * the controller. Hence the grandparent here should be * the elder. */ if (dev->dv_parent->dv_parent != elder) { return; } /* * And now check for proper target and lun values */ if (sl->target == PAGE0->mem_boot.pz_layers[0] && sl->lun == PAGE0->mem_boot.pz_layers[1]) { bootdv = dev; } } #endif }
static void puc_attach(device_t parent, device_t self, void *aux) { struct puc_softc *sc = device_private(self); struct pci_attach_args *pa = aux; struct puc_attach_args paa; pci_intr_handle_t intrhandle; pcireg_t subsys; int i, barindex; bus_addr_t base; bus_space_tag_t tag; #ifdef PUCCN bus_space_handle_t ioh; #endif int locs[PUCCF_NLOCS]; 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)); if (sc->sc_desc == NULL) { /* * This was a class/subclass match, so tell people to compile * kernel with options that cause this driver to spew. */ #ifdef PUC_PRINT_REGS printf(":\n"); pci_conf_print(pa->pa_pc, pa->pa_tag, NULL); #else printf(": unknown PCI communications device\n"); printf("%s: compile kernel with PUC_PRINT_REGS and larger\n", device_xname(self)); printf("%s: mesage buffer (via 'options MSGBUFSIZE=...'),\n", device_xname(self)); printf("%s: and report the result with send-pr\n", device_xname(self)); #endif return; } printf(": %s (", sc->sc_desc->name); for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) printf("%s%s", i ? ", " : "", puc_port_type_name(sc->sc_desc->ports[i].type)); printf(")\n"); for (i = 0; i < 6; i++) { pcireg_t bar, type; sc->sc_bar_mappings[i].mapped = 0; bar = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START + 4 * i); /* XXX const */ if (bar == 0) /* BAR not implemented(?) */ continue; type = (PCI_MAPREG_TYPE(bar) == PCI_MAPREG_TYPE_IO ? PCI_MAPREG_TYPE_IO : PCI_MAPREG_MEM_TYPE(bar)); if (type == PCI_MAPREG_TYPE_IO) { tag = pa->pa_iot; base = PCI_MAPREG_IO_ADDR(bar); } else { tag = pa->pa_memt; base = PCI_MAPREG_MEM_ADDR(bar); } #ifdef PUCCN if (com_is_console(tag, base, &ioh)) { sc->sc_bar_mappings[i].mapped = 1; sc->sc_bar_mappings[i].a = base; sc->sc_bar_mappings[i].s = COM_NPORTS; sc->sc_bar_mappings[i].t = tag; sc->sc_bar_mappings[i].h = ioh; continue; } #endif sc->sc_bar_mappings[i].mapped = (pci_mapreg_map(pa, PCI_MAPREG_START + 4 * i, 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); if (sc->sc_bar_mappings[i].mapped) continue; aprint_error_dev(self, "couldn't map BAR at offset 0x%lx\n", (long)(PCI_MAPREG_START + 4 * i)); } /* Map interrupt. */ if (pci_intr_map(pa, &intrhandle)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } /* * XXX the sub-devices establish the interrupts, for the * XXX following reasons: * XXX * XXX * we can't really know what IPLs they'd want * XXX * XXX * the MD dispatching code can ("should") dispatch * XXX chained interrupts better than we can. * XXX * XXX It would be nice if we could indicate to the MD interrupt * XXX handling code that the interrupt line used by the device * XXX was a PCI (level triggered) interrupt. * XXX * XXX It's not pretty, but hey, what is? */ /* Configure each port. */ for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) { bus_space_handle_t subregion_handle; /* make sure the base address register is mapped */ barindex = PUC_PORT_BAR_INDEX(sc->sc_desc->ports[i].bar); if (!sc->sc_bar_mappings[barindex].mapped) { printf("%s: %s port uses unmapped BAR (0x%x)\n", device_xname(self), puc_port_type_name(sc->sc_desc->ports[i].type), sc->sc_desc->ports[i].bar); continue; } /* set up to configure the child device */ paa.port = i; paa.type = sc->sc_desc->ports[i].type; paa.flags = sc->sc_desc->ports[i].flags; paa.pc = pa->pa_pc; paa.tag = pa->pa_tag; paa.intrhandle = intrhandle; paa.a = sc->sc_bar_mappings[barindex].a; paa.t = sc->sc_bar_mappings[barindex].t; paa.dmat = pa->pa_dmat; paa.dmat64 = pa->pa_dmat64; if ( #ifdef PUCCN !com_is_console(sc->sc_bar_mappings[barindex].t, sc->sc_bar_mappings[barindex].a, &subregion_handle) && #endif bus_space_subregion(sc->sc_bar_mappings[barindex].t, sc->sc_bar_mappings[barindex].h, sc->sc_desc->ports[i].offset, sc->sc_bar_mappings[barindex].s - sc->sc_desc->ports[i].offset, &subregion_handle) != 0) { aprint_error_dev(self, "couldn't get subregion for port %d\n", i); continue; } paa.h = subregion_handle; #if 0 printf("%s: port %d: %s @ (index %d) 0x%x (0x%lx, 0x%lx)\n", device_xname(self), paa.port, puc_port_type_name(paa.type), barindex, (int)paa.a, (long)paa.t, (long)paa.h); #endif locs[PUCCF_PORT] = i; /* and configure it */ sc->sc_ports[i].dev = config_found_sm_loc(self, "puc", locs, &paa, puc_print, config_stdsubmatch); } }
void pciaddr_resource_manage(struct pcibios_softc *sc, pci_chipset_tag_t pc, pcitag_t tag, pciaddr_resource_manage_func_t func) { struct extent *ex; pcireg_t val, mask; bus_addr_t addr; bus_size_t size; int error, mapreg, type, reg_start, reg_end, width; val = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(val)) { default: printf("WARNING: unknown PCI device header 0x%x.\n", PCI_HDRTYPE_TYPE(val)); sc->nbogus++; return; case 0: reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_END; break; case 1: /* PCI-PCI bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PPB_END; break; case 2: /* PCI-CardBus bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PCB_END; break; } error = 0; for (mapreg = reg_start; mapreg < reg_end; mapreg += width) { /* inquire PCI device bus space requirement */ val = pci_conf_read(pc, tag, mapreg); pci_conf_write(pc, tag, mapreg, ~0); mask = pci_conf_read(pc, tag, mapreg); pci_conf_write(pc, tag, mapreg, val); type = PCI_MAPREG_TYPE(val); width = 4; if (type == PCI_MAPREG_TYPE_MEM) { if (PCI_MAPREG_MEM_TYPE(val) == PCI_MAPREG_MEM_TYPE_64BIT) { /* XXX We could examine the upper 32 bits * XXX of the BAR here, but we are totally * XXX unprepared to handle a non-zero value, * XXX either here or anywhere else in * XXX i386-land. * XXX So just arrange to not look at the * XXX upper 32 bits, lest we misinterpret * XXX it as a 32-bit BAR set to zero. */ width = 8; } addr = PCI_MAPREG_MEM_ADDR(val); size = PCI_MAPREG_MEM_SIZE(mask); ex = sc->extent_mem; } else { /* XXX some devices give 32bit value */ addr = PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END; size = PCI_MAPREG_IO_SIZE(mask); ex = sc->extent_port; } if (!size) /* unused register */ continue; /* reservation/allocation phase */ error += (*func) (sc, pc, tag, mapreg, ex, type, &addr, size); PCIBIOS_PRINTV(("\t%02xh %s 0x%08x 0x%08x\n", mapreg, type ? "port" : "mem ", (unsigned int)addr, (unsigned int)size)); } if (error) sc->nbogus++; PCIBIOS_PRINTV(("\t\t[%s]\n", error ? "NG" : "OK")); }
static void iop_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct iop_softc *sc; pci_chipset_tag_t pc; pci_intr_handle_t ih; const char *intrstr; pcireg_t reg; int i; char intrbuf[PCI_INTRSTR_LEN]; sc = device_private(self); sc->sc_dev = self; pa = aux; pc = pa->pa_pc; printf(": "); /* * The kernel always uses the first memory mapping to communicate * with the IOP. */ for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) { reg = pci_conf_read(pc, pa->pa_tag, i); if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_MEM) { sc->sc_memaddr = PCI_MAPREG_MEM_ADDR(reg); break; } } if (i == PCI_MAPREG_END) { printf("can't find mapping\n"); return; } /* Map the register window. */ if (pci_mapreg_map(pa, i, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { aprint_error_dev(self, "can't map register window\n"); return; } /* Map the 2nd register window. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DPT && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_2005S) { i += 4; /* next BAR */ if (i == PCI_MAPREG_END) { printf("can't find mapping\n"); return; } #if 0 /* Should we check it? (see FreeBSD's asr driver) */ reg = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG); printf("subid %x, %x\n", PCI_VENDOR(reg), PCI_PRODUCT(reg)); #endif if (pci_mapreg_map(pa, i, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_msg_iot, &sc->sc_msg_ioh, NULL, NULL)) { aprint_error_dev(self, "can't map 2nd register window\n"); return; } } else { /* iop devices other than 2005S */ sc->sc_msg_iot = sc->sc_iot; sc->sc_msg_ioh = sc->sc_ioh; } sc->sc_pcibus = pa->pa_bus; sc->sc_pcidev = pa->pa_device; sc->sc_dmat = pa->pa_dmat; sc->sc_bus_memt = pa->pa_memt; sc->sc_bus_iot = pa->pa_iot; /* Enable the device. */ 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); /* Map and establish the interrupt.. */ if (pci_intr_map(pa, &ih)) { printf("can't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, iop_intr, sc); if (sc->sc_ih == NULL) { printf("can't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } /* Attach to the bus-independent code. */ iop_init(sc, intrstr); }
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; }
/** * 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); }
int obsd_pci_mem_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { pcireg_t address, mask, address1 = 0, mask1 = 0xffffffff, csr; u_int64_t waddress, wmask; int s, is64bit; is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT); if (reg < PCI_MAPREG_START || #if 0 /* * Can't do this check; some devices have mapping registers * way out in left field. */ reg >= PCI_MAPREG_END || #endif (reg & 3)) panic("pci_mem_find: bad request"); if (is64bit && (reg + 4) >= PCI_MAPREG_END) panic("pci_mem_find: bad 64-bit request"); /* * Section 6.2.5.1, `Address Maps', tells us that: * * 1) The builtin software should have already mapped the device in a * reasonable way. * * 2) A device which wants 2^n bytes of memory will hardwire the bottom * n bits of the address to 0. As recommended, we write all 1s while * the device is disabled and see what we get back. */ s = splhigh(); csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); if (csr & PCI_COMMAND_MEM_ENABLE) pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr & ~PCI_COMMAND_MEM_ENABLE); address = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, 0xffffffff); mask = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); if (is64bit) { address1 = pci_conf_read(pc, tag, reg + 4); pci_conf_write(pc, tag, reg + 4, 0xffffffff); mask1 = pci_conf_read(pc, tag, reg + 4); pci_conf_write(pc, tag, reg + 4, address1); } if (csr & PCI_COMMAND_MEM_ENABLE) pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); splx(s); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { #ifdef DEBUG printf("pci_mem_find: expected type mem, found i/o\n"); #endif return (EINVAL); } if (type != -1 && PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) { #ifdef DEBUG printf("pci_mem_find: expected mem type %08x, found %08x\n", PCI_MAPREG_MEM_TYPE(type), PCI_MAPREG_MEM_TYPE(address)); #endif return (EINVAL); } waddress = (u_int64_t)address1 << 32UL | address; wmask = (u_int64_t)mask1 << 32UL | mask; if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) || (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) { #ifdef DEBUG printf("pci_mem_find: void region\n"); #endif return (ENOENT); } switch (PCI_MAPREG_MEM_TYPE(address)) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: /* * Handle the case of a 64-bit memory register on a * platform with 32-bit addressing. Make sure that * the address assigned and the device's memory size * fit in 32 bits. We implicitly assume that if * bus_addr_t is 64-bit, then so is bus_size_t. */ if (sizeof(u_int64_t) > sizeof(bus_addr_t) && (address1 != 0 || mask1 != 0xffffffff)) { #ifdef DEBUG printf("pci_mem_find: 64-bit memory map which is " "inaccessible on a 32-bit platform\n"); #endif return (EINVAL); } break; default: #ifdef DEBUG printf("pci_mem_find: reserved mapping register type\n"); #endif return (EINVAL); } if (sizeof(u_int64_t) > sizeof(bus_addr_t)) { if (basep != 0) *basep = PCI_MAPREG_MEM_ADDR(address); if (sizep != 0) *sizep = PCI_MAPREG_MEM_SIZE(mask); } else { if (basep != 0) *basep = PCI_MAPREG_MEM64_ADDR(waddress); if (sizep != 0) *sizep = PCI_MAPREG_MEM64_SIZE(wmask); } if (flagsp != 0) *flagsp = #ifdef BUS_SPACE_MAP_PREFETCHABLE PCI_MAPREG_MEM_PREFETCHABLE(address) ? BUS_SPACE_MAP_PREFETCHABLE : #endif 0; return (0); }
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); }
static bus_addr_t pucprobe_doit(struct consdev *cn) { struct pci_attach_args pa; int bus; static int dev = 0, func = 0; int maxdev, nfunctions = 0, i; /* XXX */ pcireg_t reg, bhlcr, subsys = 0; /* XXX */ int foundport = 0; const struct puc_device_description *desc; pcireg_t base; /* Fetch our tags */ #if defined(amd64) || defined(i386) if (cpu_puc_cnprobe(cn, &pa) != 0) #endif return 0; pci_decompose_tag(pa.pa_pc, pa.pa_tag, &bus, &maxdev, NULL); /* Scan through devices and find a communication class device. */ for (; dev <= maxdev ; dev++) { pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, 0); reg = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG); if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || PCI_VENDOR(reg) == 0) continue; bhlcr = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_BHLC_REG); if (PCI_HDRTYPE_MULTIFN(bhlcr)) { nfunctions = 8; } else { nfunctions = 1; } resume_scan: for (; func < nfunctions; func++) { pa.pa_tag = pci_make_tag(pa.pa_pc, bus, dev, func); reg = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_CLASS_REG); if (PCI_CLASS(reg) == PCI_CLASS_COMMUNICATIONS && PCI_SUBCLASS(reg) == PCI_SUBCLASS_COMMUNICATIONS_SERIAL) { pa.pa_id = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG); subsys = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_SUBSYS_ID_REG); foundport = 1; break; } } if (foundport) break; func = 0; } /* * If all devices was scanned and couldn't find any communication * device, return with 0. */ if (!foundport) return 0; /* Clear foundport flag */ foundport = 0; /* Check whether the device is in the puc device table or not */ desc = puc_find_description(PCI_VENDOR(pa.pa_id), PCI_PRODUCT(pa.pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys)); /* If not, check the next communication device */ if (desc == NULL) { /* Resume from the next function */ func++; goto resume_scan; } /* * We found a device and it's on the puc table. Set the tag and * the base address. */ for (i = 0; PUC_PORT_VALID(desc, i); i++) { if (desc->ports[i].type != PUC_PORT_TYPE_COM) continue; puccnflags = desc->ports[i].flags; base = pci_conf_read(pa.pa_pc, pa.pa_tag, desc->ports[i].bar); base += desc->ports[i].offset; if (PCI_MAPREG_TYPE(base) == PCI_MAPREG_TYPE_IO) { puctag = pa.pa_iot; base = PCI_MAPREG_IO_ADDR(base); } #if 0 /* For MMIO device */ else { puctag = pa.pa_memt; base = PCI_MAPREG_MEM_ADDR(base); } #endif if (com_is_console(puctag, base, NULL)) continue; foundport = 1; break; } if (foundport == 0) { func++; goto resume_scan; } #if 0 cn->cn_pri = CN_REMOTE; #else if (cn) cn->cn_pri = CN_REMOTE; #endif return base; }
static int pci_mem_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { pcireg_t address, mask, address1 = 0, mask1 = 0xffffffff; u_int64_t waddress, wmask; int s, is64bit, isrom; is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT); isrom = (reg == PCI_MAPREG_ROM); if ((!isrom) && (reg < PCI_MAPREG_START || #if 0 /* * Can't do this check; some devices have mapping registers * way out in left field. */ reg >= PCI_MAPREG_END || #endif (reg & 3))) panic("pci_mem_find: bad request"); if (is64bit && (reg + 4) >= PCI_MAPREG_END) panic("pci_mem_find: bad 64-bit request"); /* * Section 6.2.5.1, `Address Maps', tells us that: * * 1) The builtin software should have already mapped the device in a * reasonable way. * * 2) A device which wants 2^n bytes of memory will hardwire the bottom * n bits of the address to 0. As recommended, we write all 1s and see * what we get back. */ s = splhigh(); address = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, 0xffffffff); mask = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); if (is64bit) { address1 = pci_conf_read(pc, tag, reg + 4); pci_conf_write(pc, tag, reg + 4, 0xffffffff); mask1 = pci_conf_read(pc, tag, reg + 4); pci_conf_write(pc, tag, reg + 4, address1); } splx(s); if (!isrom) { /* * roms should have an enable bit instead of a memory * type decoder bit. For normal BARs, make sure that * the address decoder type matches what we asked for. */ if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { printf("pci_mem_find: expected type mem, found i/o\n"); return (1); } /* XXX Allow 64bit bars for 32bit requests.*/ if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type) && PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE_64BIT) { printf("pci_mem_find: " "expected mem type %08x, found %08x\n", PCI_MAPREG_MEM_TYPE(type), PCI_MAPREG_MEM_TYPE(address)); return (1); } } waddress = (u_int64_t)address1 << 32UL | address; wmask = (u_int64_t)mask1 << 32UL | mask; if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) || (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) { aprint_debug("pci_mem_find: void region\n"); return (1); } switch (PCI_MAPREG_MEM_TYPE(address)) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: /* * Handle the case of a 64-bit memory register on a * platform with 32-bit addressing. Make sure that * the address assigned and the device's memory size * fit in 32 bits. We implicitly assume that if * bus_addr_t is 64-bit, then so is bus_size_t. */ if (sizeof(u_int64_t) > sizeof(bus_addr_t) && (address1 != 0 || mask1 != 0xffffffff)) { printf("pci_mem_find: 64-bit memory map which is " "inaccessible on a 32-bit platform\n"); return (1); } break; default: printf("pci_mem_find: reserved mapping register type\n"); return (1); } if (sizeof(u_int64_t) > sizeof(bus_addr_t)) { if (basep != 0) *basep = PCI_MAPREG_MEM_ADDR(address); if (sizep != 0) *sizep = PCI_MAPREG_MEM_SIZE(mask); } else { if (basep != 0) *basep = PCI_MAPREG_MEM64_ADDR(waddress); if (sizep != 0) *sizep = PCI_MAPREG_MEM64_SIZE(wmask); } if (flagsp != 0) *flagsp = (isrom || PCI_MAPREG_MEM_PREFETCHABLE(address)) ? BUS_SPACE_MAP_PREFETCHABLE : 0; return (0); }
/* * int cardbus_mapreg_map(struct cardbus_softc *, int, int, pcireg_t, * int bus_space_tag_t *, bus_space_handle_t *, * bus_addr_t *, bus_size_t *) * This function maps bus-space on the value of Base Address * Register (BAR) indexed by the argument `reg' (the second argument). * When the value of the BAR is not valid, such as 0x00000000, a new * address should be allocated for the BAR and new address values is * written on the BAR. */ int cardbus_mapreg_map(struct cardbus_softc *sc, int func, 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) { cardbus_chipset_tag_t cc = sc->sc_cc; cardbus_function_tag_t cf = sc->sc_cf; bus_space_tag_t bustag; rbus_tag_t rbustag; bus_space_handle_t handle; bus_addr_t base; bus_size_t size; int flags; int status = 0; pcitag_t tag; size = 0; /* XXX gcc */ flags = 0; /* XXX gcc */ tag = cardbus_make_tag(cc, cf, sc->sc_bus, func); DPRINTF(("cardbus_mapreg_map called: %s %x\n", device_xname(sc->sc_dev), type)); if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) { if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size, &flags)) { status = 1; } bustag = sc->sc_iot; rbustag = sc->sc_rbus_iot; } else { if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size, &flags)){ status = 1; } bustag = sc->sc_memt; rbustag = sc->sc_rbus_memt; } if (status == 0) { bus_addr_t mask = size - 1; if (base != 0) { mask = 0xffffffff; } if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask, size, busflags | flags, &base, &handle)) { panic("io alloc"); } } cardbus_conf_write(cc, cf, tag, reg, base); DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base)); if (tagp != 0) { *tagp = bustag; } if (handlep != 0) { *handlep = handle; } if (basep != 0) { *basep = base; } if (sizep != 0) { *sizep = size; } return 0; }
static void cac_pci_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; const struct cac_pci_type *ct; struct cac_softc *sc; pci_chipset_tag_t pc; pci_intr_handle_t ih; const char *intrstr; pcireg_t reg; int memr, ior, i; char intrbuf[PCI_INTRSTR_LEN]; aprint_naive(": RAID controller\n"); sc = device_private(self); sc->sc_dev = self; pa = (struct pci_attach_args *)aux; pc = pa->pa_pc; ct = cac_pci_findtype(pa); /* * Map the PCI register window. */ memr = -1; ior = -1; for (i = 0x10; i <= 0x14; i += 4) { reg = pci_conf_read(pa->pa_pc, pa->pa_tag, i); if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) { if (ior == -1 && PCI_MAPREG_IO_SIZE(reg) != 0) ior = i; } else { if (memr == -1 && PCI_MAPREG_MEM_SIZE(reg) != 0) memr = i; } } if (memr != -1) { if (pci_mapreg_map(pa, memr, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) memr = -1; else ior = -1; } if (ior != -1) if (pci_mapreg_map(pa, ior, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) ior = -1; if (memr == -1 && ior == -1) { aprint_error_dev(self, "can't map i/o or memory space\n"); return; } sc->sc_dmat = pa->pa_dmat; /* Enable the device. */ 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); /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error("can't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, cac_intr, sc); if (sc->sc_ih == NULL) { aprint_error("can't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal(": Compaq %s\n", ct->ct_typestr); /* Now attach to the bus-independent code. */ memcpy(&sc->sc_cl, ct->ct_linkage, sizeof(sc->sc_cl)); cac_init(sc, intrstr, (ct->ct_flags & CT_STARTFW) != 0); }
/* * static int cardbus_io_find(cardbus_chipset_tag_t cc, * cardbus_function_tag_t cf, pcitag_t tag, * int reg, pcireg_t type, bus_addr_t *basep, * bus_size_t *sizep, int *flagsp) * This code is stolen from sys/dev/pci_map.c. */ static int cardbus_io_find( cardbus_chipset_tag_t cc, cardbus_function_tag_t cf, pcitag_t tag, int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp) { pcireg_t address, mask; int s; /* EXT ROM is able to map on memory space ONLY. */ if (reg == CARDBUS_ROM_REG) { return 1; } if(reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { panic("cardbus_io_find: bad request"); } /* * Section 6.2.5.1, `Address Maps', tells us that: * * 1) The builtin software should have already mapped the device in a * reasonable way. * * 2) A device which wants 2^n bytes of memory will hardwire the bottom * n bits of the address to 0. As recommended, we write all 1s and see * what we get back. */ s = splhigh(); address = cardbus_conf_read(cc, cf, tag, reg); cardbus_conf_write(cc, cf, tag, reg, 0xffffffff); mask = cardbus_conf_read(cc, cf, tag, reg); cardbus_conf_write(cc, cf, tag, reg, address); splx(s); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) { printf("cardbus_io_find: expected type i/o, found mem\n"); return 1; } if (PCI_MAPREG_IO_SIZE(mask) == 0) { printf("cardbus_io_find: void region\n"); return 1; } if (basep != 0) { *basep = PCI_MAPREG_IO_ADDR(address); } if (sizep != 0) { *sizep = PCI_MAPREG_IO_SIZE(mask); } if (flagsp != 0) { *flagsp = 0; } return 0; }
void pciaddr_resource_manage(pci_chipset_tag_t pc, pcitag_t tag, pciaddr_resource_manage_func_t func, void *ctx) { pcireg_t val, mask; bus_addr_t addr; bus_size_t size; int error, useport, usemem, mapreg, type, reg_start, reg_end, width; val = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(val)) { default: aprint_error("WARNING: unknown PCI device header."); pciaddr.nbogus++; return; case PCI_HDRTYPE_DEVICE: reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_END; break; case PCI_HDRTYPE_PPB: /* PCI-PCI bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PPB_END; break; case PCI_HDRTYPE_PCB: /* PCI-CardBus bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PCB_END; break; } error = useport = usemem = 0; for (mapreg = reg_start; mapreg < reg_end; mapreg += width) { /* inquire PCI device bus space requirement */ val = pci_conf_read(pc, tag, mapreg); pci_conf_write(pc, tag, mapreg, ~0); mask = pci_conf_read(pc, tag, mapreg); pci_conf_write(pc, tag, mapreg, val); type = PCI_MAPREG_TYPE(val); width = 4; if (type == PCI_MAPREG_TYPE_MEM) { if (PCI_MAPREG_MEM_TYPE(val) == PCI_MAPREG_MEM_TYPE_64BIT) { /* XXX We could examine the upper 32 bits * XXX of the BAR here, but we are totally * XXX unprepared to handle a non-zero value, * XXX either here or anywhere else in * XXX i386-land. * XXX So just arrange to not look at the * XXX upper 32 bits, lest we misinterpret * XXX it as a 32-bit BAR set to zero. */ width = 8; } size = PCI_MAPREG_MEM_SIZE(mask); } else { size = PCI_MAPREG_IO_SIZE(mask); } addr = pciaddr_ioaddr(val); if (size == 0) /* unused register */ continue; if (type == PCI_MAPREG_TYPE_MEM) ++usemem; else ++useport; /* reservation/allocation phase */ error += (*func) (pc, tag, mapreg, ctx, type, &addr, size); aprint_debug("\n\t%02xh %s 0x%08x 0x%08x", mapreg, type ? "port" : "mem ", (unsigned int)addr, (unsigned int)size); } /* enable/disable PCI device */ val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); if (error == 0) val |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); else val &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val); if (error != 0) pciaddr.nbogus++; aprint_debug("\n\t\t[%s]\n", error ? "NG" : "OK"); }
static int pci_device_openbsd_probe(struct pci_device *device) { struct pci_device_private *priv = (struct pci_device_private *)device; struct pci_mem_region *region; uint64_t reg64, size64; uint32_t bar, reg, size; int domain, bus, dev, func, err; domain = device->domain; bus = device->bus; dev = device->dev; func = device->func; err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, ®); if (err) return err; priv->header_type = PCI_HDRTYPE_TYPE(reg); if (priv->header_type != 0) return 0; region = device->regions; for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += sizeof(uint32_t), region++) { err = pci_read(domain, bus, dev, func, bar, ®); if (err) return err; /* Probe the size of the region. */ err = pci_readmask(domain, bus, dev, func, bar, &size); if (err) return err; if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) { region->is_IO = 1; region->base_addr = PCI_MAPREG_IO_ADDR(reg); region->size = PCI_MAPREG_IO_SIZE(size); } else { if (PCI_MAPREG_MEM_PREFETCHABLE(reg)) region->is_prefetchable = 1; switch(PCI_MAPREG_MEM_TYPE(reg)) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: region->base_addr = PCI_MAPREG_MEM_ADDR(reg); region->size = PCI_MAPREG_MEM_SIZE(size); break; case PCI_MAPREG_MEM_TYPE_64BIT: region->is_64 = 1; reg64 = reg; size64 = size; bar += sizeof(uint32_t); err = pci_read(domain, bus, dev, func, bar, ®); if (err) return err; reg64 |= (uint64_t)reg << 32; err = pci_readmask(domain, bus, dev, func, bar, &size); if (err) return err; size64 |= (uint64_t)size << 32; region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64); region->size = PCI_MAPREG_MEM64_SIZE(size64); region++; break; } } } /* Probe expansion ROM if present */ err = pci_read(domain, bus, dev, func, PCI_ROM_REG, ®); if (err) return err; if (reg != 0) { err = pci_write(domain, bus, dev, func, PCI_ROM_REG, ~PCI_ROM_ENABLE); if (err) return err; pci_read(domain, bus, dev, func, PCI_ROM_REG, &size); pci_write(domain, bus, dev, func, PCI_ROM_REG, reg); if (PCI_ROM_ADDR(reg) != 0) { priv->rom_base = PCI_ROM_ADDR(reg); device->rom_size = PCI_ROM_SIZE(size); } } return 0; }
/** * 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); }