From be9e35bafa5f13f4b26a1d965c3db4b59f4957f8 Mon Sep 17 00:00:00 2001 From: Zihao Yu Date: Sun, 13 Oct 2019 21:15:37 +0800 Subject: [PATCH] device,serial: add registers to keep compatible to 16550 --- src/device/serial.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/device/serial.c b/src/device/serial.c index 5bf249db..dc37ace5 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -2,16 +2,21 @@ #include "device/map.h" /* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */ +// NOTE: this is compatible to 16550 #define SERIAL_PORT 0x3F8 #define SERIAL_MMIO 0xa10003F8 + #define CH_OFFSET 0 +#define LSR_OFFSET 5 +#define LSR_TX_READY 0x20 +#define LSR_RX_READY 0x01 #define QUEUE_SIZE 1024 static char queue[QUEUE_SIZE] = {}; static int f = 0, r = 0; -static uint8_t *serial_ch_base = NULL; +static uint8_t *serial_base = NULL; static void serial_enqueue(char ch) { int next = (r + 1) % QUEUE_SIZE; @@ -22,21 +27,26 @@ static void serial_enqueue(char ch) { } } -static void serial_ch_io_handler(uint32_t offset, int len, bool is_write) { - assert(offset == 0); - assert(len == 1); +static char serial_dequeue() { + char ch = 0xff; + if (f != r) { + ch = queue[f]; + f = (f + 1) % QUEUE_SIZE; + } + return ch; +} - if (is_write) { - char c = serial_ch_base[0]; +static void serial_io_handler(uint32_t offset, int len, bool is_write) { + assert(len == 1); + switch (offset) { /* We bind the serial port with the host stdout in NEMU. */ - putc(c, stderr); - } else { - if (f != r) { - serial_ch_base[0] = queue[f]; - f = (f + 1) % QUEUE_SIZE; - } else { - serial_ch_base[0] = 0xff; - } + case CH_OFFSET: + if (is_write) putc(serial_base[0], stderr); + else serial_base[0] = serial_dequeue(); + break; + case LSR_OFFSET: + if (!is_write) serial_base[5] = LSR_TX_READY | LSR_RX_READY; + break; } } @@ -49,9 +59,9 @@ static void preset_input() { } void init_serial() { - serial_ch_base = new_space(1); - add_pio_map("serial", SERIAL_PORT + CH_OFFSET, serial_ch_base, 1, serial_ch_io_handler); - add_mmio_map("serial", SERIAL_MMIO + CH_OFFSET, serial_ch_base, 1, serial_ch_io_handler); + serial_base = new_space(8); + add_pio_map("serial", SERIAL_PORT, serial_base, 8, serial_io_handler); + add_mmio_map("serial", SERIAL_MMIO, serial_base, 8, serial_io_handler); preset_input(); } -- GitLab