#include "uart_16550.h" #include int uart_thre(enum UART port) { return inb(port + LineStatus) & THRE; } void uart_putc(const FILE *self, char a) { while (uart_thre((enum UART)self->id) == 0) {} outb(a, self->id); if (a == '\n') { while (uart_thre((enum UART)self->id) == 0) {} outb('\r', self->id); } } int uart_puts(const FILE *self, const char *string, int length) { int written = 0; if (length == -1) while (*string != '\0') { uart_putc(self, *string); ++string; ++written; } else for (int i = 0; i < length; ++i) { uart_putc(self, string[i]); ++written; } return written; } void uart_flush(__attribute__((unused)) const FILE *self) { } FILE uart_stream; FILE * uart_init(enum UART port) { outb(0x00, port + 1); // Disable all interrupts outb(0x80, port + 3); // Enable DLAB (set baud rate divisor) outb(0x03, port + 0); // Set divisor to 3 (lo byte) 38400 baud outb(0x00, port + 1); // (hi byte) outb(0x03, port + 3); // 8 bits, no parity, one stop bit outb(0xc7, port + 2); // Enable FIFO, clear them, with 14-byte threshold outb(0x0b, port + 4); // IRQs enabled, RTS/DSR set outb(0x1e, port + 4); // Set in loopback mode, test the serial chip outb(0xae, port + 0); // 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(port + 0) != 0xae) { return NULL; } // 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(0x0f, port + 4); uart_stream.id = port; uart_stream.putc = &uart_putc; uart_stream.puts = &uart_puts; uart_stream.flush = &uart_flush; return &uart_stream; }