89 lines
2.0 KiB
C
89 lines
2.0 KiB
C
|
|
/*
|
|
Driver for serial output.
|
|
Mostly useful for debug output because QEMU allows the redirection of serial output to either stdio or a file on the host computer.
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <port_io.h>
|
|
#include <string.h>
|
|
|
|
#include <drivers/serio.h>
|
|
|
|
|
|
#define COM1_IO_ADDR 0x3F8
|
|
#define COM2_IO_ADDR 0x2F8
|
|
|
|
#define COM1_IRQ 0x4
|
|
#define COM2_IRQ 0x3
|
|
|
|
#define COM1_LCR (COM1_IO_ADDR + 3)
|
|
#define COM2_LCR (COM2_IO_ADDR + 3)
|
|
|
|
#define BAUD 57600
|
|
#define DIVISOR 2
|
|
|
|
|
|
int serial_init(void)
|
|
{
|
|
/* The following is taken from https://wiki.osdev.org/Serial_Ports */
|
|
|
|
outb(COM1_IO_ADDR + 1, 0x00); // Disable all interrupts
|
|
outb(COM1_IO_ADDR + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
|
outb(COM1_IO_ADDR + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
|
outb(COM1_IO_ADDR + 1, 0x00); // (hi byte)
|
|
outb(COM1_IO_ADDR + 3, 0x03); // 8 bits, no parity, one stop bit
|
|
outb(COM1_IO_ADDR + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
|
outb(COM1_IO_ADDR + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
|
outb(COM1_IO_ADDR + 4, 0x1E); // Set in loopback mode, test the serial chip
|
|
outb(COM1_IO_ADDR + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
|
|
|
// Check if serial is faulty (i.e: not same byte as sent)
|
|
if(inb(COM1_IO_ADDR + 0) != 0xAE)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// If serial is not faulty set it in normal operation mode
|
|
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
|
outb(COM1_IO_ADDR + 4, 0x0F);
|
|
return 0;
|
|
}
|
|
|
|
static int is_transmit_empty(void)
|
|
{
|
|
return inb(COM1_IO_ADDR + 5) & 0x20;
|
|
}
|
|
|
|
static int serial_received(void)
|
|
{
|
|
return inb(COM1_IO_ADDR + 5) & 1;
|
|
}
|
|
|
|
void serial_write(char a)
|
|
{
|
|
while (is_transmit_empty() == 0);
|
|
|
|
outb(COM1_IO_ADDR, a);
|
|
}
|
|
|
|
void serial_puts(const char* s)
|
|
{
|
|
for (int i = 0; i < (int) strlen(s); i++)
|
|
{
|
|
serial_write(s[i]);
|
|
}
|
|
}
|
|
|
|
char serial_read(void)
|
|
{
|
|
while (serial_received() == 0);
|
|
|
|
return inb(COM1_IO_ADDR);
|
|
}
|
|
|
|
bool use_serial(void)
|
|
{
|
|
return true;
|
|
}
|