oxytoxin

unix-like kernel
git clone git://git.evenfri.xyz/oxytoxin.git
Log | Files | Refs | README | LICENSE

commit b36b06a67ffbbe92bddc0f15f93f0985ad509917
parent 850434fb99e947be383d59a9948572dd0369f8eb
Author: evenfri <evenfri256@gmail.com>
Date:   Sun, 23 Aug 2026 21:55:34 +0800

add keyboard driver, pit

Diffstat:
Mdat.h | 5+++++
Adrivers.h | 7+++++++
Mfns.h | 4++++
Midt.c | 3++-
Minit.c | 28++++++++++++++++++++++++----
Aisr_stub.asm | 25+++++++++++++++++++++++++
Akeyboard/built-in.a | 0
Akeyboard/keyboard.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Akeyboard/keyboard.h | 10++++++++++
Akeyboard/keyboard_entry.asm | 12++++++++++++
Akeyboard/mkfile | 15+++++++++++++++
Mmkfile | 7+++++--
Moxytoxin.h | 2++
Apit.c | 36++++++++++++++++++++++++++++++++++++
Mtty.c | 41++++++++++++++++++++++++++++-------------
Mvga.c | 8++++++--
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);