X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/2236410f4582ab45ae8c384dd6eeeef5d10aab15..d1b1c8d9119229dbeed06cd252917e54a1cb77f6:/lunaix-os/hal/pci.c diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c index 9a3c581..af7a256 100644 --- a/lunaix-os/hal/pci.c +++ b/lunaix-os/hal/pci.c @@ -22,7 +22,7 @@ LOG_MODULE("PCI") static DEFINE_LLIST(pci_devices); static DECLARE_HASHTABLE(pci_devcache, 8); -static struct device* pcidev_cat; +static struct device_cat* pcidev_cat; static struct device_def pci_def; void @@ -58,13 +58,13 @@ pci_create_device(pciaddr_t loc, ptr_t pci_base, int devinfo) device->cspace_base = pci_base; device->intr_info = intr; - device_create(&device->dev, pcidev_cat, DEV_IFSYS, NULL); + device_create(&device->dev, dev_meta(pcidev_cat), DEV_IFSYS, NULL); pci_probe_msi_info(device); pci_probe_bar_info(device); llist_append(&pci_devices, &device->dev_chain); - device_register(&device->dev, &pci_def.class, "%x", loc); + register_device(&device->dev, &pci_def.class, "%x", loc); pci_def.class.variant++; return device; @@ -214,6 +214,42 @@ pci_probe_bar_info(struct pci_device* device) } } +void +pci_setup_msi(struct pci_device* device, int vector) +{ + // PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1 + + ptr_t msi_addr = pci_get_msi_base(); + u32_t msi_data = pci_config_msi_data(vector); + + pci_reg_t reg1 = pci_read_cspace(device->cspace_base, device->msi_loc); + pci_reg_t msg_ctl = reg1 >> 16; + int offset_cap64 = !!(msg_ctl & MSI_CAP_64BIT) * 4; + + pci_write_cspace(device->cspace_base, + PCI_MSI_ADDR_LO(device->msi_loc), + msi_addr); + + if (offset_cap64) { + pci_write_cspace(device->cspace_base, + PCI_MSI_ADDR_HI(device->msi_loc), + (u64_t)msi_addr >> 32); + } + + pci_write_cspace(device->cspace_base, + PCI_MSI_DATA(device->msi_loc, offset_cap64), + msi_data & 0xffff); + + if ((msg_ctl & MSI_CAP_MASK)) { + pci_write_cspace( + device->cspace_base, PCI_MSI_MASK(device->msi_loc, offset_cap64), 0); + } + + // manipulate the MSI_CTRL to allow device using MSI to request service. + reg1 = (reg1 & 0xff8fffff) | 0x10000; + pci_write_cspace(device->cspace_base, device->msi_loc, reg1); +} + void pci_probe_msi_info(struct pci_device* device) {