#include #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); } }