static int pci_device_freebsd_probe( struct pci_device * dev ) { struct pci_device_private *priv = (struct pci_device_private *) dev; struct pci_bar_io bar; uint8_t irq; int err, i; #if HAVE_PCI_IO_PC_DOMAIN bar.pbi_sel.pc_domain = dev->domain; #endif bar.pbi_sel.pc_bus = dev->bus; bar.pbi_sel.pc_dev = dev->dev; bar.pbi_sel.pc_func = dev->func; /* Many of the fields were filled in during initial device enumeration. * At this point, we need to fill in regions, rom_size, and irq. */ err = pci_device_cfg_read_u8( dev, &irq, 60 ); if (err) return errno; dev->irq = irq; for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) { bar.pbi_reg = PCIR_BAR(i); if ( ioctl( freebsd_pci_sys->pcidev, PCIOCGETBAR, &bar ) < 0 ) continue; if (PCI_BAR_IO(bar.pbi_base)) dev->regions[i].is_IO = 1; if ((bar.pbi_base & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) dev->regions[i].is_64 = 1; if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH) dev->regions[i].is_prefetchable = 1; dev->regions[i].base_addr = bar.pbi_base & ~((uint64_t)0xf); dev->regions[i].size = bar.pbi_length; } /* If it's a VGA device, set up the rom size for read_rom using the * 0xc0000 mapping. */ if ((dev->device_class & 0x00ffff00) == ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8))) { dev->rom_size = 64 * 1024; } return 0; }
static int ipmi2_pci_attach(device_t dev) { struct ipmi_softc *sc; int error, iface, type; sc = device_get_softc(dev); sc->ipmi_dev = dev; /* Interface is determined by progif. */ switch (pci_get_progif(dev)) { case PCIP_SERIALBUS_IPMI_SMIC: iface = SMIC_MODE; break; case PCIP_SERIALBUS_IPMI_KCS: iface = KCS_MODE; break; case PCIP_SERIALBUS_IPMI_BT: iface = BT_MODE; device_printf(dev, "BT interface unsupported\n"); return (ENXIO); default: device_printf(dev, "Unsupported interface: %d\n", pci_get_progif(dev)); return (ENXIO); } /* Check the BAR to determine our resource type. */ sc->ipmi_io_rid = PCIR_BAR(0); if (PCI_BAR_IO(pci_read_config(dev, PCIR_BAR(0), 4))) type = SYS_RES_IOPORT; else type = SYS_RES_MEMORY; sc->ipmi_io_type = type; sc->ipmi_io_spacing = 1; sc->ipmi_io_res[0] = bus_alloc_resource_any(dev, type, &sc->ipmi_io_rid, RF_ACTIVE); if (sc->ipmi_io_res[0] == NULL) { device_printf(dev, "couldn't map ports/memory\n"); return (ENXIO); } sc->ipmi_irq_rid = 0; sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE); switch (iface) { case KCS_MODE: device_printf(dev, "using KSC interface\n"); /* * We have to examine the resource directly to determine the * alignment. */ if (!ipmi_kcs_probe_align(sc)) { device_printf(dev, "Unable to determine alignment\n"); error = ENXIO; goto bad; } error = ipmi_kcs_attach(sc); if (error) goto bad; break; case SMIC_MODE: device_printf(dev, "using SMIC interface\n"); error = ipmi_smic_attach(sc); if (error) goto bad; break; } error = ipmi_attach(dev); if (error) goto bad; return (0); bad: ipmi_release_resources(dev); return (error); }
static int mpt_pci_attach(device_t dev) { struct mpt_softc *mpt; int iqd; uint32_t data, cmd; int mpt_io_bar, mpt_mem_bar; mpt = (struct mpt_softc*)device_get_softc(dev); switch (pci_get_device(dev)) { case MPI_MANUFACTPAGE_DEVICEID_FC909_FB: case MPI_MANUFACTPAGE_DEVICEID_FC909: case MPI_MANUFACTPAGE_DEVICEID_FC919: case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB: case MPI_MANUFACTPAGE_DEVICEID_FC929: case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB: case MPI_MANUFACTPAGE_DEVICEID_FC929X: case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB: case MPI_MANUFACTPAGE_DEVICEID_FC919X: case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB: case MPI_MANUFACTPAGE_DEVICEID_FC949E: case MPI_MANUFACTPAGE_DEVICEID_FC949X: mpt->is_fc = 1; break; case MPI_MANUFACTPAGE_DEVID_SAS1078: case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB: mpt->is_1078 = 1; /* FALLTHROUGH */ case MPI_MANUFACTPAGE_DEVID_SAS1064: case MPI_MANUFACTPAGE_DEVID_SAS1064A: case MPI_MANUFACTPAGE_DEVID_SAS1064E: case MPI_MANUFACTPAGE_DEVID_SAS1066: case MPI_MANUFACTPAGE_DEVID_SAS1066E: case MPI_MANUFACTPAGE_DEVID_SAS1068: case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB: case MPI_MANUFACTPAGE_DEVID_SAS1068E: case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB: mpt->is_sas = 1; break; default: mpt->is_spi = 1; break; } mpt->dev = dev; mpt->unit = device_get_unit(dev); mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT; mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; mpt->verbose = MPT_PRT_NONE; mpt->role = MPT_ROLE_NONE; mpt->mpt_ini_id = MPT_INI_ID_NONE; #ifdef __sparc64__ if (mpt->is_spi) mpt->mpt_ini_id = OF_getscsinitid(dev); #endif mpt_set_options(mpt); if (mpt->verbose == MPT_PRT_NONE) { mpt->verbose = MPT_PRT_WARN; /* Print INFO level (if any) if bootverbose is set */ mpt->verbose += (bootverbose != 0)? 1 : 0; } /* Make sure memory access decoders are enabled */ cmd = pci_read_config(dev, PCIR_COMMAND, 2); if ((cmd & PCIM_CMD_MEMEN) == 0) { device_printf(dev, "Memory accesses disabled"); return (ENXIO); } /* * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. */ cmd |= PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; pci_write_config(dev, PCIR_COMMAND, cmd, 2); /* * Make sure we've disabled the ROM. */ data = pci_read_config(dev, PCIR_BIOS, 4); data &= ~PCIM_BIOS_ENABLE; pci_write_config(dev, PCIR_BIOS, data, 4); /* * Is this part a dual? * If so, link with our partner (around yet) */ switch (pci_get_device(dev)) { case MPI_MANUFACTPAGE_DEVICEID_FC929: case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB: case MPI_MANUFACTPAGE_DEVICEID_FC949E: case MPI_MANUFACTPAGE_DEVICEID_FC949X: case MPI_MANUFACTPAGE_DEVID_53C1030: case MPI_MANUFACTPAGE_DEVID_53C1030ZC: mpt_link_peer(mpt); break; default: break; } /* * Figure out which are the I/O and MEM Bars */ data = pci_read_config(dev, PCIR_BAR(0), 4); if (PCI_BAR_IO(data)) { /* BAR0 is IO, BAR1 is memory */ mpt_io_bar = 0; mpt_mem_bar = 1; } else { /* BAR0 is memory, BAR1 is IO */ mpt_mem_bar = 0; mpt_io_bar = 1; } /* * Set up register access. PIO mode is required for * certain reset operations (but must be disabled for * some cards otherwise). */ mpt_io_bar = PCIR_BAR(mpt_io_bar); mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &mpt_io_bar, RF_ACTIVE); if (mpt->pci_pio_reg == NULL) { if (bootverbose) { device_printf(dev, "unable to map registers in PIO mode\n"); } } else { mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); } mpt_mem_bar = PCIR_BAR(mpt_mem_bar); mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mpt_mem_bar, RF_ACTIVE); if (mpt->pci_reg == NULL) { if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) { device_printf(dev, "Unable to memory map registers.\n"); } if (mpt->is_sas || mpt->pci_pio_reg == NULL) { device_printf(dev, "Giving Up.\n"); goto bad; } if (bootverbose) { device_printf(dev, "Falling back to PIO mode.\n"); } mpt->pci_st = mpt->pci_pio_st; mpt->pci_sh = mpt->pci_pio_sh; } else { mpt->pci_st = rman_get_bustag(mpt->pci_reg); mpt->pci_sh = rman_get_bushandle(mpt->pci_reg); } /* Get a handle to the interrupt */ iqd = 0; if (mpt->msi_enable) { /* * First try to alloc an MSI-X message. If that * fails, then try to alloc an MSI message instead. */ if (pci_msix_count(dev) == 1) { mpt->pci_msi_count = 1; if (pci_alloc_msix(dev, &mpt->pci_msi_count) == 0) { iqd = 1; } else { mpt->pci_msi_count = 0; } } if (iqd == 0 && pci_msi_count(dev) == 1) { mpt->pci_msi_count = 1; if (pci_alloc_msi(dev, &mpt->pci_msi_count) == 0) { iqd = 1; } else { mpt->pci_msi_count = 0; } } } mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | (mpt->pci_msi_count ? 0 : RF_SHAREABLE)); if (mpt->pci_irq == NULL) { device_printf(dev, "could not allocate interrupt\n"); goto bad; } MPT_LOCK_SETUP(mpt); /* Disable interrupts at the part */ mpt_disable_ints(mpt); /* Register the interrupt handler */ if (mpt_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr, mpt, &mpt->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; } /* Allocate dma memory */ if (mpt_dma_mem_alloc(mpt)) { mpt_prt(mpt, "Could not allocate DMA memory\n"); goto bad; } #if 0 /* * Save the PCI config register values * * Hard resets are known to screw up the BAR for diagnostic * memory accesses (Mem1). * * Using Mem1 is known to make the chip stop responding to * configuration space transfers, so we need to save it now */ mpt_read_config_regs(mpt); #endif /* * Disable PIO until we need it */ if (mpt->is_sas) { pci_disable_io(dev, SYS_RES_IOPORT); } /* Initialize the hardware */ if (mpt->disabled == 0) { if (mpt_attach(mpt) != 0) { goto bad; } } else { mpt_prt(mpt, "device disabled at user request\n"); goto bad; } mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown, dev, SHUTDOWN_PRI_DEFAULT); if (mpt->eh == NULL) { mpt_prt(mpt, "shutdown event registration failed\n"); (void) mpt_detach(mpt); goto bad; } return (0); bad: mpt_dma_mem_free(mpt); mpt_free_bus_resources(mpt); mpt_unlink_peer(mpt); MPT_LOCK_DESTROY(mpt); /* * but return zero to preserve unit numbering */ return (0); }
static int cfginitbar(struct vmctx *ctx, struct passthru_softc *sc) { int i, error; struct pci_devinst *pi; struct pci_bar_io bar; enum pcibar_type bartype; uint64_t base, size; pi = sc->psc_pi; /* * Initialize BAR registers */ for (i = 0; i <= PCI_BARMAX; i++) { bzero(&bar, sizeof(bar)); bar.pbi_sel = sc->psc_sel; bar.pbi_reg = PCIR_BAR(i); if (ioctl(pcifd, PCIOCGETBAR, &bar) < 0) continue; if (PCI_BAR_IO(bar.pbi_base)) { bartype = PCIBAR_IO; base = bar.pbi_base & PCIM_BAR_IO_BASE; } else { switch (bar.pbi_base & PCIM_BAR_MEM_TYPE) { case PCIM_BAR_MEM_64: bartype = PCIBAR_MEM64; break; default: bartype = PCIBAR_MEM32; break; } base = bar.pbi_base & PCIM_BAR_MEM_BASE; } size = bar.pbi_length; if (bartype != PCIBAR_IO) { if (((base | size) & PAGE_MASK) != 0) { printf("passthru device %d/%d/%d BAR %d: " "base %#lx or size %#lx not page aligned\n", sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, i, base, size); return (-1); } } /* Cache information about the "real" BAR */ sc->psc_bar[i].type = bartype; sc->psc_bar[i].size = size; sc->psc_bar[i].addr = base; /* Allocate the BAR in the guest I/O or MMIO space */ error = pci_emul_alloc_pbar(pi, i, base, bartype, size); if (error) return (-1); /* The MSI-X table needs special handling */ if (i == pci_msix_table_bar(pi)) { error = init_msix_table(ctx, sc, base); if (error) return (-1); } else if (bartype != PCIBAR_IO) { /* Map the physical BAR in the guest MMIO space */ error = vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, pi->pi_bar[i].addr, pi->pi_bar[i].size, base); if (error) return (-1); } /* * 64-bit BAR takes up two slots so skip the next one. */ if (bartype == PCIBAR_MEM64) { i++; assert(i <= PCI_BARMAX); sc->psc_bar[i].type = PCIBAR_MEMHI64; } } return (0); }