diff options
Diffstat (limited to 'device/portio_uart.c')
-rw-r--r-- | device/portio_uart.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/device/portio_uart.c b/device/portio_uart.c new file mode 100644 index 0000000..00800b5 --- /dev/null +++ b/device/portio_uart.c @@ -0,0 +1,68 @@ +#ifdef ENABLE_PORTIO_UART +#include "jove.h" +#include "device/portio_uart.h" +#include "device/portio.h" + +static void +s_set_int(ioport_t dev, uint8_t enable) +{ + port_outb(PORTIO_UART_COM_IER(dev), enable); +} + +static void +s_set_baud(ioport_t dev, uint16_t baud) +{ + /* Enable DLAB */ + port_outb(PORTIO_UART_COM_LCR(dev), PORTIO_UART_COM_LCR(dev) | 0x80); + /* Write low & high. */ + port_outb(PORTIO_UART_COM_DLAB_DLL(dev), (uint8_t)(baud & 0xFF)); + port_outb(PORTIO_UART_COM_DLAB_DLH(dev), (uint8_t)((baud >> 8) & 0xFF)); + /* Disable DLAB */ + port_outb(PORTIO_UART_COM_LCR(dev), PORTIO_UART_COM_LCR(dev) & 0x7F); +} + +static void +s_set_fcr(ioport_t dev, uint8_t flg) +{ + port_outb(PORTIO_UART_COM_FCR(dev), flg); +} + +static void +s_set_lcr(ioport_t dev, uint8_t flg) +{ + port_outb(PORTIO_UART_COM_LCR(dev), flg); +} + +static void +s_set_mcr(ioport_t dev, uint8_t flg) +{ + port_outb(PORTIO_UART_COM_MCR(dev), flg); +} + +void +portio_uart_setup(void) +{ + s_set_int(PORTIO_UART_COM1, 0); + s_set_baud(PORTIO_UART_COM1, 3); + s_set_lcr(PORTIO_UART_COM1, 1 | 2); + s_set_fcr(PORTIO_UART_COM1, 1 | 2 | 4 | 0xC0); + s_set_fcr(PORTIO_UART_COM1, 1 | 2 | 8); + s_set_mcr(PORTIO_UART_COM1, 1 | 2 | 4 | 8); + + uint64_t serial_i = _initDirectory.self.data++; + _initDirectory.entries[serial_i] = (struct jove_ObjectDirectoryEntry) { + .type = KO_DEV_UART, + .data = PORTIO_UART_COM1 + }; + _initData.log_object = serial_i; +} + +void +portio_uart_write(uint64_t dev, const char *s, int n) +{ + for(int i = 0; i < n; i++) { + port_outb(dev, s[i]); + } +} + +#endif |