Cleaning up uart driver

This commit is contained in:
Imbus 2025-06-25 10:59:10 +02:00
parent 2c49f5cec3
commit f65ea0f131

View file

@ -1,42 +1,52 @@
//
// low-level driver routines for 16550a UART.
//
#include "types.h" #include "types.h"
#include "param.h"
#include "memlayout.h" #include "memlayout.h"
#include "riscv.h"
#include "spinlock.h" #include "spinlock.h"
#include "proc.h"
#include "defs.h" #include "defs.h"
// the UART control registers are memory-mapped // the UART control registers are memory-mapped
// at address UART0. this macro returns the // at address UART0. this macro returns the
// address of one of the registers. // 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_RX_ENABLE (1 << 0)
#define IER_TX_ENABLE (1 << 1) #define IER_TX_ENABLE (1 << 1)
#define FCR 2 // FIFO control register
#define FCR_FIFO_ENABLE (1 << 0) #define FCR_FIFO_ENABLE (1 << 0)
#define FCR_FIFO_CLEAR (3 << 1) // clear the content of the two FIFOs #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_EIGHT_BITS (3 << 0)
#define LCR_BAUD_LATCH (1 << 7) // special mode to set baud rate #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_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 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. // the transmit output buffer.
struct spinlock uart_tx_lock; struct spinlock uart_tx_lock;
@ -52,17 +62,17 @@ void uartstart();
void void
uartinit(void) uartinit(void)
{ {
// disable interrupts. // WriteReg(IER, 0x00);
WriteReg(IER, 0x00); UART->ier_dlm = 0x00; // disable interrupts.
// special mode to set baud rate. UART->lcr = LCR_BAUD_LATCH; // special mode to set baud rate.
WriteReg(LCR, LCR_BAUD_LATCH); // WriteReg(LCR, LCR_BAUD_LATCH);
// LSB for baud rate of 38.4K. // LSB for baud rate of 38.4K.
WriteReg(0, 0x03); WriteReg(DLL, 0x03);
// MSB for baud rate of 38.4K. // MSB for baud rate of 38.4K.
WriteReg(1, 0x00); WriteReg(DLL, 0x00);
// leave set-baud mode, // leave set-baud mode,
// and set word length to 8 bits, no parity. // and set word length to 8 bits, no parity.