[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:
Corey Tabaka
2012-07-02 00:27:04 -07:00
parent ece5516ce9
commit 94f3f37b4a
3 changed files with 71 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -25,6 +25,7 @@
void platform_init_interrupts(void);
void platform_init_timer(void);
void platform_init_uart(void);
#endif