summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/serial_com.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-09-04 11:31:40 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-09-04 11:31:40 -0400
commit8251da342161767fe203627223ccd4a7026701c6 (patch)
treeaf2db0f11b0ea8ad35f88663a855bab39a80f679 /arch/x86_64/hal/serial_com.c
downloadjove-kernel-8251da342161767fe203627223ccd4a7026701c6.tar.gz
jove-kernel-8251da342161767fe203627223ccd4a7026701c6.tar.bz2
jove-kernel-8251da342161767fe203627223ccd4a7026701c6.zip
initial commit. working on tasking
Diffstat (limited to 'arch/x86_64/hal/serial_com.c')
-rw-r--r--arch/x86_64/hal/serial_com.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/arch/x86_64/hal/serial_com.c b/arch/x86_64/hal/serial_com.c
new file mode 100644
index 0000000..3967cd7
--- /dev/null
+++ b/arch/x86_64/hal/serial_com.c
@@ -0,0 +1,92 @@
+#include "serial_com.h"
+#include "port.h"
+#include "jove.h"
+#include "hal/obj.h"
+#include "init.h"
+#include "lib/printf.h"
+
+static int
+serial_com_recv(uint16_t port)
+{
+ return inb(SERIAL_COM_LSR(port)) & 1;
+}
+
+static char
+serial_com_getc(uint16_t port)
+{
+ while(serial_com_recv(port) == 0);
+ return inb(port);
+}
+
+static int
+serial_com_put_ready(uint16_t port)
+{
+ return inb(SERIAL_COM_LSR(port)) & 0x20;
+}
+
+static void
+serial_com_putc(uint16_t port, char c)
+{
+ while(serial_com_put_ready(port) == 0);
+ outb(port, c);
+}
+
+int
+serial_com_init_port(
+ uint16_t port,
+ uint16_t baud_divisor)
+{
+ uint8_t div_low = (uint8_t)baud_divisor;
+ uint8_t div_high = (uint8_t)(baud_divisor >> 8);
+
+ outb(SERIAL_COM_IER(port), 0x00); // Disable all interrupts
+ outb(SERIAL_COM_LCR(port), 0x80); // Enable DLAB mode.
+ outb(SERIAL_COM_DLAB_BAUD_LO(port), div_low);
+ outb(SERIAL_COM_DLAB_BAUD_HI(port), div_high);
+ outb(SERIAL_COM_LCR(port), 0x03); // 8 bits, no parity, one stop bit.
+ outb(SERIAL_COM_FIFO(port), 0xC7); // Enable FIFO, clear them, 14 byte threshold.
+ outb(SERIAL_COM_MCR(port), 0x0B); // Enable IRQs, set RTS/DSR.
+
+ //Test to check if the serial port actually works.
+ outb(SERIAL_COM_MCR(port), 0x1E); // Set loopback mode.
+ outb(port, 0xAE); // Send test byte.
+ if(inb(port) != 0xAE) {
+ return 1;
+ }
+
+ //Set the port to normal operation mode.
+ //(no loopback, IRQs enabled, OUT#1 and OUT#2 enabled.)
+ outb(SERIAL_COM_MCR(port), 0x0F);
+ return 0;
+}
+
+void
+serial_com_init(void)
+{
+ if(serial_com_init_port(SERIAL_COM1, 3)) {
+ hcf();
+ }
+
+ {
+ jove_owned_obj_t *com_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_SERIAL_COM_I));
+ obj_settype(com_obj, JOVE_OBJ_SERIAL_COM);
+ obj_setvalue(com_obj, SERIAL_COM1);
+ obj_release(com_obj);
+ }
+
+ kprintf("Initialized COM1 on port %X for obj %X\n", SERIAL_COM1, ROOTDIR_SERIAL_COM_I);
+}
+
+int
+serial_com_write(
+ jove_owned_obj_t *obj,
+ const char *s, size_t len)
+{
+ if(obj->type != JOVE_OBJ_SERIAL_COM) {
+ reterr(EBADOBJ);
+ }
+ for(size_t i = 0; i < len; i++) {
+ serial_com_putc((uint16_t)obj->value, s[i]);
+ }
+ return len;
+}