From c10bebb9efe366ce8bd924d345219a60cc30e18f Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 16 Aug 2025 00:52:17 -0300 Subject: [PATCH] pc_com: handle tx differently --- kernel-src/io/serial/pc_com.c | 37 ++++++----------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/kernel-src/io/serial/pc_com.c b/kernel-src/io/serial/pc_com.c index 0e487dc5..289b2207 100644 --- a/kernel-src/io/serial/pc_com.c +++ b/kernel-src/io/serial/pc_com.c @@ -61,11 +61,7 @@ typedef struct { int io_base; uacpi_resource_irq irq; - ringbuffer_t tx_ringbuffer; - spinlock_t tx_spinlock; // locked in IPL_SERIAL - ringbuffer_t rx_ringbuffer; - thread_t *handler_thread; semaphore_t rx_semaphore; @@ -102,12 +98,6 @@ static bool can_transmit(pc_com_t *pc_com) { return read_port(pc_com, PORT_LINE_STATUS) & LINE_STATUS_TX_BUFFER_EMPTY; } -static void transmit_data(pc_com_t *pc_com) { - char c; - ringbuffer_read(&pc_com->tx_ringbuffer, &c, 1); - write_port(pc_com, PORT_TX, c); -} - static void set_irqs(pc_com_t *pc_com, int irqs) { write_port(pc_com, PORT_INTERRUPT_ENABLE, irqs); } @@ -185,33 +175,20 @@ static void handler_thread(void) { static size_t write_tty(void *internal, char *str, size_t size) { pc_com_t *pc_com = internal; - long ipl = spinlock_acquire_raise_ipl(&pc_com->tx_spinlock, IPL_SERIAL); + for (int i = 0; i < size; ++i) { + while (!can_transmit(pc_com)); + write_port(pc_com, PORT_TX, str[i]); + } - size_t written = ringbuffer_write(&pc_com->tx_ringbuffer, str, size); - if (can_transmit(pc_com)) - transmit_data(pc_com); - - spinlock_release_lower_ipl(&pc_com->tx_spinlock, ipl); - - return written; + return size; } // TODO enqueue dpc and call tty_process directly from it once it is safe to be called from an interrupt context static void irq(isr_t *self, context_t *) { pc_com_t *pc_com = self->priv; - int interrupt_status = read_port(pc_com, PORT_INTERRUPT_ID) & 0x0e; - // check if there is data to be received process_data(pc_com); - - // check if there is data to be transmitted and tx buffer is empty - spinlock_acquire(&pc_com->tx_spinlock); - - if (((interrupt_status == INTERRUPT_STATUS_TX_EMPTY) || can_transmit(pc_com)) && RINGBUFFER_DATACOUNT(&pc_com->tx_ringbuffer)) - transmit_data(pc_com); - - spinlock_release(&pc_com->tx_spinlock); } static uacpi_iteration_decision set_com_resource(void *user, uacpi_resource *res) { @@ -237,12 +214,10 @@ static uacpi_iteration_decision init_com(void *, uacpi_namespace_node *node, uns pc_com_t *pc_com = alloc(sizeof(pc_com_t)); __assert(pc_com); - __assert(ringbuffer_init(&pc_com->tx_ringbuffer, 1000) == 0); __assert(ringbuffer_init(&pc_com->rx_ringbuffer, 1000) == 0); pc_com->id = pc_com_id++; SEMAPHORE_INIT(&pc_com->rx_semaphore, 0); - SPINLOCK_INIT(pc_com->tx_spinlock); // get io port and gsi uacpi_status ret = uacpi_get_current_resources(node, &res); @@ -268,7 +243,7 @@ static uacpi_iteration_decision init_com(void *, uacpi_namespace_node *node, uns set_irqs(pc_com, INTERRUPT_ENABLE_NONE); set_baud_divisor(pc_com, 3); write_port(pc_com, PORT_LINE_CONTROL, LINE_CONTROL_WORD_LENGTH_8_BITS); - set_irqs(pc_com, INTERRUPT_ENABLE_DATA_AVAILABLE | INTERRUPT_ENABLE_TX_EMPTY); + set_irqs(pc_com, INTERRUPT_ENABLE_DATA_AVAILABLE); write_port(pc_com, PORT_MODEM_CONTROL, MODEM_CONTROL_DATA_TERMINAL_READY | MODEM_CONTROL_REQUEST_TO_SEND | MODEM_CONTROL_AUX_1 | MODEM_CONTROL_AUX_2);