diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/amd64/serial.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/arch/amd64/serial.c b/src/arch/amd64/serial.c new file mode 100644 index 0000000..685da7f --- /dev/null +++ b/src/arch/amd64/serial.c @@ -0,0 +1,58 @@ +#include <serial.h> +#include "bindings.h" + +// port numbers for first four serial ports +static uint16_t SERIAL_PORTS[] = { + [COM1] = 0x3F8, + [COM2] = 0x2F8, + [COM3] = 0x3E8, + [COM4] = 0x2E8, +}; + +// initialize the specified COM port for serial +// see https://wiki.osdev.org/Serial_Ports +// and https://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming +int serial_init(enum serial_com_port com) { + uint16_t port = SERIAL_PORTS[com]; + outb(port + 1, 0x00); // disable interrupts + outb(port + 3, 0x80); // enable DLAB (divisor latch access bit) + outb(port + 0, 0x03); // (lo) Set baud divisor to 3 38400 baud + outb(port + 1, 0x00); // (hi) + outb(port + 3, 0x03); // disable DLAB, set 8 bits per word, one stop bit, no parity + outb(port + 2, 0xC7); // enable and clear FIFOs, set to maximum threshold + // outb(port + 4, 0x0B); // TODO copied this from osdev wiki but i don't think you need it here + outb(port + 4, 0x1E); // set in loopback mode for test + outb(port + 0, 0xAE); // test by sending 0xAE + + uint8_t response = inb(port + 0); + if(response != 0xAE) { + // TODO panic here? + return -1; + } + + // disable loopback, enable IRQs + outb(port + 4, 0x0F); + return 0; +} + +uint8_t serial_in(enum serial_com_port com) { + uint16_t port = SERIAL_PORTS[com]; + // wait for data to be available + while((inb(port + 5) & 0x01) == 0); + return inb(port); +} + +void serial_out(enum serial_com_port com, uint8_t ch) { + uint16_t port = SERIAL_PORTS[com]; + // wait for output to be free + while((inb(port + 5) & 0x20) == 0); + outb(port, ch); +} + +void serial_out_str(enum serial_com_port com, char *str) { + uint16_t port = SERIAL_PORTS[com]; + for(; *str != '\0'; str++) { + while((inb(port + 5) & 0x20) == 0); + outb(port, *str); + } +} |