Procházet zdrojové kódy

feat: serial port read and write

greatbridf před 2 roky
rodič
revize
177ff70411
6 změnil soubory, kde provedl 83 přidání a 2 odebrání
  1. 2 0
      CMakeLists.txt
  2. 3 0
      Makefile
  3. 4 2
      include/asm/port_io.h
  4. 13 0
      include/kernel/hw/serial.h
  5. 52 0
      src/kernel/hw/serial.c
  6. 9 0
      src/kernel_main.c

+ 2 - 0
CMakeLists.txt

@@ -46,6 +46,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/mem.c
                         src/kernel/vga.c
                         src/kernel/hw/keyboard.cpp
+                        src/kernel/hw/serial.c
                         src/kernel/hw/timer.c
                         src/kernel/event/event.cpp
                         src/types/buffer.c
@@ -59,6 +60,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/mem.h
                         include/kernel/vga.h
                         include/kernel/hw/keyboard.h
+                        include/kernel/hw/serial.h
                         include/kernel/hw/timer.h
                         include/kernel/input/keycodes.h
                         include/kernel/input/input_event.h

+ 3 - 0
Makefile

@@ -1,6 +1,9 @@
 .PHONY: run
 run: build
 	qemu-system-i386 -drive file=build/boot.img,format=raw -display curses -no-reboot -no-shutdown -S -s -enable-kvm
+.PHONY: srun
+srun: build
+	qemu-system-i386 -drive file=build/boot.img,format=raw -display none -no-reboot -no-shutdown -S -s -enable-kvm -serial mon:stdio
 
 .PHONY: build
 build:

+ 4 - 2
include/asm/port_io.h

@@ -2,6 +2,8 @@
 
 #include <types/types.h>
 
+typedef uint16_t port_id_t;
+
 #define PORT_PIC1 (0x20)
 #define PORT_PIC2 (0xa0)
 #define PORT_PIC1_COMMAND (PORT_PIC1)
@@ -21,8 +23,8 @@
 extern "C" {
 #endif
 
-extern void asm_outb(uint16_t port_number, uint8_t data);
-extern uint8_t asm_inb(uint16_t port_number);
+extern void asm_outb(port_id_t port_number, uint8_t data);
+extern uint8_t asm_inb(port_id_t port_number);
 
 extern void asm_hlt(void);
 extern void asm_cli(void);

+ 13 - 0
include/kernel/hw/serial.h

@@ -0,0 +1,13 @@
+#pragma once
+#include <asm/port_io.h>
+
+#define PORT_SERIAL0 (0x3f8)
+#define PORT_SERIAL1 (0x2f8)
+
+int32_t init_serial_port(port_id_t port);
+
+int32_t is_serial_has_data(port_id_t port);
+uint8_t serial_read_data(port_id_t port);
+
+int32_t is_serial_ready_for_transmition(port_id_t port);
+void serial_send_data(port_id_t port, uint8_t data);

+ 52 - 0
src/kernel/hw/serial.c

@@ -0,0 +1,52 @@
+#include <kernel/hw/serial.h>
+#include <asm/port_io.h>
+
+int32_t init_serial_port(port_id_t port)
+{
+    // taken from osdev.org
+
+   asm_outb(port + 1, 0x00);    // Disable all interrupts
+   asm_outb(port + 3, 0x80);    // Enable DLAB (set baud rate divisor)
+   // TODO: set baud rate
+   asm_outb(port + 0, 0x00);    // Set divisor to 0 -3- (lo byte) 115200 -38400- baud
+   asm_outb(port + 1, 0x00);    //                  (hi byte)
+   asm_outb(port + 3, 0x03);    // 8 bits, no parity, one stop bit
+   asm_outb(port + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
+   asm_outb(port + 4, 0x0B);    // IRQs enabled, RTS/DSR set
+   asm_outb(port + 4, 0x1E);    // Set in loopback mode, test the serial chip
+   asm_outb(port + 0, 0xAE);    // Test serial chip (send byte 0xAE and check if serial returns same byte)
+
+   // Check if serial is faulty (i.e: not same byte as sent)
+   if(asm_inb(port + 0) != 0xAE) {
+      return 1;
+   }
+
+   // If serial is not faulty set it in normal operation mode
+   // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+   asm_outb(port + 4, 0x0F);
+   return 0;
+}
+
+int32_t is_serial_has_data(port_id_t port)
+{
+    return asm_inb(port + 5) & 1;
+}
+
+uint8_t serial_read_data(port_id_t port)
+{
+    while (is_serial_has_data(port) == 0)
+        ;
+    return asm_inb(port);
+}
+
+int32_t is_serial_ready_for_transmition(port_id_t port)
+{
+    return asm_inb(port + 5) & 0x20;
+}
+
+void serial_send_data(port_id_t port, uint8_t data)
+{
+    while (is_serial_ready_for_transmition(port) == 0)
+        ;
+    return asm_outb(port, data);
+}

+ 9 - 0
src/kernel_main.c

@@ -4,6 +4,7 @@
 #include <asm/port_io.h>
 #include <kernel/event/event.h>
 #include <kernel/hw/keyboard.h>
+#include <kernel/hw/serial.h>
 #include <kernel/hw/timer.h>
 #include <kernel/interrupt.h>
 #include <kernel/mem.h>
@@ -113,6 +114,14 @@ void kernel_main(void)
     vga_printk(k_malloc_buf, 0x0fu);
     k_free(k_malloc_buf);
 
+    printkf("initializing serial ports... ");
+    int result = init_serial_port(PORT_SERIAL0);
+    if (result == 0) {
+        printkf("ok\n");
+    } else {
+        printkf("failed\n");
+    }
+
     void* kernel_stack = k_malloc(KERNEL_STACK_SIZE);
     init_gdt_with_tss(kernel_stack + KERNEL_STACK_SIZE - 1, KERNEL_STACK_SEGMENT);
     printkf("new GDT and TSS loaded\n");