diff options
| author | Jon Santmyer <jon@jonsantmyer.com> | 2026-09-04 11:31:40 -0400 |
|---|---|---|
| committer | Jon Santmyer <jon@jonsantmyer.com> | 2026-09-04 11:31:40 -0400 |
| commit | 8251da342161767fe203627223ccd4a7026701c6 (patch) | |
| tree | af2db0f11b0ea8ad35f88663a855bab39a80f679 /arch/x86_64/hal/serial_com.c | |
| download | jove-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.c | 92 |
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; +} |
