1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

simplify uart device

- HermitCore uses on uart to send log messages to qemu
- unidirectional communication => remove interrupt handler
- remove mmio support for uart
This commit is contained in:
Stefan Lankes 2017-03-05 18:48:51 +01:00
parent 815937216f
commit 890134dc82
4 changed files with 8 additions and 151 deletions

View file

@ -40,12 +40,6 @@ extern "C" {
*/
int uart_init(void);
/** @brief Initialize UART output without a device check
*
* @return Returns 0 on success
*/
int uart_early_init(char*);
/** @brief Simple string output on a serial device.
*
* If you want a new line you will have to "\\n".

View file

@ -97,40 +97,28 @@
#define UART_MCR_RTS 0x02 /* RTS complement */
#define UART_MCR_DTR 0x01 /* DTR complement */
static uint8_t mmio = 0;
static size_t iobase = 0;
static inline unsigned char read_from_uart(uint32_t off)
{
uint8_t c = 0;
if (mmio)
c = *((const volatile unsigned char*) (iobase + off));
else if (iobase)
if (iobase)
c = inportb(iobase + off);
return c;
}
static void write_to_uart(uint32_t off, unsigned char c)
static inline void write_to_uart(uint32_t off, unsigned char c)
{
if (mmio)
*((volatile unsigned char*) (iobase + off)) = c;
else if (iobase)
if (iobase)
outportb(iobase + off, c);
}
/* Get a single character on a serial device */
static unsigned char uart_getchar(void)
{
return read_from_uart(UART_RX);
}
/* Puts a single character on a serial device */
int uart_putchar(unsigned char c)
{
if (!iobase && !mmio)
if (!iobase)
return 0;
write_to_uart(UART_TX, c);
@ -143,7 +131,7 @@ int uart_puts(const char *text)
{
size_t i, len = strlen(text);
if (!iobase && !mmio)
if (!iobase)
return 0;
for (i = 0; i < len; i++)
@ -152,39 +140,6 @@ int uart_puts(const char *text)
return len;
}
/* Handles all UART's interrupt */
static void uart_handler(struct state *s)
{
unsigned char c = read_from_uart(UART_IIR);
while (!(c & UART_IIR_NO_INT)) {
if (c & UART_IIR_RDI) {
c = uart_getchar();
//TODO: handle input messages
goto out;
}
if(c & UART_IIR_THRI) {
// acknowledge interrupt
c = read_from_uart(UART_IIR);
goto out;
}
if(c & UART_IIR_RLSI) {
// acknowledge interrupt
c = read_from_uart(UART_LSR);
goto out;
}
out:
c = read_from_uart(UART_IIR);
}
}
static int uart_config(void)
{
/*
@ -226,105 +181,14 @@ static int uart_config(void)
extern const void kernel_start;
int uart_early_init(char* cmdline)
{
if (is_uhyve())
return 0;
#if 1
// default value of our QEMU configuration
iobase = 0xc110;
#else
if (BUILTIN_EXPECT(!cmdline, 0))
return -EINVAL;
char* str = strstr(cmdline, "uart=");
if (!str)
return -EINVAL;
if (strncmp(str, "uart=io:", 8) == 0) {
iobase = strtol(str+8, (char **)NULL, 16);
if (!iobase)
return -EINVAL;
mmio = 0;
} else if (strncmp(str, "uart=mmio:", 10) == 0) {
iobase = strtol(str+10, (char **)NULL, 16);
if (!iobase)
return -EINVAL;
if (iobase >= PAGE_MAP_ENTRIES*PAGE_SIZE) {
/* at this point we use the boot page table
* => IO address is not mapped
* => dirty hack, map device before the kernel
*/
int err;
size_t newaddr = ((size_t) &kernel_start - PAGE_SIZE);
err = page_map_bootmap(newaddr & PAGE_MASK, iobase & PAGE_MASK, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
if (BUILTIN_EXPECT(err, 0)) {
iobase = 0;
return err;
}
iobase = newaddr;
}
mmio = 1;
}
#endif
// configure uart
return uart_config();
}
int uart_init(void)
{
if (is_uhyve())
return 0;
#ifdef CONFIG_PCI
pci_info_t pci_info;
uint32_t bar = 0;
// Searching for Intel's UART device
if (pci_get_device_info(0x8086, 0x0936, iobase, &pci_info) == 0)
goto Lsuccess;
// Searching for Qemu's UART device
if (pci_get_device_info(0x1b36, 0x0002, iobase, &pci_info) == 0)
goto Lsuccess;
// Searching for Qemu's 2x UART device (pci-serial-2x)
if (pci_get_device_info(0x1b36, 0x0003, iobase, &pci_info) == 0)
goto Lsuccess;
// Searching for Qemu's 4x UART device (pci-serial-4x)
if (pci_get_device_info(0x1b36, 0x0004, iobase, &pci_info) == 0)
goto Lsuccess;
return -1;
Lsuccess:
iobase = pci_info.base[bar];
irq_install_handler(32+pci_info.irq, uart_handler);
if (pci_info.type[0]) {
mmio = 0;
LOG_INFO("UART uses io address 0x%x\n", iobase);
} else {
mmio = 1;
page_map(iobase & PAGE_MASK, iobase & PAGE_MASK, 1, PG_GLOBAL | PG_ACCESSED | PG_DIRTY | PG_RW | PG_PCD);
LOG_INFO("UART uses mmio address 0x%x\n", iobase);
vma_add(iobase, iobase + PAGE_SIZE, VMA_READ|VMA_WRITE);
}
// default value of our QEMU configuration
iobase = 0xc110;
// configure uart
return uart_config();
#else
// per default we use COM1...
if (!iobase)
iobase = 0x3F8;
mmio = 0;
if ((iobase == 0x3F8) || (iobase == 0x3E8))
irq_install_handler(32+4, uart_handler);
else if ((iobase == 0x2F8) || (iobase == 0x2E8))
irq_install_handler(32+3, uart_handler);
else
return -EINVAL;
// configure uart
return uart_config();
#endif
}

View file

@ -132,7 +132,6 @@ static int hermit_init(void)
multitasking_init();
memory_init();
signal_init();
uart_init();
return 0;
}

View file

@ -45,7 +45,7 @@ spinlock_irqsave_t stdio_lock = SPINLOCK_IRQSAVE_INIT;
int koutput_init(void)
{
if (is_single_kernel())
uart_early_init(NULL);
uart_init();
return 0;
}