#include "serial.h" #include "uart.h" #include "io/log.h" static struct LogDevice s_serial_logdev = { .out = serial_out, .chain = NULL }; bool serial_supported = true; void serial_setup(void) { /* Disable interrupts. */ poutb(SERIAL_UART_COM_IER(SERIAL_UART_COM1), 0x0); /* Enable DLAB. */ poutb(SERIAL_UART_COM_LCR(SERIAL_UART_COM1), 0x80); /* Set divisor to 3 (38400 baud)*/ poutb(SERIAL_UART_COM_DLAB_DLL(SERIAL_UART_COM1), 3); poutb(SERIAL_UART_COM_DLAB_DLH(SERIAL_UART_COM1), 0); /* Set flags for LCR (8 bits, no parity, one stop)*/ poutb(SERIAL_UART_COM_LCR(SERIAL_UART_COM1), 1 | 2); /* Enable & clear FIFO, 14-byte threshold */ poutb(SERIAL_UART_COM_FCR(SERIAL_UART_COM1), 1 | 2 | 4 | 0xC0); /* Enable interrupts, set RTS/DSR. */ poutb(SERIAL_UART_COM_MCR(SERIAL_UART_COM1), 1 | 2 | 8); /* Set loopback mode for testing. */ poutb(SERIAL_UART_COM_MCR(SERIAL_UART_COM1), 2 | 4 | 8 | 0x10); /* Test serial output. */ poutb(SERIAL_UART_COM1, 0xAE); if(pinb(SERIAL_UART_COM1) != 0xAE) { serial_supported = false; return; } /* Serial is not faulty. * No loopback, enable output 1 & 2.*/ poutb(SERIAL_UART_COM_MCR(SERIAL_UART_COM1), 1 | 2 | 4 | 8); klog_newdev(&s_serial_logdev); } static ALWAYS_INLINE bool serial_transmit_empty(uint16_t com) { return pinb(SERIAL_UART_COM_LSR(com) & 0x20); } static inline void serial_outb(uint16_t com, uint8_t b) { if(b == '\n') serial_outb(com, '\r'); while(!serial_transmit_empty(SERIAL_UART_COM1)); poutb(com, b); } void serial_out(const char *s, size_t len) { if(!serial_supported) return; for(; len > 0; len--) serial_outb(SERIAL_UART_COM1, *(s++)); }