summaryrefslogtreecommitdiffstats
path: root/device/portio_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'device/portio_uart.c')
-rw-r--r--device/portio_uart.c68
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