diff --git a/kernel/console.c b/kernel/console.c index 6fb79cd..87a83ff 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -192,6 +192,8 @@ consoleinit(void) uartinit(); - devsw[CONSOLE].write = consolewrite; + // connect read and write system calls + // to consoleread and consolewrite. devsw[CONSOLE].read = consoleread; + devsw[CONSOLE].write = consolewrite; } diff --git a/kernel/uart.c b/kernel/uart.c index ba66237..852a085 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -1,3 +1,7 @@ +// +// low-level driver routines for 16550a UART. +// + #include "types.h" #include "param.h" #include "memlayout.h" @@ -6,41 +10,49 @@ #include "proc.h" #include "defs.h" -// -// qemu -machine virt has a 16550a UART -// qemu/hw/riscv/virt.c -// http://byterunner.com/16550.html -// -// caller should lock. -// +// 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)) -// address of one of the registers -#define R(reg) ((volatile unsigned char *)(UART0 + reg)) +// the registers. some have different meanings for +// read and write. +// 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 FCR 2 // FIFO control register +#define ISR 2 // interrupt status register +#define LCR 3 // line control register +#define LSR 5 // line status register + +#define ReadReg(reg) (*(Reg(reg))) +#define WriteReg(reg, v) (*(Reg(reg)) = (v)) void uartinit(void) { - // disable interrupts -- IER - *R(1) = 0x00; + // disable interrupts. + WriteReg(IER, 0x00); - // special mode to set baud rate - *R(3) = 0x80; + // special mode to set baud rate. + WriteReg(LCR, 0x80); - // LSB for baud rate of 38.4K - *R(0) = 0x03; + // LSB for baud rate of 38.4K. + WriteReg(0, 0x03); - // MSB for baud rate of 38.4K - *R(1) = 0x00; + // MSB for baud rate of 38.4K. + WriteReg(1, 0x00); // leave set-baud mode, // and set word length to 8 bits, no parity. - *R(3) = 0x03; + WriteReg(LCR, 0x03); - // reset and enable FIFOs -- FCR. - *R(2) = 0x07; + // reset and enable FIFOs. + WriteReg(FCR, 0x07); - // enable receive interrupts -- IER. - *R(1) = 0x01; + // enable receive interrupts. + WriteReg(IER, 0x01); } // write one output character to the UART. @@ -48,9 +60,9 @@ void uartputc(int c) { // wait for Transmit Holding Empty to be set in LSR. - while((*R(5) & (1 << 5)) == 0) + while((ReadReg(LSR) & (1 << 5)) == 0) ; - *R(0) = c; + WriteReg(THR, c); } // read one input character from the UART. @@ -58,9 +70,9 @@ uartputc(int c) int uartgetc(void) { - if(*R(5) & 0x01){ + if(ReadReg(LSR) & 0x01){ // input data is ready. - return *R(0); + return ReadReg(RHR); } else { return -1; }