Пример #1
0
int
pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type,
		   uint64_t size)
{

	return (pci_emul_alloc_pbar(pdi, idx, 0, type, size));
}
Пример #2
0
static int
pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
	struct pci_uart_softc *sc;
	uint64_t bar;
	int ivec;

	sc = malloc(sizeof(struct pci_uart_softc));
	memset(sc, 0, sizeof(struct pci_uart_softc));

	pi->pi_arg = sc;
	sc->pi = pi;

	pthread_mutex_init(&sc->mtx, NULL);

	/* initialize config space */
	pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
	pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM);
	if (pci_is_legacy(pi)) {
		pci_uart_legacy_res(&bar, &ivec);
		pci_emul_alloc_pbar(pi, 0, bar, PCIBAR_IO, 8);
	} else {
		ivec = -1;
		pci_emul_alloc_bar(pi, 0, PCIBAR_IO, 8);
	}
	pci_lintr_request(pi, ivec);

	if (opts != NULL && !strcmp("stdio", opts) && !pci_uart_stdio) {
		pci_uart_stdio = 1;
		sc->stdio = 1;
	}

	pci_uart_reset(sc);

	return (0);
}
Пример #3
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);
}