X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/04f32c3e67120f8498cdcf7926bab88e4e405258..ebb55b7e5f0b8f31328950ec383b77b208ffbb64:/lunaix-os/hal/char/uart/16x50_isa.c diff --git a/lunaix-os/hal/char/uart/16x50_isa.c b/lunaix-os/hal/char/uart/16x50_isa.c new file mode 100644 index 0000000..d8d2e1b --- /dev/null +++ b/lunaix-os/hal/char/uart/16x50_isa.c @@ -0,0 +1,64 @@ +#include +#include +#include + +#include + +#include "16x50.h" + +LOG_MODULE("16x50-isa"); + +static DEFINE_LLIST(com_ports); + +static void +com_irq_handler(const struct hart_state* hstate) +{ + int vector = hart_vector_stamp(hstate); + uart_handle_irq_overlap(vector, &com_ports); +} + +static int +upiom_init(struct device_def* def) +{ + int irq3 = 3, irq4 = 4; + u16_t ioports[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 }; + int* irqs[] = { &irq4, &irq3, &irq4, &irq3 }; + + struct uart16550* uart = NULL; + ptr_t base; + + // COM 1...4 + for (size_t i = 0; i < 4; i++) { + + base = ioports[i]; + uart = uart16x50_pmio_create(base); + if (!uart) { + WARN("port 0x%x not accessible", base); + continue; + } + + int irq = *irqs[i]; + if (irq) { + /* + * Since these irqs are overlapped, this particular setup is needed + * to avoid double-bind + */ + uart->iv = isrm_bindirq(irq, com_irq_handler); + *((volatile int*)irqs[i]) = 0; + } + + INFO("base: 0x%x, irq=%d", + base, irq, uart->iv); + + uart_create_serial(uart, &def->class, &com_ports, "S"); + } + + return 0; +} + +static struct device_def uart_pmio_def = { + .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_UART16550), + .name = "16550 UART (PIO)", + .init = upiom_init +}; +EXPORT_DEVICE(uart16550_pmio, &uart_pmio_def, load_onboot); \ No newline at end of file