Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions src/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ static void pci_command_bar(struct pci_dev *dev)
bool enable_mem =
PCI_HDR_READ(dev->hdr, PCI_COMMAND, 16) & PCI_COMMAND_MEMORY;
for (int i = 0; i < PCI_STD_NUM_BARS; i++) {
struct bus *bus = dev->bar_is_io_space[i] ? dev->io_bus : dev->mmio_bus;
bool enable = dev->bar_is_io_space[i] ? enable_io : enable_mem;
bool is_io = dev->bar_layout[i] & PCI_BASE_ADDRESS_SPACE_IO;
struct bus *bus = is_io ? dev->io_bus : dev->mmio_bus;
bool enable = is_io ? enable_io : enable_mem;

if (enable)
pci_activate_bar(dev, i, bus);
Expand All @@ -71,9 +72,9 @@ static void pci_config_bar(struct pci_dev *dev, uint8_t bar)
{
uint32_t mask = ~(dev->bar_size[bar] - 1);
uint32_t old_bar = PCI_HDR_READ(dev->hdr, PCI_BAR_OFFSET(bar), 32);
uint32_t new_bar = (old_bar & mask) | dev->bar_is_io_space[bar];
uint32_t new_bar = (old_bar & mask) | (dev->bar_layout[bar] & ~mask);
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), new_bar, 32);
dev->space_dev[bar].base = new_bar;
dev->space_dev[bar].base = new_bar & mask;
}

static void pci_config_write(struct pci_dev *dev,
Expand Down Expand Up @@ -145,14 +146,17 @@ static void pci_mmio_io(void *owner,
void pci_set_bar(struct pci_dev *dev,
uint8_t bar,
uint32_t bar_size,
bool is_io_space,
uint32_t layout,
dev_io_fn do_io)
{
/* TODO: mem type, prefetch */
/* FIXME: bar_size must be power of 2 */
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), is_io_space, 32);
/*
* FIXME: bar_size must be a power of two.
* TODO: 64-bit BARs need a second adjacent slot for the upper dword;
* only 32-bit memory and I/O BARs are wired up here.
*/
PCI_HDR_WRITE(dev->hdr, PCI_BAR_OFFSET(bar), layout, 32);
dev->bar_size[bar] = bar_size;
dev->bar_is_io_space[bar] = is_io_space;
dev->bar_layout[bar] = layout;
dev_init(&dev->space_dev[bar], 0, bar_size, dev, do_io);
}

Expand Down
9 changes: 7 additions & 2 deletions src/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct pci_dev {
void *hdr;
uint32_t bar_size[6];
bool bar_active[6];
bool bar_is_io_space[6];
uint32_t bar_layout[6];
struct dev space_dev[6];
struct dev config_dev;
struct bus *io_bus;
Expand All @@ -46,10 +46,15 @@ struct pci {
struct dev pci_mmio_dev;
};

/*
* Configure a PCI BAR. @layout is a bitmask of PCI_BASE_ADDRESS_* flags
* from <linux/pci_regs.h> (space, mem type, prefetch). The non-address
* bits are preserved across guest BAR sizing probes.
*/
void pci_set_bar(struct pci_dev *dev,
uint8_t bar,
uint32_t bar_size,
bool is_io_space,
uint32_t layout,
dev_io_fn do_io);
void pci_set_status(struct pci_dev *dev, uint16_t status);
void pci_dev_register(struct pci_dev *dev);
Expand Down
3 changes: 2 additions & 1 deletion src/virtio-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ void virtio_pci_init(struct virtio_pci_dev *dev,
PCI_HDR_WRITE(dev->pci_dev.hdr, PCI_HEADER_TYPE, PCI_HEADER_TYPE_NORMAL, 8);
PCI_HDR_WRITE(dev->pci_dev.hdr, PCI_INTERRUPT_PIN, 1, 8);
pci_set_status(&dev->pci_dev, PCI_STATUS_CAP_LIST | PCI_STATUS_INTERRUPT);
pci_set_bar(&dev->pci_dev, 0, 0x100, PCI_BASE_ADDRESS_SPACE_MEMORY,
pci_set_bar(&dev->pci_dev, 0, 0x100,
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32,
virtio_pci_space_io);
virtio_pci_set_cap(dev, cap_list);
dev->device_feature |=
Expand Down