static bool radeon_read_bios(struct radeon_device *rdev) { uint8_t __iomem *bios; bus_size_t size; pcireg_t address, mask; bus_space_handle_t romh; int rc; rdev->bios = NULL; /* XXX: some cards may return 0 for rom size? ddx has a workaround */ address = pci_conf_read(rdev->pc, rdev->pa_tag, PCI_ROM_REG); pci_conf_write(rdev->pc, rdev->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE); mask = pci_conf_read(rdev->pc, rdev->pa_tag, PCI_ROM_REG); address |= PCI_ROM_ENABLE; pci_conf_write(rdev->pc, rdev->pa_tag, PCI_ROM_REG, address); size = PCI_ROM_SIZE(mask); if (size == 0) return false; rc = bus_space_map(rdev->memt, PCI_ROM_ADDR(address), size, BUS_SPACE_MAP_LINEAR, &romh); if (rc != 0) { printf(": can't map PCI ROM (%d)\n", rc); return false; } bios = (uint8_t *)bus_space_vaddr(rdev->memt, romh); if (!bios) { printf(": bus_space_vaddr failed\n"); return false; } if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) goto fail; rdev->bios = kmalloc(size, GFP_KERNEL); memcpy(rdev->bios, bios, size); bus_space_unmap(rdev->memt, romh, size); return true; fail: bus_space_unmap(rdev->memt, romh, size); return false; }
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; }
int cas_pci_enaddr(struct cas_softc *sc, struct pci_attach_args *pa) { struct pci_vpd_largeres *res; struct pci_vpd *vpd; bus_space_handle_t romh; bus_space_tag_t romt; bus_size_t romsize; u_int8_t buf[32], *desc; pcireg_t address, mask; int dataoff, vpdoff, len; int rv = -1; address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, 0xfffffffe); mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); address |= PCI_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address); romt = pa->pa_memt; romsize = PCI_ROM_SIZE(mask); if (bus_space_map(romt, PCI_ROM_ADDR(address), romsize, 0, &romh)) { romsize = 0; goto fail; } bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf)); if (bcmp(buf, cas_promhdr, sizeof(cas_promhdr))) goto fail; dataoff = buf[PROMHDR_PTR_DATA] | (buf[PROMHDR_PTR_DATA + 1] << 8); if (dataoff < 0x1c) goto fail; bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf)); if (bcmp(buf, cas_promdat, sizeof(cas_promdat)) || bcmp(buf + PROMDATA_DATA2, cas_promdat2, sizeof(cas_promdat2))) goto fail; vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8); if (vpdoff < 0x1c) goto fail; next: bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf)); if (!PCI_VPDRES_ISLARGE(buf[0])) goto fail; res = (struct pci_vpd_largeres *)buf; vpdoff += sizeof(*res); len = ((res->vpdres_len_msb << 8) + res->vpdres_len_lsb); switch(PCI_VPDRES_LARGE_NAME(res->vpdres_byte0)) { case PCI_VPDRES_TYPE_IDENTIFIER_STRING: /* Skip identifier string. */ vpdoff += len; goto next; case PCI_VPDRES_TYPE_VPD: while (len > 0) { bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf)); vpd = (struct pci_vpd *)buf; vpdoff += sizeof(*vpd) + vpd->vpd_len; len -= sizeof(*vpd) + vpd->vpd_len; /* * We're looking for an "Enhanced" VPD... */ if (vpd->vpd_key0 != 'Z') continue; desc = buf + sizeof(*vpd); /* * ...which is an instance property... */ if (desc[0] != 'I') continue; desc += 3; /* * ...that's a byte array with the proper * length for a MAC address... */ if (desc[0] != 'B' || desc[1] != ETHER_ADDR_LEN) continue; desc += 2; /* * ...named "local-mac-address". */ if (strcmp(desc, "local-mac-address") != 0) continue; desc += strlen("local-mac-address") + 1; bcopy(desc, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); rv = 0; } break; default: goto fail; } fail: if (romsize != 0) bus_space_unmap(romt, romh, romsize); address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); address &= ~PCI_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address); return (rv); }
void ppb_alloc_resources(struct ppb_softc *sc, struct pci_attach_args *pa) { pci_chipset_tag_t pc = sc->sc_pc; pcireg_t id, busdata, blr, bhlcr, type, csr; pcireg_t addr, mask; pcitag_t tag; int bus, dev; int reg, reg_start, reg_end, reg_rom; int io_count = 0; int mem_count = 0; bus_addr_t start, end; u_long base, size; if (pa->pa_memex == NULL) return; busdata = pci_conf_read(pc, sc->sc_tag, PPB_REG_BUSINFO); bus = PPB_BUSINFO_SECONDARY(busdata); if (bus == 0) return; /* * Count number of devices. If there are no devices behind * this bridge, there's no point in allocating any address * space. */ for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) { tag = pci_make_tag(pc, bus, dev, 0); id = pci_conf_read(pc, tag, PCI_ID_REG); if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0) continue; bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); switch (PCI_HDRTYPE_TYPE(bhlcr)) { case 0: reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_END; reg_rom = PCI_ROM_REG; break; case 1: /* PCI-PCI bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PPB_END; reg_rom = 0; /* 0x38 */ break; case 2: /* PCI-Cardbus bridge */ reg_start = PCI_MAPREG_START; reg_end = PCI_MAPREG_PCB_END; reg_rom = 0; break; default: return; } for (reg = reg_start; reg < reg_end; reg += 4) { if (pci_mapreg_probe(pc, tag, reg, &type) == 0) continue; if (type == PCI_MAPREG_TYPE_IO) io_count++; else mem_count++; } if (reg_rom != 0) { addr = pci_conf_read(pc, tag, reg_rom); pci_conf_write(pc, tag, reg_rom, ~PCI_ROM_ENABLE); mask = pci_conf_read(pc, tag, reg_rom); pci_conf_write(pc, tag, reg_rom, addr); if (PCI_ROM_SIZE(mask)) mem_count++; } } csr = pci_conf_read(pc, sc->sc_tag, PCI_COMMAND_STATUS_REG); /* * Get the bridge in a consistent state. If memory mapped I/O * is disabled, disabled the associated windows as well. */ if ((csr & PCI_COMMAND_MEM_ENABLE) == 0) { pci_conf_write(pc, sc->sc_tag, PPB_REG_MEM, 0x0000ffff); pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFMEM, 0x0000ffff); pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFBASE_HI32, 0); pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFLIM_HI32, 0); } /* Allocate I/O address space if necessary. */ if (io_count > 0 && pa->pa_ioex) { blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_IOSTATUS); sc->sc_iobase = (blr << PPB_IO_SHIFT) & PPB_IO_MASK; sc->sc_iolimit = (blr & PPB_IO_MASK) | 0x00000fff; blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_IO_HI); sc->sc_iobase |= (blr & 0x0000ffff) << 16; sc->sc_iolimit |= (blr & 0xffff0000); if (sc->sc_iolimit < sc->sc_iobase || sc->sc_iobase == 0) { start = max(PCI_IO_START, pa->pa_ioex->ex_start); end = min(PCI_IO_END, pa->pa_ioex->ex_end); for (size = 0x2000; size >= PPB_IO_MIN; size >>= 1) if (extent_alloc_subregion(pa->pa_ioex, start, end, size, size, 0, 0, 0, &base) == 0) break; if (size >= PPB_IO_MIN) { sc->sc_iobase = base; sc->sc_iolimit = base + size - 1; blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_IOSTATUS); blr &= 0xffff0000; blr |= sc->sc_iolimit & PPB_IO_MASK; blr |= (sc->sc_iobase >> PPB_IO_SHIFT); pci_conf_write(pc, sc->sc_tag, PPB_REG_IOSTATUS, blr); blr = (sc->sc_iobase & 0xffff0000) >> 16; blr |= sc->sc_iolimit & 0xffff0000; pci_conf_write(pc, sc->sc_tag, PPB_REG_IO_HI, blr); csr |= PCI_COMMAND_IO_ENABLE; }
/** * 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 gem_pci_enaddr(struct gem_softc *sc, struct pci_attach_args *pa) { struct pci_vpd *vpd; bus_space_handle_t romh; bus_space_tag_t romt; bus_size_t romsize; u_int8_t buf[32]; pcireg_t address, mask; int dataoff, vpdoff; int rv = -1; address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, 0xfffffffe); mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); address |= PCI_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address); romt = pa->pa_memt; romsize = PCI_ROM_SIZE(mask); if (bus_space_map(romt, PCI_ROM_ADDR(address), romsize, 0, &romh)) { romsize = 0; goto fail; } bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf)); if (bcmp(buf, gem_promhdr, sizeof(gem_promhdr))) goto fail; dataoff = buf[PROMHDR_PTR_DATA] | (buf[PROMHDR_PTR_DATA + 1] << 8); if (dataoff < 0x1c) goto fail; bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf)); if (bcmp(buf, gem_promdat, sizeof(gem_promdat)) || bcmp(buf + PROMDATA_DATA2, gem_promdat2, sizeof(gem_promdat2))) goto fail; vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8); if (vpdoff < 0x1c) goto fail; bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf)); /* * The VPD of gem is not in PCI 2.2 standard format. The length * in the resource header is in big endian. */ vpd = (struct pci_vpd *)(buf + 3); if (!PCI_VPDRES_ISLARGE(buf[0]) || PCI_VPDRES_LARGE_NAME(buf[0]) != PCI_VPDRES_TYPE_VPD) goto fail; if (vpd->vpd_key0 != 'N' || vpd->vpd_key1 != 'A') goto fail; bcopy(buf + 6, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); rv = 0; fail: if (romsize != 0) bus_space_unmap(romt, romh, romsize); address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); address &= ~PCI_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address); return (rv); }
/* * Grovel the STI ROM image. */ int sti_check_rom(struct sti_pci_softc *spc, struct pci_attach_args *pa) { struct sti_softc *sc = &spc->sc_base; pcireg_t address, mask; bus_space_handle_t romh; bus_size_t romsize, subsize, stiromsize; bus_addr_t selected, offs, suboffs; u_int32_t tmp; int i; int rc; /* sort of inline sti_pci_enable_rom(sc) */ address = 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); address |= PCI_ROM_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address); sc->sc_flags |= STI_ROM_ENABLED; /* * Map the complete ROM for now. */ romsize = PCI_ROM_SIZE(mask); rc = bus_space_map(pa->pa_memt, PCI_ROM_ADDR(address), romsize, 0, &romh); sti_pci_disable_rom(sc); if (rc != 0) { printf("%s: can't map PCI ROM (%d)\n", sc->sc_dev.dv_xname, rc); goto fail2; } /* * Iterate over the ROM images, pick the best candidate. */ selected = (bus_addr_t)-1; for (offs = 0; offs < romsize; offs += subsize) { sti_pci_enable_rom(sc); /* * Check for a valid ROM header. */ tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0); tmp = letoh32(tmp); if (tmp != 0x55aa0000) { sti_pci_disable_rom(sc); if (offs == 0) { printf("%s: invalid PCI ROM header signature" " (%08x)\n", sc->sc_dev.dv_xname, tmp); rc = EINVAL; } break; } /* * Check ROM type. */ tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4); tmp = letoh32(tmp); if (tmp != 0x00000001) { /* 1 == STI ROM */ sti_pci_disable_rom(sc); if (offs == 0) { printf("%s: invalid PCI ROM type (%08x)\n", sc->sc_dev.dv_xname, tmp); rc = EINVAL; } break; } subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, offs + 0x0c); subsize <<= 9; #ifdef STIDEBUG sti_pci_disable_rom(sc); printf("ROM offset %08lx size %08lx type %08x", offs, subsize, tmp); sti_pci_enable_rom(sc); #endif /* * Check for a valid ROM data structure. * We do not need it except to know what architecture the ROM * code is for. */ suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh, offs + 0x18); tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0); tmp = letoh32(tmp); if (tmp != 0x50434952) { /* PCIR */ sti_pci_disable_rom(sc); if (offs == 0) { printf("%s: invalid PCI data signature" " (%08x)\n", sc->sc_dev.dv_xname, tmp); rc = EINVAL; } else { #ifdef STIDEBUG printf(" invalid PCI data signature %08x\n", tmp); #endif continue; } } tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14); sti_pci_disable_rom(sc); #ifdef STIDEBUG printf(" code %02x", tmp); #endif switch (tmp) { #ifdef __hppa__ case 0x10: if (selected == (bus_addr_t)-1) selected = offs; break; #endif #ifdef __i386__ case 0x00: if (selected == (bus_addr_t)-1) selected = offs; break; #endif default: #ifdef STIDEBUG printf(" (wrong architecture)"); #endif break; } #ifdef STIDEBUG if (selected == offs) printf(" -> SELECTED"); printf("\n"); #endif } if (selected == (bus_addr_t)-1) { if (rc == 0) { printf("%s: found no ROM with correct microcode" " architecture\n", sc->sc_dev.dv_xname); rc = ENOEXEC; } goto fail; } /* * Read the STI region BAR assignments. */ sti_pci_enable_rom(sc); offs = selected + (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e); for (i = 0; i < STI_REGION_MAX; i++) { rc = sti_readbar(sc, pa, i, bus_space_read_1(pa->pa_memt, romh, offs + i)); if (rc != 0) goto fail; } /* * Find out where the STI ROM itself lies, and its size. */ offs = selected + (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08); stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, offs + 0x18); stiromsize = letoh32(stiromsize); sti_pci_disable_rom(sc); /* * Replace our mapping with a smaller mapping of only the area * we are interested in. */ bus_space_unmap(pa->pa_memt, romh, romsize); rc = bus_space_map(pa->pa_memt, PCI_ROM_ADDR(address) + offs, stiromsize, 0, &spc->sc_romh); if (rc != 0) { printf("%s: can't map STI ROM (%d)\n", sc->sc_dev.dv_xname, rc); goto fail2; } return (0); fail: bus_space_unmap(pa->pa_memt, romh, romsize); fail2: sti_pci_disable_rom(sc); return (rc); }