+size_t
+pci_bar_sizing(struct pci_device* dev, uint32_t* bar_out, uint32_t bar_num)
+{
+ pci_reg_t bar = pci_read_cspace(dev->cspace_base, PCI_REG_BAR(bar_num));
+ if (!bar) {
+ *bar_out = 0;
+ return 0;
+ }
+
+ pci_write_cspace(dev->cspace_base, PCI_REG_BAR(bar_num), 0xffffffff);
+ pci_reg_t sized =
+ pci_read_cspace(dev->cspace_base, PCI_REG_BAR(bar_num)) & ~0x1;
+ if (PCI_BAR_MMIO(bar)) {
+ sized = PCI_BAR_ADDR_MM(sized);
+ }
+ *bar_out = bar;
+ pci_write_cspace(dev->cspace_base, PCI_REG_BAR(bar_num), bar);
+ return ~sized + 1;
+}
+
+void
+pci_setup_msi(struct pci_device* device, int vector)
+{
+ // Dest: APIC#0, Physical Destination, No redirection
+ uint32_t msi_addr = (__APIC_BASE_PADDR);
+
+ // Edge trigger, Fixed delivery
+ uint32_t msi_data = vector;
+
+ pci_write_cspace(
+ device->cspace_base, PCI_MSI_ADDR(device->msi_loc), msi_addr);
+ pci_write_cspace(
+ device->cspace_base, PCI_MSI_DATA(device->msi_loc), msi_data & 0xffff);
+
+ pci_reg_t reg1 = pci_read_cspace(device->cspace_base, device->msi_loc);
+
+ // manipulate the MSI_CTRL to allow device using MSI to request service.
+ reg1 = ((((reg1 >> 16) & ~0x70) | 0x1) << 16) | (reg1 & 0xffff);
+ pci_write_cspace(device->cspace_base, device->msi_loc, reg1);
+}
+