76 lines
1.5 KiB
C
76 lines
1.5 KiB
C
#include <stdint.h>
|
|
|
|
#include "tianole/arch.h"
|
|
|
|
#define X86_QEMU_DEBUG_PORT 0xe9
|
|
|
|
#define X86_COM1_BASE 0x3f8
|
|
#define X86_COM_DATA 0
|
|
#define X86_COM_INTERRUPT_ENABLE 1
|
|
#define X86_COM_FIFO_CONTROL 2
|
|
#define X86_COM_LINE_CONTROL 3
|
|
#define X86_COM_MODEM_CONTROL 4
|
|
#define X86_COM_LINE_STATUS 5
|
|
|
|
#define X86_COM_LCR_DLAB 0x80
|
|
#define X86_COM_LCR_8N1 0x03
|
|
#define X86_COM_LSR_THRE 0x20
|
|
|
|
static inline void outb(uint16_t port, uint8_t value)
|
|
{
|
|
__asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port));
|
|
}
|
|
|
|
static inline uint8_t inb(uint16_t port)
|
|
{
|
|
uint8_t value;
|
|
|
|
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
|
|
return value;
|
|
}
|
|
|
|
static void debug_port_putc(char ch)
|
|
{
|
|
outb(X86_QEMU_DEBUG_PORT, (uint8_t)ch);
|
|
}
|
|
|
|
static void serial_putc(char ch)
|
|
{
|
|
uint32_t timeout;
|
|
|
|
for (timeout = 0; timeout < 100000; timeout++) {
|
|
if ((inb(X86_COM1_BASE + X86_COM_LINE_STATUS) &
|
|
X86_COM_LSR_THRE) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
outb(X86_COM1_BASE + X86_COM_DATA, (uint8_t)ch);
|
|
}
|
|
|
|
void arch_early_log_init(void)
|
|
{
|
|
outb(X86_COM1_BASE + X86_COM_INTERRUPT_ENABLE, 0x00);
|
|
outb(X86_COM1_BASE + X86_COM_LINE_CONTROL, X86_COM_LCR_DLAB);
|
|
outb(X86_COM1_BASE + X86_COM_DATA, 0x03);
|
|
outb(X86_COM1_BASE + X86_COM_INTERRUPT_ENABLE, 0x00);
|
|
outb(X86_COM1_BASE + X86_COM_LINE_CONTROL, X86_COM_LCR_8N1);
|
|
outb(X86_COM1_BASE + X86_COM_FIFO_CONTROL, 0xc7);
|
|
outb(X86_COM1_BASE + X86_COM_MODEM_CONTROL, 0x0b);
|
|
}
|
|
|
|
void arch_early_log_putc(char ch)
|
|
{
|
|
debug_port_putc(ch);
|
|
serial_putc(ch);
|
|
}
|
|
|
|
void arch_halt_forever(void)
|
|
{
|
|
__asm__ volatile("cli");
|
|
|
|
for (;;) {
|
|
__asm__ volatile("hlt");
|
|
}
|
|
}
|