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; }
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 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; }
/* * 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; }
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")); }
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__) || 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); }
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); }
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 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); } }
/** * 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); }
/* * Enable memory and I/O on pci devices. Care about already enabled devices * (probabaly by the console driver). * * The idea behind the following code is: * We build a by sizes sorted list of the requirements of the different * pci devices. After that we choose the start addresses of that areas * in such a way that they are placed as closed as possible together. */ static void enable_pci_devices(void) { PCI_MEMREG memlist; PCI_MEMREG iolist; struct pci_memreg *p, *q; int dev, reg, id, class; pcitag_t tag; pcireg_t csr, address, mask; pci_chipset_tag_t pc; int sizecnt, membase_1m; pc = 0; csr = 0; tag = 0; LIST_INIT(&memlist); LIST_INIT(&iolist); /* * first step: go through all devices and gather memory and I/O * sizes */ for (dev = 0; dev < pci_bus_maxdevs(pc,0); dev++) { tag = pci_make_tag(pc, 0, dev, 0); id = pci_conf_read(pc, tag, PCI_ID_REG); if (id == 0 || id == 0xffffffff) continue; csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); /* * special case: if a display card is found and memory is enabled * preserve 128k at 0xa0000 as vga memory. * XXX: if a display card is found without being enabled, leave * it alone! You will usually only create conflicts by enabeling * it. */ class = pci_conf_read(pc, tag, PCI_CLASS_REG); switch (PCI_CLASS(class)) { case PCI_CLASS_PREHISTORIC: case PCI_CLASS_DISPLAY: if (csr & (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) { p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg), M_TEMP, M_WAITOK); memset(p, '\0', sizeof(struct pci_memreg)); p->dev = dev; p->csr = csr; p->tag = tag; p->reg = 0; /* there is no register about this */ p->size = 0x20000; /* 128kByte */ p->mask = 0xfffe0000; p->address = 0xa0000; insert_into_list(&memlist, p); } else continue; } for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) { 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 (mask == 0) continue; /* Register unused */ p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg), M_TEMP, M_WAITOK); memset(p, '\0', sizeof(struct pci_memreg)); p->dev = dev; p->csr = csr; p->tag = tag; p->reg = reg; p->mask = mask; p->address = 0; if (mask & PCI_MAPREG_TYPE_IO) { p->size = PCI_MAPREG_IO_SIZE(mask); /* * Align IO if necessary */ if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_IO_ALIGN_MASK)) { p->mask = PCI_MACHDEP_IO_ALIGN_MASK; p->size = PCI_MAPREG_IO_SIZE(p->mask); } /* * if I/O is already enabled (probably by the console driver) * save the address in order to take care about it later. */ if (csr & PCI_COMMAND_IO_ENABLE) p->address = address; insert_into_list(&iolist, p); } else { p->size = PCI_MAPREG_MEM_SIZE(mask); /* * Align memory if necessary */ if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_MEM_ALIGN_MASK)) { p->mask = PCI_MACHDEP_MEM_ALIGN_MASK; p->size = PCI_MAPREG_MEM_SIZE(p->mask); } /* * if memory is already enabled (probably by the console driver) * save the address in order to take care about it later. */ if (csr & PCI_COMMAND_MEM_ENABLE) p->address = address; insert_into_list(&memlist, p); if (PCI_MAPREG_MEM_TYPE(mask) == PCI_MAPREG_MEM_TYPE_64BIT) reg++; } } #if defined(_ATARIHW_) /* * Both interrupt pin & line are set to the device (== slot) * number. This makes sense on the atari Hades because the * individual slots are hard-wired to a specific MFP-pin. */ csr = (DEV2SLOT(dev) << PCI_INTERRUPT_PIN_SHIFT); csr |= (DEV2SLOT(dev) << PCI_INTERRUPT_LINE_SHIFT); pci_conf_write(pc, tag, PCI_INTERRUPT_REG, csr); #else /* * On the Milan, we accept the BIOS's choice. */ #endif } /* * second step: calculate the memory and I/O addresses beginning from * PCI_MEM_START and PCI_IO_START. Care about already mapped areas. * * begin with memory list */ address = PCI_MEM_START; sizecnt = 0; membase_1m = 0; p = LIST_FIRST(&memlist); while (p != NULL) { if (!(p->csr & PCI_COMMAND_MEM_ENABLE)) { if (PCI_MAPREG_MEM_TYPE(p->mask) == PCI_MAPREG_MEM_TYPE_32BIT_1M) { if (p->size > membase_1m) membase_1m = p->size; do { p->address = membase_1m; membase_1m += p->size; } while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address, p->size, PCI_COMMAND_MEM_ENABLE)); if (membase_1m > 0x00100000) { /* * Should we panic here? */ printf("\npcibus0: dev %d reg %d: memory not configured", p->dev, p->reg); p->reg = 0; } } else { if (sizecnt && (p->size > sizecnt)) sizecnt = ((p->size + sizecnt) & p->mask) & PCI_MAPREG_MEM_ADDR_MASK; if (sizecnt > address) { address = sizecnt; sizecnt = 0; } do { p->address = address + sizecnt; sizecnt += p->size; } while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address, p->size, PCI_COMMAND_MEM_ENABLE)); if ((address + sizecnt) > PCI_MEM_END) { /* * Should we panic here? */ printf("\npcibus0: dev %d reg %d: memory not configured", p->dev, p->reg); p->reg = 0; } } if (p->reg > 0) { pci_conf_write(pc, p->tag, p->reg, p->address); csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG); csr |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr); p->csr = csr; } } p = LIST_NEXT(p, link); } /* * now the I/O list */ address = PCI_IO_START; sizecnt = 0; p = LIST_FIRST(&iolist); while (p != NULL) { if (!(p->csr & PCI_COMMAND_IO_ENABLE)) { if (sizecnt && (p->size > sizecnt)) sizecnt = ((p->size + sizecnt) & p->mask) & PCI_MAPREG_IO_ADDR_MASK; if (sizecnt > address) { address = sizecnt; sizecnt = 0; } do { p->address = address + sizecnt; sizecnt += p->size; } while (overlap_pci_areas(LIST_FIRST(&iolist), p, p->address, p->size, PCI_COMMAND_IO_ENABLE)); if ((address + sizecnt) > PCI_IO_END) { /* * Should we panic here? */ printf("\npcibus0: dev %d reg %d: io not configured", p->dev, p->reg); } else { pci_conf_write(pc, p->tag, p->reg, p->address); csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG); csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr); p->csr = csr; } } p = LIST_NEXT(p, link); } #ifdef DEBUG_PCI_MACHDEP printf("\nI/O List:\n"); p = LIST_FIRST(&iolist); while (p != NULL) { printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev, p->reg, p->size, p->address); p = LIST_NEXT(p, link); } printf("\nMemlist:"); p = LIST_FIRST(&memlist); while (p != NULL) { printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev, p->reg, p->size, p->address); p = LIST_NEXT(p, link); } #endif /* * Free the lists */ p = LIST_FIRST(&iolist); while (p != NULL) { q = p; LIST_REMOVE(q, link); free(p, M_WAITOK); p = LIST_FIRST(&iolist); } p = LIST_FIRST(&memlist); while (p != NULL) { q = p; LIST_REMOVE(q, link); free(p, M_WAITOK); p = LIST_FIRST(&memlist); } }