X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/ebb55b7e5f0b8f31328950ec383b77b208ffbb64..43487eff262637a59a4c2c0272d7c4a824af3944:/lunaix-os/hal/char/uart/16x50_pci.c diff --git a/lunaix-os/hal/char/uart/16x50_pci.c b/lunaix-os/hal/char/uart/16x50_pci.c index 880fd2d..bba016f 100644 --- a/lunaix-os/hal/char/uart/16x50_pci.c +++ b/lunaix-os/hal/char/uart/16x50_pci.c @@ -1,5 +1,4 @@ #include -#include #include #include @@ -13,52 +12,43 @@ LOG_MODULE("16x50-pci") static DEFINE_LLIST(pci_ports); + static void -uart_msi_irq_handler(const struct hart_state* hstate) +uart_msi_irq_handler(irq_t irq, const struct hart_state* hstate) { - int vector; struct uart16550* uart; - vector = hart_vector_stamp(hstate); - uart = (struct uart16550*)isrm_get_payload(hstate); + uart = irq_payload(irq, struct uart16550); assert(uart); - uart_handle_irq(vector, uart); -} - -static void -uart_intx_irq_handler(const struct hart_state* hstate) -{ - int vector = hart_vector_stamp(hstate); - uart_handle_irq_overlap(vector, &pci_ports); -} - -static int -pci16550_init(struct device_def* def) -{ - return pci_bind_definition_all(pcidev_def(def)); + uart_handle_irq(irq, uart); } static bool -pci16650_check_compat(struct pci_device_def* def, - struct pci_device* pcidev) +pci16x50_check_compat(struct pci_probe* probe) { unsigned int classid; - classid = pci_device_class(pcidev); + classid = pci_device_class(probe); return (classid & 0xffff00) == PCI_DEVICE_16x50_UART; } -static int -pci16650_binder(struct device_def* def, struct device* dev) +int +pci16x50_pci_register(struct device_def* def) +{ + return !pci_register_driver(def, pci16x50_check_compat); +} + +int +pci16x50_pci_create(struct device_def* def, morph_t* obj) { - int irq; struct pci_base_addr* bar; - struct pci_device* pcidev; + struct pci_probe* probe; struct uart16550* uart; struct serial_dev* sdev; + irq_t irq; - pcidev = PCI_DEVICE(dev); + probe = changeling_reveal(obj, pci_probe_morpher); pci_reg_t cmd = 0; @@ -67,20 +57,25 @@ pci16650_binder(struct device_def* def, struct device* dev) cmd = 0; pci_cmd_set_msi(&cmd); - bar = pci_device_bar(pcidev, i); + bar = pci_device_bar(probe, i); if (bar->size == 0) { continue; } - + if (!pci_bar_mmio_space(bar)) { +#ifdef CONFIG_PCI_PMIO pci_cmd_set_pmio(&cmd); - pci_apply_command(pcidev, cmd); + pci_apply_command(probe, cmd); uart = uart16x50_pmio_create(bar->start); - } - else { +#else + WARN("plaform configured to not support pmio access."); + continue; +#endif + } else + { pci_cmd_set_mmio(&cmd); - pci_apply_command(pcidev, cmd); + pci_apply_command(probe, cmd); uart = uart16x50_mmio_create(bar->start, bar->size); } @@ -90,36 +85,26 @@ pci16650_binder(struct device_def* def, struct device* dev) continue; } - if (pci_capability_msi(pcidev)) { - irq = isrm_ivexalloc(uart_msi_irq_handler); - isrm_set_payload(irq, __ptr(uart)); - pci_setup_msi(pcidev, irq); - } - else { - irq = pci_intr_irq(pcidev); - irq = isrm_bindirq(irq, uart_intx_irq_handler); + if (!pci_capability_msi(probe)) { + WARN("failed to fallback to legacy INTx: not supported."); + continue; } - INFO("base: 0x%x (%s), irq=%d (%s)", + sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI"); + + irq = pci_declare_msi_irq(uart_msi_irq_handler, probe); + irq_set_payload(irq, uart); + pci_assign_msi(probe, irq, NULL); + + INFO("base: 0x%x (%s), %s", bar->start, pci_bar_mmio_space(bar) ? "mmio" : "pmio", - irq, - pci_capability_msi(pcidev) ? "msi" : "intx, re-routed"); + pci_capability_msi(probe) ? "msi" : "intx, re-routed"); - uart->iv = irq; + uart->irq = irq; - sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI"); - pci_bind_instance(pcidev, sdev); + pci_bind_instance(probe, sdev->dev); } return 0; } - -static struct pci_device_def uart_pci_def = { - .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_CHAR, DEV_UART16550), - .name = "16550 UART (PCI/MMIO)", - .init = pci16550_init, - .bind = pci16650_binder }, - .test_compatibility = pci16650_check_compat -}; -EXPORT_PCI_DEVICE(uart16550_pci, &uart_pci_def, load_onboot); \ No newline at end of file