From 402211c0382c0238f70471ec51c4d3ef27ce6ca0 Mon Sep 17 00:00:00 2001 From: Furkan Mudanyali Date: Thu, 21 Jul 2022 12:20:35 +0300 Subject: [PATCH] Initial timer and keyboard mapping --- kernel/Makefile | 2 + kernel/arch/i386/boot/idt.c | 18 ++----- kernel/arch/i386/boot/pic.c | 6 +-- kernel/include/rockos/idt.h | 2 - kernel/include/rockos/irq.h | 0 kernel/include/rockos/keyboard.h | 3 ++ kernel/include/rockos/timer.h | 16 ++++++ kernel/rockos/kernel.c | 18 ++++++- kernel/rockos/keyboard.c | 86 ++++++++++++++++++++++++++++++++ kernel/rockos/paging.c | 2 +- kernel/rockos/timer.c | 26 ++++++++++ 11 files changed, 157 insertions(+), 22 deletions(-) delete mode 100644 kernel/include/rockos/irq.h create mode 100644 kernel/include/rockos/keyboard.h create mode 100644 kernel/include/rockos/timer.h create mode 100644 kernel/rockos/keyboard.c create mode 100644 kernel/rockos/timer.c diff --git a/kernel/Makefile b/kernel/Makefile index 5f1701f..0cd6a48 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -31,6 +31,8 @@ KERNEL_OBJS=\ $(KERNEL_ARCH_OBJS) \ rockos/kernel.o \ rockos/paging.o \ +rockos/keyboard.o \ +rockos/timer.o \ OBJS=\ $(ARCHDIR)/boot/crti.o \ diff --git a/kernel/arch/i386/boot/idt.c b/kernel/arch/i386/boot/idt.c index 0b0a618..56408a3 100644 --- a/kernel/arch/i386/boot/idt.c +++ b/kernel/arch/i386/boot/idt.c @@ -1,18 +1,8 @@ #include -#include +#include +#include #include -static unsigned char key; - -__attribute__((interrupt)) void keyboard_handler(void* frame) { - key = inb(0x60); - outb(0x20, 0x20); -} - -unsigned char readkey() { - return key; -} - __attribute__((interrupt)) void int_handler(void* frame, unsigned int number) { if (number <= 21) { printf("%s\n", err_msg[number]); @@ -107,7 +97,9 @@ void idt_init(void) { idt_set_descriptor(29, int29_wrapper, 0x8E); idt_set_descriptor(30, int30_wrapper, 0x8E); idt_set_descriptor(31, int31_wrapper, 0x8E); - + // IRQs + idt_set_descriptor(32, timer_handler, 0x8E); + timer_phase(100); idt_set_descriptor(33, keyboard_handler, 0x8E); __asm__ volatile("lidt %0" : : "m"(idtptr)); // Load new IDT diff --git a/kernel/arch/i386/boot/pic.c b/kernel/arch/i386/boot/pic.c index b9d39b1..2d186ea 100644 --- a/kernel/arch/i386/boot/pic.c +++ b/kernel/arch/i386/boot/pic.c @@ -23,8 +23,6 @@ void PIC_remap() { outb(PIC2_DATA, ICW4_8086); io_wait(); - outb(PIC1_DATA, 0xFF); // restore saved masks - outb(PIC2_DATA, 0xFF); - - outb(PIC1_DATA, 0xFD); // Keyboard IRQ + outb(PIC1_DATA, 0); // ALL THE INTERRUPTS + outb(PIC2_DATA, 0); } \ No newline at end of file diff --git a/kernel/include/rockos/idt.h b/kernel/include/rockos/idt.h index 010b1be..799de1c 100644 --- a/kernel/include/rockos/idt.h +++ b/kernel/include/rockos/idt.h @@ -44,6 +44,4 @@ static char* err_msg[] = { "#CP Control Protection Exception!" }; -unsigned char readkey(); - #endif \ No newline at end of file diff --git a/kernel/include/rockos/irq.h b/kernel/include/rockos/irq.h deleted file mode 100644 index e69de29..0000000 diff --git a/kernel/include/rockos/keyboard.h b/kernel/include/rockos/keyboard.h new file mode 100644 index 0000000..0b38965 --- /dev/null +++ b/kernel/include/rockos/keyboard.h @@ -0,0 +1,3 @@ +void keyboard_handler(void* frame); +unsigned char readkey(); +void initialize_keyset(); \ No newline at end of file diff --git a/kernel/include/rockos/timer.h b/kernel/include/rockos/timer.h new file mode 100644 index 0000000..a379750 --- /dev/null +++ b/kernel/include/rockos/timer.h @@ -0,0 +1,16 @@ +#include + +#define SUBTICKS_PER_TICK 100 + +#define PIT_0 0x40 +#define PIT_1 0x41 +#define PIT_2 0x42 +#define PIT_CONTROL 0x43 + +#define PIT_MASK 0xFF +#define PIT_SCALE 1193180 +#define PIT_SET 0x36 + +void timer_phase(uint32_t hz); +void timer_handler(void* frame); +uint64_t get_ticks(); \ No newline at end of file diff --git a/kernel/rockos/kernel.c b/kernel/rockos/kernel.c index 8a9cf9c..5bd5828 100644 --- a/kernel/rockos/kernel.c +++ b/kernel/rockos/kernel.c @@ -1,7 +1,10 @@ #include #include -#include +#include +#include +#include +#include void kernel_main(void) { printf("Hello, kernel World!\n"); @@ -10,14 +13,25 @@ void kernel_main(void) { printf("Int test: %d\n", 747474); printf("Hex test: 0x%x\n", 0xDEADBEEF); printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2); + initialize_keyset(); + + outb(0x70, (0x80 << 7) | 0x0); // Seconds + uint8_t sec = inb(0x71); + outb(0x70, (0x80 << 7) | 0x02); // Minutes + uint8_t min = inb(0x71); + outb(0x70, (0x80 << 7) | 0x04); // Hours + uint8_t hour = inb(0x71); + printf("Time: %x:%x:%x\n", hour, min, sec); unsigned char oldkey; unsigned char key = readkey(); for(;;){ oldkey = key; key = readkey(); - if (key != oldkey) + if (key != '\0') { putchar(key); + } + } asm("cli; hlt"); diff --git a/kernel/rockos/keyboard.c b/kernel/rockos/keyboard.c new file mode 100644 index 0000000..2885ecd --- /dev/null +++ b/kernel/rockos/keyboard.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +#define ESC_P 0x01 +#define BACKSPACE_P 0x0F +#define ENTER_P 0x1C +#define LEFT_C_P 0x1D +#define LEFT_SHIFT_P 0x2B +#define RIGHT_SHIFT_P 0x36 +#define LEFT_ALT_P 0x38 +#define CAPS_LCK_P 0x3A + +static unsigned char interrupt_key; +static uint8_t keyset[89]; +static uint64_t keytimes[89]; + +static unsigned char keymap[89] = { + 0, ESC_P, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', BACKSPACE_P, + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', ENTER_P, LEFT_C_P, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', LEFT_SHIFT_P, '\\', + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', RIGHT_SHIFT_P, '*', LEFT_ALT_P, ' ', CAPS_LCK_P +}; + +void initialize_keyset() { + //for(int i = 0; i < 89; ++i) keyset[i] = 0; + memset(keyset, 0, 89); + memset(keytimes, 0, 89); +} + +__attribute__((interrupt)) void keyboard_handler(void* frame) { + interrupt_key = inb(0x60); + pic_eoi(1); + if((interrupt_key & 128) == 128){ + keyset[interrupt_key - 0x80] = 0; + keytimes[interrupt_key - 0x80] = 0; + } else { + if(keyset[interrupt_key] == 2) + return; + keyset[interrupt_key] = 1; + } +} + +unsigned char readkey() { + uint8_t shift_pressed = 0; + if (keyset[LEFT_SHIFT_P] || keyset[RIGHT_SHIFT_P]) + shift_pressed = 1; + + for(uint8_t i = 0; i < 89; ++i) { + switch(i) { + case ESC_P: + case LEFT_C_P: + case LEFT_SHIFT_P: + case RIGHT_SHIFT_P: + case LEFT_ALT_P: + case CAPS_LCK_P: + continue; + } + if (keyset[i]){ + uint64_t temptime = get_ticks(); + if(keytimes[i]) { + if(keyset[i] == 1) { + if(temptime - keytimes[i] < 20) { + return 0; + } else { + keyset[i] = 2; + //return 0; + } + } else { + if(temptime - keytimes[i] < 5) { + return 0; + } + } + } + keytimes[i] = temptime; + if (shift_pressed && (keymap[i] > 0x60 && keymap[i] < 0x7A)) { + return keymap[i] - 0x20; + } else { + return keymap[i]; + } + } + } + return 0; +} \ No newline at end of file diff --git a/kernel/rockos/paging.c b/kernel/rockos/paging.c index e9fb96e..ae47352 100644 --- a/kernel/rockos/paging.c +++ b/kernel/rockos/paging.c @@ -1,7 +1,7 @@ #include #include -void load_page_dir(uint32_t page_dir) { +void load_page_dir(uint32_t* page_dir) { asm volatile ( "mov %%eax, %%cr3" : diff --git a/kernel/rockos/timer.c b/kernel/rockos/timer.c new file mode 100644 index 0000000..37def03 --- /dev/null +++ b/kernel/rockos/timer.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +uint64_t ticks = 0; +uint8_t subticks = 0; + +__attribute__((interrupt)) void timer_handler(void* frame) { + if(++subticks == SUBTICKS_PER_TICK) { + ++ticks; + subticks = 0; + } + pic_eoi(0); +} + +void timer_phase(uint32_t hz) { + uint32_t divisor = PIT_SCALE / hz; + outb(PIT_CONTROL, PIT_SET); + outb(PIT_0, divisor & PIT_MASK); + outb(PIT_0, (divisor >> 8) & PIT_MASK); +} + +uint64_t get_ticks() { + return ticks*100 + subticks; +} \ No newline at end of file