From f65ea0f131a6454c2458558ccf27b5b3881d1b3a Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Wed, 25 Jun 2025 10:59:10 +0200 Subject: [PATCH] Cleaning up uart driver --- kernel/uart.c | 64 +++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/kernel/uart.c b/kernel/uart.c index 370472e..3f46d45 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -1,42 +1,52 @@ -// -// low-level driver routines for 16550a UART. -// - #include "types.h" -#include "param.h" #include "memlayout.h" -#include "riscv.h" #include "spinlock.h" -#include "proc.h" #include "defs.h" // the UART control registers are memory-mapped // at address UART0. this macro returns the // address of one of the registers. -#define Reg(reg) ((volatile unsigned char *)(UART0 + reg)) -// the UART control registers. -// some have different meanings for -// read vs write. -// see http://byterunner.com/16550.html -#define RHR 0 // receive holding register (for input bytes) -#define THR 0 // transmit holding register (for output bytes) -#define IER 1 // interrupt enable register #define IER_RX_ENABLE (1 << 0) #define IER_TX_ENABLE (1 << 1) -#define FCR 2 // FIFO control register #define FCR_FIFO_ENABLE (1 << 0) #define FCR_FIFO_CLEAR (3 << 1) // clear the content of the two FIFOs -#define ISR 2 // interrupt status register -#define LCR 3 // line control register #define LCR_EIGHT_BITS (3 << 0) #define LCR_BAUD_LATCH (1 << 7) // special mode to set baud rate -#define LSR 5 // line status register #define LSR_RX_READY (1 << 0) // input is waiting to be read from RHR #define LSR_TX_IDLE (1 << 5) // THR can accept another character to send -#define ReadReg(reg) (*(Reg(reg))) -#define WriteReg(reg, v) (*(Reg(reg)) = (v)) +/* + * Keep in mind that some of these registers share locations, but have different + * meaning depending on direction + */ +typedef struct { + volatile u8 rbr_thr_dll; // 0x00: RBR (read), THR (write), DLL (when DLAB=1) + volatile u8 ier_dlm; // 0x01: IER (when DLAB=0), DLM (when DLAB=1) + volatile u8 iir_fcr; // 0x02: Interrupt Identification Register (read), FIFO Control Register (write) + volatile u8 lcr; // 0x03: Line Control Register + volatile u8 mcr; // 0x04: Modem Control Register + volatile u8 lsr; // 0x05: Line Status Register + volatile u8 msr; // 0x06: Modem Status Register + volatile u8 scr; // 0x07: Scratch Register +} uart16550_t; + +#define UART ((uart16550_t *)UART0) + +#define THR rbr_thr_dll +#define RBR rbr_thr_dll +#define DLL rbr_thr_dll +#define IER ier_dlm +#define DLM ier_dlm +#define FCR iir_fcr +#define IIR iir_fcr +#define LCR lcr +#define LSR lsr +#define RHR THR + +// TODO: Remove these +#define ReadReg(reg) ((UART)->reg) +#define WriteReg(reg, v) ((UART)->reg = (v)) // the transmit output buffer. struct spinlock uart_tx_lock; @@ -52,17 +62,17 @@ void uartstart(); void uartinit(void) { - // disable interrupts. - WriteReg(IER, 0x00); + // WriteReg(IER, 0x00); + UART->ier_dlm = 0x00; // disable interrupts. - // special mode to set baud rate. - WriteReg(LCR, LCR_BAUD_LATCH); + UART->lcr = LCR_BAUD_LATCH; // special mode to set baud rate. + // WriteReg(LCR, LCR_BAUD_LATCH); // LSB for baud rate of 38.4K. - WriteReg(0, 0x03); + WriteReg(DLL, 0x03); // MSB for baud rate of 38.4K. - WriteReg(1, 0x00); + WriteReg(DLL, 0x00); // leave set-baud mode, // and set word length to 8 bits, no parity.