Changeset View
Changeset View
Standalone View
Standalone View
head/usr.sbin/bhyve/pci_emul.c
Show First 20 Lines • Show All 580 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
int | int | ||||
pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, | pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, | ||||
enum pcibar_type type, uint64_t size) | enum pcibar_type type, uint64_t size) | ||||
{ | { | ||||
int error; | int error; | ||||
uint64_t *baseptr, limit, addr, mask, lobits, bar; | uint64_t *baseptr, limit, addr, mask, lobits, bar; | ||||
uint16_t cmd, enbit; | |||||
assert(idx >= 0 && idx <= PCI_BARMAX); | assert(idx >= 0 && idx <= PCI_BARMAX); | ||||
if ((size & (size - 1)) != 0) | if ((size & (size - 1)) != 0) | ||||
size = 1UL << flsl(size); /* round up to a power of 2 */ | size = 1UL << flsl(size); /* round up to a power of 2 */ | ||||
/* Enforce minimum BAR sizes required by the PCI standard */ | /* Enforce minimum BAR sizes required by the PCI standard */ | ||||
if (type == PCIBAR_IO) { | if (type == PCIBAR_IO) { | ||||
if (size < 4) | if (size < 4) | ||||
size = 4; | size = 4; | ||||
} else { | } else { | ||||
if (size < 16) | if (size < 16) | ||||
size = 16; | size = 16; | ||||
} | } | ||||
switch (type) { | switch (type) { | ||||
case PCIBAR_NONE: | case PCIBAR_NONE: | ||||
baseptr = NULL; | baseptr = NULL; | ||||
addr = mask = lobits = 0; | addr = mask = lobits = enbit = 0; | ||||
break; | break; | ||||
case PCIBAR_IO: | case PCIBAR_IO: | ||||
baseptr = &pci_emul_iobase; | baseptr = &pci_emul_iobase; | ||||
limit = PCI_EMUL_IOLIMIT; | limit = PCI_EMUL_IOLIMIT; | ||||
mask = PCIM_BAR_IO_BASE; | mask = PCIM_BAR_IO_BASE; | ||||
lobits = PCIM_BAR_IO_SPACE; | lobits = PCIM_BAR_IO_SPACE; | ||||
enbit = PCIM_CMD_PORTEN; | |||||
break; | break; | ||||
case PCIBAR_MEM64: | case PCIBAR_MEM64: | ||||
/* | /* | ||||
* XXX | * XXX | ||||
* Some drivers do not work well if the 64-bit BAR is allocated | * Some drivers do not work well if the 64-bit BAR is allocated | ||||
* above 4GB. Allow for this by allocating small requests under | * above 4GB. Allow for this by allocating small requests under | ||||
* 4GB unless then allocation size is larger than some arbitrary | * 4GB unless then allocation size is larger than some arbitrary | ||||
* number (32MB currently). | * number (32MB currently). | ||||
Show All 12 Lines | if (size > 32 * 1024 * 1024) { | ||||
PCIM_BAR_MEM_PREFETCH; | PCIM_BAR_MEM_PREFETCH; | ||||
break; | break; | ||||
} else { | } else { | ||||
baseptr = &pci_emul_membase32; | baseptr = &pci_emul_membase32; | ||||
limit = PCI_EMUL_MEMLIMIT32; | limit = PCI_EMUL_MEMLIMIT32; | ||||
mask = PCIM_BAR_MEM_BASE; | mask = PCIM_BAR_MEM_BASE; | ||||
lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64; | lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64; | ||||
} | } | ||||
enbit = PCIM_CMD_MEMEN; | |||||
break; | break; | ||||
case PCIBAR_MEM32: | case PCIBAR_MEM32: | ||||
baseptr = &pci_emul_membase32; | baseptr = &pci_emul_membase32; | ||||
limit = PCI_EMUL_MEMLIMIT32; | limit = PCI_EMUL_MEMLIMIT32; | ||||
mask = PCIM_BAR_MEM_BASE; | mask = PCIM_BAR_MEM_BASE; | ||||
lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; | lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; | ||||
enbit = PCIM_CMD_MEMEN; | |||||
break; | break; | ||||
default: | default: | ||||
printf("pci_emul_alloc_base: invalid bar type %d\n", type); | printf("pci_emul_alloc_base: invalid bar type %d\n", type); | ||||
assert(0); | assert(0); | ||||
} | } | ||||
if (baseptr != NULL) { | if (baseptr != NULL) { | ||||
error = pci_emul_alloc_resource(baseptr, limit, size, &addr); | error = pci_emul_alloc_resource(baseptr, limit, size, &addr); | ||||
Show All 10 Lines | pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, | ||||
pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); | pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); | ||||
if (type == PCIBAR_MEM64) { | if (type == PCIBAR_MEM64) { | ||||
assert(idx + 1 <= PCI_BARMAX); | assert(idx + 1 <= PCI_BARMAX); | ||||
pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64; | pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64; | ||||
pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); | pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); | ||||
} | } | ||||
cmd = pci_get_cfgdata16(pdi, PCIR_COMMAND); | |||||
if ((cmd & enbit) != enbit) | |||||
pci_set_cfgdata16(pdi, PCIR_COMMAND, cmd | enbit); | |||||
register_bar(pdi, idx); | register_bar(pdi, idx); | ||||
return (0); | return (0); | ||||
} | } | ||||
#define CAP_START_OFFSET 0x40 | #define CAP_START_OFFSET 0x40 | ||||
static int | static int | ||||
pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) | pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot, | ||||
pdi->pi_lintr.ioapic_irq = 0; | pdi->pi_lintr.ioapic_irq = 0; | ||||
pdi->pi_d = pde; | pdi->pi_d = pde; | ||||
snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); | snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); | ||||
/* Disable legacy interrupts */ | /* Disable legacy interrupts */ | ||||
pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); | pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); | ||||
pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); | pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); | ||||
pci_set_cfgdata8(pdi, PCIR_COMMAND, | pci_set_cfgdata8(pdi, PCIR_COMMAND, PCIM_CMD_BUSMASTEREN); | ||||
PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); | |||||
err = (*pde->pe_init)(ctx, pdi, fi->fi_param); | err = (*pde->pe_init)(ctx, pdi, fi->fi_param); | ||||
if (err == 0) | if (err == 0) | ||||
fi->fi_devi = pdi; | fi->fi_devi = pdi; | ||||
else | else | ||||
free(pdi); | free(pdi); | ||||
return (err); | return (err); | ||||
▲ Show 20 Lines • Show All 1,348 Lines • Show Last 20 Lines |