commit b36b06a67ffbbe92bddc0f15f93f0985ad509917
parent 850434fb99e947be383d59a9948572dd0369f8eb
Author: evenfri <evenfri256@gmail.com>
Date: Sun, 23 Aug 2026 21:55:34 +0800
add keyboard driver, pit
Diffstat:
16 files changed, 261 insertions(+), 22 deletions(-)
diff --git a/dat.h b/dat.h
@@ -57,4 +57,9 @@ typedef void (*int_handler)();
#define irq_0 0x20
#define irq_8 0x28
+/* pit */
+#define pit_chan0 0x40
+#define pit_comm 0x43
+#define pit_base_freq 1193182
+
#endif /* dat_h */
diff --git a/drivers.h b/drivers.h
@@ -0,0 +1,7 @@
+#ifndef drivers_h
+#define drivers_h
+
+#include "keyboard/keyboard.h"
+
+#endif /* drivers_h */
+
diff --git a/fns.h b/fns.h
@@ -47,4 +47,8 @@ extern void gdt_init(void);
void idt_register(unsigned char vec, int_handler handler);
void idt_init(void);
+/* pit */
+void pit_init(uint32_t freq);
+void pit_sleep(uint32_t ticks_to_wait);
+
#endif /* fns_h */
diff --git a/idt.c b/idt.c
@@ -4,6 +4,7 @@ static idt_entry_t idt[256];
static idtr_t idtr;
void excp_handler() {
+ tty_write("IDT: exception handled\n", 23);
asm volatile ("cli; hlt");
}
@@ -19,7 +20,7 @@ void pic_remap() {
outb(pic_1_data, 0x01); io_wait();
outb(pic_2_data, 0x01); io_wait();
- outb(pic_1_data, 0xfc); io_wait();
+ outb(pic_1_data, 0xfd); io_wait();
outb(pic_2_data, 0xff); io_wait();
}
diff --git a/init.c b/init.c
@@ -1,6 +1,17 @@
#include "oxytoxin.h"
-void stub(void) {
+size_t read(void *buf, size_t size) {
+ size_t bytes_read;
+ size_t i;
+
+ char *ptr = (char *)buf;
+ bytes_read = 0;
+
+ for (i = 0; i < size; i++) {
+ ptr[i] = keyboard_read();
+ bytes_read++;
+ }
+ return bytes_read;
}
void start_kernel(uint32_t magic, multiboot_info_t *mbi) {
@@ -10,12 +21,21 @@ void start_kernel(uint32_t magic, multiboot_info_t *mbi) {
tty_init();
gdt_init();
idt_init();
-
- idt_register(33, stub);
+ pit_init(1000);
+ keyboard_init();
asm volatile ("sti");
while (1) {
- asm volatile ("hlt");
+ char c;
+ size_t bytes;
+
+ bytes = read(&c, 1);
+
+ if (bytes > 0) {
+ tty_write(&c, 1);
+ } else {
+ asm volatile("hlt");
+ }
}
}
diff --git a/isr_stub.asm b/isr_stub.asm
@@ -0,0 +1,25 @@
+bits 32
+
+global irq0_stub
+extern pit_handler
+
+section .text
+
+irq0_stub:
+ pusha
+
+ mov ax, ds
+ push eax
+
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+
+ call pit_handler
+
+ pop eax
+ mov ds, ax
+ mov es, ax
+
+ popa
+ iret
diff --git a/keyboard/built-in.a b/keyboard/built-in.a
Binary files differ.
diff --git a/keyboard/keyboard.c b/keyboard/keyboard.c
@@ -0,0 +1,80 @@
+#include "oxytoxin.h"
+#include "keyboard.h"
+
+unsigned int shift_state = 0;
+
+unsigned char buf[buf_size];
+unsigned int buf_head = 0;
+unsigned int buf_tail = 0;
+
+const char lower_scancodes[128] = {
+ 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
+ '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
+ '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
+ ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',',
+ '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0};
+
+const char upper_scancodes[128] = {
+ 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
+ '{', '}', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
+ ':', '\"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<',
+ '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0};
+
+extern void keyboard_entry(void);
+
+char keyboard_read(void) {
+ char ch;
+
+ while (1) {
+ asm volatile ("cli");
+ if (buf_head != buf_tail) {
+ ch = buf[buf_head];
+ buf_head = (buf_head + 1) % buf_size;
+ asm volatile ("sti");
+ return ch;
+ }
+ asm volatile ("sti; hlt");
+ }
+}
+
+void keyboard_handler(void) {
+ unsigned char scancode;
+ unsigned int next_tail;
+ char ascii_char;
+
+ scancode = inb(0x60);
+
+ if (scancode == 0x2a || scancode == 0x36) {
+ shift_state = 1;
+ outb(0x20, 0x20);
+ return;
+ } else if (scancode == 0xaa || scancode == 0xb6) {
+ shift_state = 0;
+ outb(0x20, 0x20);
+ return;
+ }
+
+
+ if (scancode < 0x80) {
+ if (shift_state) {
+ ascii_char = upper_scancodes[scancode];
+ } else {
+ ascii_char = lower_scancodes[scancode];
+ }
+
+ if (ascii_char != 0) {
+ next_tail = (buf_tail + 1) % buf_size;
+ if (next_tail != buf_head) {
+ buf[buf_tail] = ascii_char;
+ buf_tail = next_tail;
+ }
+ }
+ }
+
+ outb(0x20, 0x20);
+}
+
+void keyboard_init(void) {
+ idt_register(33, keyboard_entry);
+}
diff --git a/keyboard/keyboard.h b/keyboard/keyboard.h
@@ -0,0 +1,10 @@
+#ifndef keyboard_h
+#define keyboard_h
+
+#define buf_size 16
+
+char keyboard_read(void);
+void keyboard_init(void);
+
+#endif /* keyboard_h */
+
diff --git a/keyboard/keyboard_entry.asm b/keyboard/keyboard_entry.asm
@@ -0,0 +1,12 @@
+bits 32
+
+global keyboard_entry
+extern keyboard_handler
+
+section .text
+
+keyboard_entry:
+ pusha
+ call keyboard_handler
+ popa
+ iret
diff --git a/keyboard/mkfile b/keyboard/mkfile
@@ -0,0 +1,15 @@
+<$kernel/build/mkhdr
+
+as = ../build/as
+cc = ../build/cc
+ar = ../build/ar
+
+ofiles = keyboard_entry.$o \
+ keyboard.$o
+
+hfiles = keyboard.h
+
+lib = built-in.a
+
+<$kernel/build/mklib
+<$kernel/build/mkcommon
diff --git a/mkfile b/mkfile
@@ -7,8 +7,8 @@ cc = ./build/cc
ld = ./build/ld
ar = ./build/ar
-ldflags =
-dirs =
+ldflags = keyboard/built-in.a
+dirs = keyboard
ofiles = boot.$o \
vga.$o \
@@ -16,10 +16,13 @@ ofiles = boot.$o \
gdt.$o \
ints.$o \
idt.$o \
+ pit.$o \
+ isr_stub.$o \
init.$o \
hfiles = dat.h \
fns.h \
+ drivers.h \
oxytoxin.h \
targ = oxytoxin
diff --git a/oxytoxin.h b/oxytoxin.h
@@ -8,4 +8,6 @@
#include "dat.h"
#include "fns.h"
+#include "drivers.h"
+
#endif /* oxytoxin_h */
diff --git a/pit.c b/pit.c
@@ -0,0 +1,36 @@
+#include "oxytoxin.h"
+
+volatile uint64_t g_ticks = 0;
+
+extern void irq0_stub(void);
+
+void pit_handler(void) {
+ g_ticks++;
+ outb(0x20, 0x20);
+}
+
+void pit_init(uint32_t freq) {
+ /* calc divisor */
+ uint32_t divisor = pit_base_freq / freq;
+
+ /* limit */
+ if (divisor > 0xffff) divisor = 0xffff;
+ if (divisor < 1) divisor = 1;
+
+ /* command byte */
+ outb(pit_comm, 0x36);
+ /* lsb */
+ outb(pit_chan0, (uint8_t)(divisor & 0xff));
+ /* msb */
+ outb(pit_chan0, (uint8_t)((divisor >> 8) & 0xff));
+
+ idt_register(0x20, irq0_stub);
+}
+
+void pit_sleep(uint32_t ticks_to_wait) {
+ uint64_t target_ticks = g_ticks + ticks_to_wait;
+ while (g_ticks < target_ticks) {
+ asm volatile ("hlt");
+ }
+}
+
diff --git a/tty.c b/tty.c
@@ -10,17 +10,23 @@ void tty_set_color(uint8_t color) {
}
void tty_putentryat(char c, uint8_t color, size_t x, size_t y) {
- const size_t index = y * vga_width + x;
+ size_t index;
+
+ index = y * vga_width + x;
tty_buffer[index] = vga_entry(c, color);
}
void tty_clear(void) {
+ size_t x;
+ size_t y;
+ size_t index;
+
tty_row = 0;
tty_column = 0;
- for (size_t y = 0; y < vga_height; y++) {
- for (size_t x = 0; x < vga_width; x++) {
- const size_t index = y * vga_width + x;
+ for (y = 0; y < vga_height; y++) {
+ for (x = 0; x < vga_width; x++) {
+ index = y * vga_width + x;
tty_buffer[index] = vga_entry(' ', tty_color);
}
}
@@ -34,21 +40,29 @@ void tty_init(void) {
}
void tty_scroll(void) {
+ int row;
+ int col;
+ size_t src_index;
+ size_t dst_index;
+ uint16_t blank;
+ size_t index;
+
/* move lines to line-1 */
- for (int row = 1; row < vga_height; row++) {
- for (int col = 0; col < vga_width; col++) {
- size_t src_index = row * vga_width + col;
- size_t dst_index = (row - 1) * vga_width + col;
+ for (row = 1; row < vga_height; row++) {
+ for (col = 0; col < vga_width; col++) {
+ src_index = row * vga_width + col;
+ dst_index = (row - 1) * vga_width + col;
tty_buffer[dst_index] = tty_buffer[src_index];
}
}
/* clear last line*/
- uint16_t blank = ' ' | (tty_color << 8);
- for (int col = 0; col < vga_width; col++) {
- size_t index = (vga_height - 1) * vga_width + col;
+ blank = ' ' | (tty_color << 8);
+ for (col = 0; col < vga_width; col++) {
+ index = (vga_height - 1) * vga_width + col;
tty_buffer[index] = blank;
}
}
+
void tty_putchar(char c) {
if(c == '\n') {
tty_row++;
@@ -78,8 +92,9 @@ void tty_putchar(char c) {
}
void tty_write(const char* data, size_t size) {
- for(size_t i = 0; i < size; i++) {
+ size_t i;
+
+ for (i = 0; i < size; i++) {
tty_putchar(data[i]);
}
}
-
diff --git a/vga.c b/vga.c
@@ -14,7 +14,9 @@ void vga_cursor_disable(void) {
}
void vga_cursor_update(int x, int y) {
- uint16_t pos = y * vga_width + x;
+ uint16_t pos;
+
+ pos = y * vga_width + x;
outb(vga_ctrl, 0x0f);
outb(vga_data, (uint8_t) (pos & 0xff));
@@ -23,7 +25,9 @@ void vga_cursor_update(int x, int y) {
}
uint16_t vga_cursor_get_pos(void) {
- uint16_t pos = 0;
+ uint16_t pos;
+
+ pos = 0;
outb(vga_ctrl, 0x0f);
pos |= inb(0x3d5);