void rtsx_pci_attach(struct device *parent, struct device *self, void *aux) { struct rtsx_pci_softc *sc = (struct rtsx_pci_softc *)self; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; char const *intrstr; bus_space_tag_t iot; bus_space_handle_t ioh; bus_size_t size; int flags; if ((pci_conf_read(pa->pa_pc, pa->pa_tag, RTSX_CFG_PCI) & RTSX_CFG_ASIC) != 0) { printf("%s: no asic\n", sc->sc.sc_dev.dv_xname); return; } if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC, rtsx_intr, sc, sc->sc.sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt\n"); return; } printf(": %s\n", intrstr); if (pci_mem_find(pa->pa_pc, pa->pa_tag, RTSX_PCI_BAR, NULL, NULL, NULL) != 0) { printf("%s: can't find registers\n", sc->sc.sc_dev.dv_xname); return; } if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0, &iot, &ioh, NULL, &size, 0)) { printf("%s: can't map registers\n", sc->sc.sc_dev.dv_xname); return; } pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209) flags = RTSX_F_5209; else flags = RTSX_F_5229; if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0) printf("%s: can't initialize chip\n", sc->sc.sc_dev.dv_xname); }
void ahci_pci_attach(struct device *parent, struct device *self, void *aux) { struct ahci_pci_softc *psc = (struct ahci_pci_softc *)self; struct ahci_softc *sc = &psc->psc_ahci; struct pci_attach_args *pa = aux; const struct ahci_device *ad; pci_intr_handle_t ih; int mapped = 0; psc->psc_pc = pa->pa_pc; psc->psc_tag = pa->pa_tag; sc->sc_dmat = pa->pa_dmat; ad = ahci_lookup_device(pa); if (ad != NULL && ad->ad_attach != NULL) { if (ad->ad_attach(sc, pa) != 0) { /* error should be printed by ad_attach */ return; } } if (!(sc->sc_flags & AHCI_F_NO_MSI)) mapped = pci_intr_map_msi(pa, &ih) != 0 ? 0 : 1; if (!mapped && pci_intr_map(pa, &ih) != 0) { printf(": unable to map interrupt\n"); return; } printf(": %s,", pci_intr_string(pa->pa_pc, ih)); if (ahci_map_regs(psc, pa) != 0) { /* error already printed by ahci_map_regs */ return; } if (ahci_map_intr(psc, pa, ih) != 0) { /* error already printed by ahci_map_intr */ goto unmap; } if (ahci_attach(sc) != 0) { /* error printed by ahci_attach */ goto unmap; } return; unmap: ahci_unmap_regs(psc); return; }
void ppbattach(struct device *parent, struct device *self, void *aux) { struct ppb_softc *sc = (struct ppb_softc *)self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; struct pcibus_attach_args pba; pci_intr_handle_t ih; pcireg_t busdata, reg, blr; char *name; int pin; sc->sc_pc = pc; sc->sc_tag = pa->pa_tag; busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO); if (PPB_BUSINFO_SECONDARY(busdata) == 0) { printf(": not configured by system firmware\n"); return; } #if 0 /* * XXX can't do this, because we're not given our bus number * (we shouldn't need it), and because we've no way to * decompose our tag. */ /* sanity check. */ if (pa->pa_bus != PPB_BUSINFO_PRIMARY(busdata)) panic("ppbattach: bus in tag (%d) != bus in reg (%d)", pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata)); #endif /* Check for PCI Express capabilities and setup hotplug support. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, ®) && (reg & PCI_PCIE_XCAP_SI)) { #ifdef __i386__ if (pci_intr_map(pa, &ih) == 0) sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO, ppb_intr, sc, self->dv_xname); #else if (pci_intr_map_msi(pa, &ih) == 0 || pci_intr_map(pa, &ih) == 0) sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO, ppb_intr, sc, self->dv_xname); #endif if (sc->sc_intrhand) { printf(": %s", pci_intr_string(pc, ih)); /* Enable hotplug interrupt. */ reg = pci_conf_read(pc, pa->pa_tag, sc->sc_cap_off + PCI_PCIE_SLCSR); reg |= (PCI_PCIE_SLCSR_HPE | PCI_PCIE_SLCSR_PDE); pci_conf_write(pc, pa->pa_tag, sc->sc_cap_off + PCI_PCIE_SLCSR, reg); timeout_set(&sc->sc_to, ppb_hotplug_insert_finish, sc); } } printf("\n"); if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BA_HPB && PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82801BAM_HPB)) ppb_alloc_resources(sc, pa); for (pin = PCI_INTERRUPT_PIN_A; pin <= PCI_INTERRUPT_PIN_D; pin++) { pa->pa_intrpin = pa->pa_rawintrpin = pin; pa->pa_intrline = 0; pci_intr_map(pa, &sc->sc_ih[pin - PCI_INTERRUPT_PIN_A]); } /* * The UltraSPARC-IIi APB doesn't implement the standard * address range registers. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_SIMBA) goto attach; /* Figure out the I/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IOSTATUS); sc->sc_iobase = (blr & 0x000000f0) << 8; sc->sc_iolimit = (blr & 0x000f000) | 0x00000fff; blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IO_HI); sc->sc_iobase |= (blr & 0x0000ffff) << 16; sc->sc_iolimit |= (blr & 0xffff0000); if (sc->sc_iolimit > sc->sc_iobase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pciio", sc->sc_dev.dv_xname); sc->sc_ioex = extent_create(name, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_ioex, sc->sc_iobase, sc->sc_iolimit - sc->sc_iobase + 1, EX_NOWAIT); } } /* Figure out the memory mapped I/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_MEM); sc->sc_membase = (blr & 0x0000fff0) << 16; sc->sc_memlimit = (blr & 0xfff00000) | 0x000fffff; if (sc->sc_memlimit > sc->sc_membase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pcimem", sc->sc_dev.dv_xname); sc->sc_memex = extent_create(name, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_memex, sc->sc_membase, sc->sc_memlimit - sc->sc_membase + 1, EX_NOWAIT); } } /* Figure out the prefetchable MMI/O address range of the bridge. */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFMEM); sc->sc_pmembase = (blr & 0x0000fff0) << 16; sc->sc_pmemlimit = (blr & 0xfff00000) | 0x000fffff; #ifdef __LP64__ /* XXX because extents use long... */ blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFBASE_HI32); sc->sc_pmembase |= ((uint64_t)blr) << 32; blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFLIM_HI32); sc->sc_pmemlimit |= ((uint64_t)blr) << 32; #endif if (sc->sc_pmemlimit > sc->sc_pmembase) { name = malloc(32, M_DEVBUF, M_NOWAIT); if (name) { snprintf(name, 32, "%s pcipmem", sc->sc_dev.dv_xname); sc->sc_pmemex = extent_create(name, 0, (u_long)-1L, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); extent_free(sc->sc_pmemex, sc->sc_pmembase, sc->sc_pmemlimit - sc->sc_pmembase + 1, EX_NOWAIT); } } /* * The Intel 82801BAM Hub-to-PCI can decode subtractively. * XXX We probably should handle subtractive decode bridges * in general. */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BA_HPB || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_HPB)) { if (sc->sc_ioex == NULL) sc->sc_ioex = pa->pa_ioex; if (sc->sc_memex == NULL) sc->sc_memex = pa->pa_memex; } attach: /* * Attach the PCI bus that hangs off of it. * * XXX Don't pass-through Memory Read Multiple. Should we? * XXX Consult the spec... */ bzero(&pba, sizeof(pba)); pba.pba_busname = "pci"; pba.pba_iot = pa->pa_iot; pba.pba_memt = pa->pa_memt; pba.pba_dmat = pa->pa_dmat; pba.pba_pc = pc; pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY; pba.pba_ioex = sc->sc_ioex; pba.pba_memex = sc->sc_memex; pba.pba_pmemex = sc->sc_pmemex; pba.pba_domain = pa->pa_domain; pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata); pba.pba_bridgeih = sc->sc_ih; pba.pba_bridgetag = &sc->sc_tag; pba.pba_intrswiz = pa->pa_intrswiz; pba.pba_intrtag = pa->pa_intrtag; sc->sc_psc = config_found(self, &pba, ppbprint); }
/** * radeon_driver_load_kms - Main load function for KMS. * * @dev: drm dev pointer * @flags: device flags * * This is the main load function for KMS (all asics). * It calls radeon_device_init() to set up the non-display * parts of the chip (asic init, CP, writeback, etc.), and * radeon_modeset_init() to set up the display parts * (crtcs, encoders, hotplug detect, etc.). * Returns 0 on success, error on failure. */ void radeondrm_attach_kms(struct device *parent, struct device *self, void *aux) { struct radeon_device *rdev = (struct radeon_device *)self; struct drm_device *dev; struct pci_attach_args *pa = aux; const struct drm_pcidev *id_entry; int is_agp; pcireg_t type; uint8_t iobar; #if !defined(__sparc64__) pcireg_t addr, mask; int s; #endif #if defined(__sparc64__) || defined(__macppc__) extern int fbnode; #endif id_entry = drm_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist); rdev->flags = id_entry->driver_data; rdev->pc = pa->pa_pc; rdev->pa_tag = pa->pa_tag; rdev->iot = pa->pa_iot; rdev->memt = pa->pa_memt; rdev->dmat = pa->pa_dmat; #if defined(__sparc64__) || defined(__macppc__) if (fbnode == PCITAG_NODE(rdev->pa_tag)) rdev->console = 1; #else if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA && (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) { rdev->console = 1; #if NVGA > 0 vga_console_attached = 1; #endif } #if NEFIFB > 0 if (efifb_is_console(pa)) { rdev->console = 1; efifb_cndetach(); } #endif #endif #define RADEON_PCI_MEM 0x10 #define RADEON_PCI_IO 0x14 #define RADEON_PCI_MMIO 0x18 #define RADEON_PCI_IO2 0x20 type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM); if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM || pci_mapreg_info(pa->pa_pc, pa->pa_tag, RADEON_PCI_MEM, type, &rdev->fb_aper_offset, &rdev->fb_aper_size, NULL)) { printf(": can't get frambuffer info\n"); return; } if (PCI_MAPREG_MEM_TYPE(type) != PCI_MAPREG_MEM_TYPE_64BIT) iobar = RADEON_PCI_IO; else iobar = RADEON_PCI_IO2; if (pci_mapreg_map(pa, iobar, PCI_MAPREG_TYPE_IO, 0, NULL, &rdev->rio_mem, NULL, &rdev->rio_mem_size, 0)) { printf(": can't map IO space\n"); return; } type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RADEON_PCI_MMIO); if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM || pci_mapreg_map(pa, RADEON_PCI_MMIO, type, 0, NULL, &rdev->rmmio, &rdev->rmmio_base, &rdev->rmmio_size, 0)) { printf(": can't map mmio space\n"); return; } #if !defined(__sparc64__) /* * Make sure we have a base address for the ROM such that we * can map it later. */ s = splhigh(); addr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE); mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, addr); splx(s); if (addr == 0 && PCI_ROM_SIZE(mask) != 0 && pa->pa_memex) { bus_size_t size, start, end; bus_addr_t base; size = PCI_ROM_SIZE(mask); start = max(PCI_MEM_START, pa->pa_memex->ex_start); end = min(PCI_MEM_END, pa->pa_memex->ex_end); if (extent_alloc_subregion(pa->pa_memex, start, end, size, size, 0, 0, 0, &base) == 0) pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, base); } #endif #ifdef notyet mtx_init(&rdev->swi_lock, IPL_TTY); #endif /* update BUS flag */ if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL)) { rdev->flags |= RADEON_IS_AGP; } else if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, NULL, NULL)) { rdev->flags |= RADEON_IS_PCIE; } else { rdev->flags |= RADEON_IS_PCI; } DRM_DEBUG("%s card detected\n", ((rdev->flags & RADEON_IS_AGP) ? "AGP" : (((rdev->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL); printf("\n"); kms_driver.num_ioctls = radeon_max_kms_ioctl; dev = (struct drm_device *)drm_attach_pci(&kms_driver, pa, is_agp, rdev->console, self); rdev->ddev = dev; rdev->pdev = dev->pdev; rdev->family = rdev->flags & RADEON_FAMILY_MASK; if (!radeon_msi_ok(rdev)) pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED; rdev->msi_enabled = 0; if (pci_intr_map_msi(pa, &rdev->intrh) == 0) rdev->msi_enabled = 1; else if (pci_intr_map(pa, &rdev->intrh) != 0) { printf(": couldn't map interrupt\n"); return; } printf("%s: %s\n", rdev->dev.dv_xname, pci_intr_string(pa->pa_pc, rdev->intrh)); rdev->irqh = pci_intr_establish(pa->pa_pc, rdev->intrh, IPL_TTY, radeon_driver_irq_handler_kms, rdev->ddev, rdev->dev.dv_xname); if (rdev->irqh == NULL) { printf("%s: couldn't establish interrupt\n", rdev->dev.dv_xname); return; } #ifdef __sparc64__ { struct rasops_info *ri; int node, console; node = PCITAG_NODE(pa->pa_tag); console = (fbnode == node); fb_setsize(&rdev->sf, 8, 1152, 900, node, 0); /* * The firmware sets up the framebuffer such that at starts at * an offset from the start of video memory. */ rdev->fb_offset = bus_space_read_4(rdev->memt, rdev->rmmio, RADEON_CRTC_OFFSET); if (bus_space_map(rdev->memt, rdev->fb_aper_offset + rdev->fb_offset, rdev->sf.sf_fbsize, BUS_SPACE_MAP_LINEAR, &rdev->memh)) { printf("%s: can't map video memory\n", rdev->dev.dv_xname); return; } ri = &rdev->sf.sf_ro; ri->ri_bits = bus_space_vaddr(rdev->memt, rdev->memh); ri->ri_hw = rdev; ri->ri_updatecursor = NULL; fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console); if (console) fbwscons_console_init(&rdev->sf, -1); } #endif rdev->shutdown = true; config_mountroot(self, radeondrm_attachhook); }
void rtwn_pci_attach(struct device *parent, struct device *self, void *aux) { struct rtwn_pci_softc *sc = (struct rtwn_pci_softc*)self; struct pci_attach_args *pa = aux; struct ifnet *ifp; int i, error; pcireg_t memtype; pci_intr_handle_t ih; const char *intrstr; sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; timeout_set(&sc->calib_to, rtwn_calib_to, sc); timeout_set(&sc->scan_to, rtwn_scan_to, sc); pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* Map control/status registers. */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RTWN_PCI_MMBA); error = pci_mapreg_map(pa, RTWN_PCI_MMBA, memtype, 0, &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_mapsize, 0); if (error != 0) { printf(": can't map mem space\n"); return; } if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(sc->sc_pc, ih); sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET, rtwn_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": can't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); /* Disable PCIe Active State Power Management (ASPM). */ if (pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL)) { uint32_t lcsr = pci_conf_read(sc->sc_pc, sc->sc_tag, sc->sc_cap_off + PCI_PCIE_LCSR); lcsr &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1); pci_conf_write(sc->sc_pc, sc->sc_tag, sc->sc_cap_off + PCI_PCIE_LCSR, lcsr); } /* Allocate Tx/Rx buffers. */ error = rtwn_alloc_rx_list(sc); if (error != 0) { printf("%s: could not allocate Rx buffers\n", sc->sc_dev.dv_xname); return; } for (i = 0; i < RTWN_NTXQUEUES; i++) { error = rtwn_alloc_tx_list(sc, i); if (error != 0) { printf("%s: could not allocate Tx buffers\n", sc->sc_dev.dv_xname); rtwn_free_rx_list(sc); return; } } /* Attach the bus-agnostic driver. */ sc->sc_sc.sc_ops.cookie = sc; sc->sc_sc.sc_ops.write_1 = rtwn_pci_write_1; sc->sc_sc.sc_ops.write_2 = rtwn_pci_write_2; sc->sc_sc.sc_ops.write_4 = rtwn_pci_write_4; sc->sc_sc.sc_ops.read_1 = rtwn_pci_read_1; sc->sc_sc.sc_ops.read_2 = rtwn_pci_read_2; sc->sc_sc.sc_ops.read_4 = rtwn_pci_read_4; sc->sc_sc.sc_ops.tx = rtwn_tx; sc->sc_sc.sc_ops.power_on = rtwn_power_on; sc->sc_sc.sc_ops.dma_init = rtwn_dma_init; sc->sc_sc.sc_ops.load_firmware = rtwn_pci_load_firmware; sc->sc_sc.sc_ops.fw_loadpage = rtwn_fw_loadpage; sc->sc_sc.sc_ops.mac_init = rtwn_mac_init; sc->sc_sc.sc_ops.bb_init = rtwn_bb_init; sc->sc_sc.sc_ops.alloc_buffers = rtwn_alloc_buffers; sc->sc_sc.sc_ops.init = rtwn_pci_init; sc->sc_sc.sc_ops.stop = rtwn_pci_stop; sc->sc_sc.sc_ops.is_oactive = rtwn_is_oactive; sc->sc_sc.sc_ops.next_calib = rtwn_next_calib; sc->sc_sc.sc_ops.cancel_calib = rtwn_cancel_calib; sc->sc_sc.sc_ops.next_scan = rtwn_pci_next_scan; sc->sc_sc.sc_ops.cancel_scan = rtwn_cancel_scan; sc->sc_sc.sc_ops.wait_async = rtwn_wait_async; error = rtwn_attach(&sc->sc_dev, &sc->sc_sc, RTWN_CHIP_88C | RTWN_CHIP_PCI); if (error != 0) { rtwn_free_rx_list(sc); for (i = 0; i < RTWN_NTXQUEUES; i++) rtwn_free_tx_list(sc, i); return; } /* ifp is now valid */ ifp = &sc->sc_sc.sc_ic.ic_if; #if NBPFILTER > 0 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO, sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN); sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); sc->sc_rxtap.wr_ihdr.it_present = htole32(RTWN_RX_RADIOTAP_PRESENT); sc->sc_txtap_len = sizeof(sc->sc_txtapu); sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(RTWN_TX_RADIOTAP_PRESENT); #endif }
void virtio_pci_attach(struct device *parent, struct device *self, void *aux) { struct virtio_pci_softc *sc = (struct virtio_pci_softc *)self; struct virtio_softc *vsc = &sc->sc_sc; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; int revision; pcireg_t id; char const *intrstr; pci_intr_handle_t ih; revision = PCI_REVISION(pa->pa_class); if (revision != 0) { printf("unknown revision 0x%02x; giving up\n", revision); return; } /* subsystem ID shows what I am */ id = PCI_PRODUCT(pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG)); printf(": Virtio %s Device", virtio_device_string(id)); #ifdef notyet if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, NULL)) printf(", msix capable"); #endif printf("\n"); vsc->sc_ops = &virtio_pci_ops; sc->sc_pc = pc; vsc->sc_dmat = pa->pa_dmat; sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI; if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize, 0)) { printf("%s: can't map i/o space\n", vsc->sc_dev.dv_xname); return; } virtio_device_reset(vsc); virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); virtio_pci_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); /* XXX: use softc as aux... */ vsc->sc_childdevid = id; vsc->sc_child = NULL; config_found(self, sc, NULL); if (vsc->sc_child == NULL) { printf("%s: no matching child driver; not configured\n", vsc->sc_dev.dv_xname); goto fail_1; } if (vsc->sc_child == VIRTIO_CHILD_ERROR) { printf("%s: virtio configuration failed\n", vsc->sc_dev.dv_xname); goto fail_1; } if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname); goto fail_2; } intrstr = pci_intr_string(pc, ih); /* * We always set the IPL_MPSAFE flag in order to do the relatively * expensive ISR read without lock, and then grab the kernel lock in * the interrupt handler. * For now, we don't support IPL_MPSAFE vq_done functions. */ KASSERT((vsc->sc_ipl & IPL_MPSAFE) == 0); sc->sc_ih = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE, virtio_pci_intr, sc, vsc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto fail_2; } printf("%s: %s\n", vsc->sc_dev.dv_xname, intrstr); virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK); return; fail_2: config_detach(vsc->sc_child, 0); fail_1: /* no pci_mapreg_unmap() or pci_intr_unmap() */ virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); }