[platform][pc] Add basic UART support and connect the console to it.
This is especially useful when using the "nographic" option of qemu like this: qemu -kernel build-pc-x86/lk.bin -nographic Define WITH_CGA_CONSOLE=1 to enable the CGA console instead.
This commit is contained in:
@@ -25,21 +25,86 @@
|
||||
#include <printf.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/x86.h>
|
||||
#include <lib/cbuf.h>
|
||||
#include <platform/interrupts.h>
|
||||
#include <platform/pc/memmap.h>
|
||||
#include <platform/console.h>
|
||||
#include <platform/keyboard.h>
|
||||
#include <platform/debug.h>
|
||||
|
||||
static int uart_baud_rate = 115200;
|
||||
static int uart_io_port = 0x3f8;
|
||||
|
||||
static cbuf_t uart_rx_buf;
|
||||
|
||||
static enum handler_return uart_irq_handler(void *arg)
|
||||
{
|
||||
unsigned char c;
|
||||
bool resched = false;
|
||||
|
||||
while (inp(uart_io_port + 5) & (1<<0)) {
|
||||
c = inp(uart_io_port + 0);
|
||||
cbuf_write(&uart_rx_buf, &c, 1, false);
|
||||
resched = true;
|
||||
}
|
||||
|
||||
return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
|
||||
}
|
||||
|
||||
void platform_init_uart(void)
|
||||
{
|
||||
/* configure the uart */
|
||||
int divisor = 115200 / uart_baud_rate;
|
||||
|
||||
/* get basic config done so that tx functions */
|
||||
outp(uart_io_port + 3, 0x80); // set up to load divisor latch
|
||||
outp(uart_io_port + 0, divisor & 0xff); // lsb
|
||||
outp(uart_io_port + 1, divisor >> 8); // msb
|
||||
outp(uart_io_port + 3, 3); // 8N1
|
||||
outp(uart_io_port + 2, 0x07); // enable FIFO, clear, 14-byte threshold
|
||||
}
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
/* finish uart init to get rx going */
|
||||
cbuf_initialize(&uart_rx_buf, 16);
|
||||
|
||||
register_int_handler(0x24, uart_irq_handler, NULL);
|
||||
unmask_interrupt(0x24);
|
||||
|
||||
outp(uart_io_port + 1, 0x1); // enable receive data available interrupt
|
||||
}
|
||||
|
||||
void uart_putc(char c)
|
||||
{
|
||||
while ((inp(uart_io_port + 5) & (1<<6)) == 0)
|
||||
;
|
||||
outp(uart_io_port + 0, c);
|
||||
}
|
||||
|
||||
int uart_getc(char *c, bool wait)
|
||||
{
|
||||
return cbuf_read(&uart_rx_buf, c, 1, wait);
|
||||
}
|
||||
|
||||
void _dputc(char c)
|
||||
{
|
||||
#if WITH_CGA_CONSOLE
|
||||
cputc(c);
|
||||
#else
|
||||
uart_putc(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
int dgetc(char *c, bool wait)
|
||||
{
|
||||
#if WITH_CGA_CONSOLE
|
||||
int ret = platform_read_key(c);
|
||||
//if (ret < 0)
|
||||
// arch_idle();
|
||||
#else
|
||||
int ret = uart_getc(c, wait);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <platform/console.h>
|
||||
#include <platform/keyboard.h>
|
||||
#include <dev/pci.h>
|
||||
#include <dev/uart.h>
|
||||
|
||||
extern multiboot_info_t *_multiboot_info;
|
||||
extern unsigned int _heap_end;
|
||||
@@ -75,6 +76,8 @@ void platform_init_multiboot_info(void)
|
||||
|
||||
void platform_early_init(void)
|
||||
{
|
||||
platform_init_uart();
|
||||
|
||||
/* update the heap end so we can take advantage of more ram */
|
||||
platform_init_multiboot_info();
|
||||
|
||||
@@ -90,6 +93,8 @@ void platform_early_init(void)
|
||||
|
||||
void platform_init(void)
|
||||
{
|
||||
uart_init();
|
||||
|
||||
platform_init_keyboard();
|
||||
|
||||
pci_init();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
void platform_init_interrupts(void);
|
||||
void platform_init_timer(void);
|
||||
void platform_init_uart(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user