Browse Source

use ring_buf to save scan codes

greatbridf 4 years ago
parent
commit
1b903a6424

+ 2 - 0
CMakeLists.txt

@@ -32,6 +32,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/stdio.c
                         src/kernel/mem.c
                         src/kernel/vga.c
+                        src/kernel/hw/keyboard.c
                         src/types/buffer.c
                         include/asm/boot.h
                         include/asm/port_io.h
@@ -39,6 +40,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/stdio.h
                         include/kernel/mem.h
                         include/kernel/vga.h
+                        include/kernel/hw/keyboard.h
                         include/types/buffer.h
                         include/types/types.h
                         include/types/size.h

+ 9 - 0
include/kernel/hw/keyboard.h

@@ -0,0 +1,9 @@
+#pragma once
+
+#include <types/types.h>
+
+int32_t keyboard_has_data(void);
+
+void process_keyboard_data(void);
+
+void handle_keyboard_interrupt(void);

+ 2 - 0
include/kernel/interrupt.h

@@ -4,6 +4,8 @@
 
 #define INTERRUPT_GATE_TYPE (0x8e)
 
+#define PIC_EOI (0x20)
+
 struct regs_32 {
     uint32_t edi;
     uint32_t esi;

+ 9 - 0
include/types/buffer.h

@@ -2,6 +2,15 @@
 
 #include "stdint.h"
 
+#define MAKE_RING_BUFFER(BUF_PTR, SIZE)        \
+    {                                          \
+        .buf_start_pos = (BUF_PTR),            \
+        .buf_end_pos = ((BUF_PTR) + (SIZE)-1), \
+        .base = (BUF_PTR),                     \
+        .head = (BUF_PTR),                     \
+        .count = 0,                            \
+    }
+
 struct ring_buffer {
     char* const buf_start_pos;
     char* const buf_end_pos;

+ 42 - 0
src/kernel/hw/keyboard.c

@@ -0,0 +1,42 @@
+#include <asm/port_io.h>
+#include <kernel/hw/keyboard.h>
+#include <kernel/stdio.h>
+#include <kernel/vga.h>
+#include <types/types.h>
+
+#define KEYBOARD_SCAN_CODE_BUFFER_SIZE (256)
+static char keyboard_scan_code_buf[KEYBOARD_SCAN_CODE_BUFFER_SIZE];
+static struct ring_buffer* p_scan_code_buf = 0;
+
+void handle_keyboard_interrupt(void)
+{
+    static struct ring_buffer
+        s_scan_code_buf
+        = MAKE_RING_BUFFER(keyboard_scan_code_buf, KEYBOARD_SCAN_CODE_BUFFER_SIZE);
+    if (p_scan_code_buf == 0)
+        p_scan_code_buf = &s_scan_code_buf;
+
+    char c = 0x00;
+    c = (char)asm_inb(PORT_KEYDATA);
+
+    ring_buffer_write(p_scan_code_buf, c);
+}
+
+int32_t keyboard_has_data(void)
+{
+    // uninitialized
+    if (p_scan_code_buf == 0)
+        return 0;
+    return !ring_buffer_empty(p_scan_code_buf);
+}
+
+void process_keyboard_data(void)
+{
+    char buf[128] = { 0 };
+    while (keyboard_has_data()) {
+        char c;
+        c = ring_buffer_read(p_scan_code_buf);
+        snprintf(buf, 128, "%d", (int32_t)c);
+    }
+    vga_printk(buf, 0x0fu);
+}

+ 41 - 43
src/kernel/interrupt.c

@@ -1,6 +1,7 @@
 #define _INTERRUPT_C_
 
 #include <asm/port_io.h>
+#include <kernel/hw/keyboard.h>
 #include <kernel/interrupt.h>
 #include <kernel/stdio.h>
 #include <kernel/vga.h>
@@ -10,19 +11,19 @@ static struct IDT_entry IDT[256];
 
 void init_idt()
 {
-    asm_outb(0x20, 0x11); // edge trigger mode
-    asm_outb(0x21, 0x20); // start from int 0x20
-    asm_outb(0x21, 0x04); // PIC1 is connected to IRQ2 (1 << 2)
-    asm_outb(0x21, 0x01); // no buffer mode
+    asm_outb(PORT_PIC1_COMMAND, 0x11); // edge trigger mode
+    asm_outb(PORT_PIC1_DATA, 0x20); // start from int 0x20
+    asm_outb(PORT_PIC1_DATA, 0x04); // PIC1 is connected to IRQ2 (1 << 2)
+    asm_outb(PORT_PIC1_DATA, 0x01); // no buffer mode
 
-    asm_outb(0xa0, 0x11); // edge trigger mode
-    asm_outb(0xa1, 0x28); // start from int 0x28
-    asm_outb(0xa1, 0x02); // connected to IRQ2
-    asm_outb(0xa1, 0x01); // no buffer mode
+    asm_outb(PORT_PIC2_COMMAND, 0x11); // edge trigger mode
+    asm_outb(PORT_PIC2_DATA, 0x28); // start from int 0x28
+    asm_outb(PORT_PIC2_DATA, 0x02); // connected to IRQ2
+    asm_outb(PORT_PIC2_DATA, 0x01); // no buffer mode
 
     // allow all the interrupts
-    asm_outb(0x21, 0x00);
-    asm_outb(0xa1, 0x00);
+    asm_outb(PORT_PIC1_DATA, 0x00);
+    asm_outb(PORT_PIC2_DATA, 0x00);
 
     // handle general protection fault (handle segmentation fault)
     SET_IDT_ENTRY_FN(13, int13, 0x08);
@@ -66,10 +67,10 @@ void int13_handler(
 
     snprintf(
         buf, 512,
-        "eax: %d, ebx: %d, ecx: %d, edx: %d\n"
-        "esp: %d, ebp: %d, esi: %d, edi: %d\n"
-        "eip: %d, cs: %d, error_code: %d   \n"
-        "eflags: %d                        \n",
+        "eax: %x, ebx: %x, ecx: %x, edx: %x\n"
+        "esp: %x, ebp: %x, esi: %x, edi: %x\n"
+        "eip: %x, cs: %x, error_code: %x   \n"
+        "eflags: %x                        \n",
         s_regs.eax, s_regs.ebx, s_regs.ecx,
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
@@ -84,79 +85,76 @@ void int13_handler(
 
 void irq0_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 // keyboard interrupt
 void irq1_handler(void)
 {
-    asm_outb(0x20, 0x20);
-    uint8_t c = 0x00;
-    c = asm_inb(PORT_KEYDATA);
-    static char buf[4] = { 0 };
-    snprintf(buf, 4, "%d", c);
-    vga_printk(buf, 0x0fu);
+    handle_keyboard_interrupt();
+
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq2_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq3_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq4_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq5_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq6_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq7_handler(void)
 {
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq8_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq9_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq10_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq11_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq12_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq13_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq14_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }
 void irq15_handler(void)
 {
-    asm_outb(0xa0, 0x20);
-    asm_outb(0x20, 0x20);
+    asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
+    asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
 }

+ 8 - 0
src/kernel_main.c

@@ -2,6 +2,7 @@
 
 #include <asm/boot.h>
 #include <asm/port_io.h>
+#include <kernel/hw/keyboard.h>
 #include <kernel/interrupt.h>
 #include <kernel/mem.h>
 #include <kernel/stdio.h>
@@ -38,6 +39,13 @@ void kernel_main(void)
     vga_printk("No work to do, halting...\n", 0x0fU);
 
     while (1) {
+        // disable interrupt
+        asm_cli();
+
+        if (keyboard_has_data()) {
+            process_keyboard_data();
+        }
+        asm_sti();
         asm_hlt();
     }
 }