sos

[unmaintained] experimenting with low level OS development
Log | Files | Refs | README | LICENSE

commit f4d64c45e2956dc72c7f3a46219665e8d9078866
parent 18c89ffc212ae5485fbfe52a0ab5a3f772ac0c74
Author: Stefan <misc@stefan-koch.name>
Date:   Sat, 21 Nov 2015 16:49:35 +0100

added code for keyboard input

Diffstat:
MMakefile | 24+++++++++++++-----------
March/x86/gdt.c | 2+-
March/x86/idt.asm | 721++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
March/x86/idt.c | 210++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Aarch/x86/pic.c | 34++++++++++++++++++++++++++++++++++
Aarch/x86/pic.h | 6++++++
Adrivers/hid/keyboard/keyboard.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adrivers/hid/keyboard/keyboard.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adrivers/hid/keyboard/ps2.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/arch/x86/io.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/arch/x86/io.h | 30++++++++++++++++++++++++++++++
Ainclude/arch/x86/math.c | 8++++++++
Ainclude/arch/x86/math.h | 1+
13 files changed, 1387 insertions(+), 24 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,18 +1,21 @@ ASM = nasm ASMFLAGS = GCC = $(HOME)/opt/cross/bin/i586-elf-gcc -GCCFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra +GCCFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -Iinclude + +C_OBJECTS = $(patsubst %.c, %.o, $(shell find . -name "*.c")) +ASM_OBJECTS = $(patsubst %.asm, %_asm.o, $(shell find . -name "*.asm")) all: image kernel kernel-install -kernel: - $(ASM) arch/x86/boot.asm -o arch/x86/boot.o -f elf - $(ASM) arch/x86/gdt.asm -o arch/x86/gdt_asm.o -f elf - $(ASM) arch/x86/idt.asm -o arch/x86/idt_asm.o -f elf - $(GCC) -c kernel.c -o kernel.o $(GCCFLAGS) - $(GCC) -c arch/x86/gdt.c -o arch/x86/gdt.o $(GCCFLAGS) - $(GCC) -c arch/x86/idt.c -o arch/x86/idt.o $(GCCFLAGS) - $(GCC) -T kernel.ld -o sos-kernel.img -ffreestanding -O2 -nostdlib arch/x86/boot.o kernel.o arch/x86/gdt_asm.o arch/x86/gdt.o arch/x86/idt.o arch/x86/idt_asm.o -lgcc +%_asm.o: %.asm + $(ASM) $< -o $@ -f elf + +%.o: %.c + $(GCC) -c $< -o $@ $(GCCFLAGS) + +kernel: $(C_OBJECTS) $(ASM_OBJECTS) + $(GCC) -T kernel.ld -o sos-kernel.img -ffreestanding -O2 -nostdlib $(C_OBJECTS) $(ASM_OBJECTS) -lgcc kernel-install: sudo losetup /dev/loop1 sos.img -o 1048576 @@ -36,7 +39,6 @@ image: sudo losetup -d /dev/loop1 clean: - rm arch/x86/*.o - rm *.o + rm $(ASM_OBJECTS) $(C_OBJECTS) rm sos-kernel.img rm sos.img diff --git a/arch/x86/gdt.c b/arch/x86/gdt.c @@ -3,7 +3,7 @@ extern void gdt_install(); -void gdt_set_entry(unsigned int pos, uint32_t base, uint32_t limit, +static void gdt_set_entry(unsigned int pos, uint32_t base, uint32_t limit, uint8_t access_rights, uint8_t flags) { gdt[pos].base_lower = base & 0xffff; diff --git a/arch/x86/idt.asm b/arch/x86/idt.asm @@ -1,7 +1,716 @@ +section .data +int_counter db 0 + section .text -global int_handler -int_handler: - mov ax, 0x10 - mov gs, ax - mov dword [gs:0xB8000],') : ' - hlt +global int_handler_0 +int_handler_0: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'0 ' +hlt + +global int_handler_1 +int_handler_1: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 ' +hlt + +global int_handler_2 +int_handler_2: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 ' +hlt + +global int_handler_3 +int_handler_3: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 ' +hlt + +global int_handler_4 +int_handler_4: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 ' +hlt + +global int_handler_5 +int_handler_5: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 ' +hlt + +global int_handler_6 +int_handler_6: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 ' +hlt + +global int_handler_7 +int_handler_7: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 ' +hlt + +global int_handler_8 +int_handler_8: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 ' +hlt + +global int_handler_9 +int_handler_9: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 ' +hlt + +global int_handler_10 +int_handler_10: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 0 ' +hlt + +global int_handler_11 +int_handler_11: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 1 ' +hlt + +global int_handler_12 +int_handler_12: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 2 ' +hlt + +global int_handler_13 +int_handler_13: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 3 ' +hlt + +global int_handler_14 +int_handler_14: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 4 ' +hlt + +global int_handler_15 +int_handler_15: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 5 ' +hlt + +global int_handler_16 +int_handler_16: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 6 ' +hlt + +global int_handler_17 +int_handler_17: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 7 ' +hlt + +global int_handler_18 +int_handler_18: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 8 ' +hlt + +global int_handler_19 +int_handler_19: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'1 9 ' +hlt + +global int_handler_20 +int_handler_20: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 0 ' +hlt + +global int_handler_21 +int_handler_21: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 1 ' +hlt + +global int_handler_22 +int_handler_22: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 2 ' +hlt + +global int_handler_23 +int_handler_23: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 3 ' +hlt + +global int_handler_24 +int_handler_24: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 4 ' +hlt + +global int_handler_25 +int_handler_25: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 5 ' +hlt + +global int_handler_26 +int_handler_26: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 6 ' +hlt + +global int_handler_27 +int_handler_27: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 7 ' +hlt + +global int_handler_28 +int_handler_28: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 8 ' +hlt + +global int_handler_29 +int_handler_29: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'2 9 ' +hlt + +global int_handler_30 +int_handler_30: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 0 ' +hlt + +global int_handler_31 +int_handler_31: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 1 ' +hlt + +global int_handler_32 +int_handler_32: +mov ax, 0x10 +mov gs, ax +xor ax, ax +mov al, byte [gs:int_counter] +inc al +mov byte [gs:int_counter], al +mov bl, 18 +div bl +mov byte [gs:0xB8000], al +mov al, 0x20 +out 0x20, al +iret + +extern keyboard_irq_handler +global int_handler_33 +int_handler_33: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 3 ' +call keyboard_irq_handler +mov al, 0x20 +out 0x20, al +iret + +global int_handler_34 +int_handler_34: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 4 ' +hlt + +global int_handler_35 +int_handler_35: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 5 ' +hlt + +global int_handler_36 +int_handler_36: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 6 ' +hlt + +global int_handler_37 +int_handler_37: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 7 ' +hlt + +global int_handler_38 +int_handler_38: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 8 ' +hlt + +global int_handler_39 +int_handler_39: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'3 9 ' +hlt + +global int_handler_40 +int_handler_40: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 0 ' +hlt + +global int_handler_41 +int_handler_41: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 1 ' +hlt + +global int_handler_42 +int_handler_42: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 2 ' +hlt + +global int_handler_43 +int_handler_43: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 3 ' +hlt + +global int_handler_44 +int_handler_44: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 4 ' +hlt + +global int_handler_45 +int_handler_45: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 5 ' +hlt + +global int_handler_46 +int_handler_46: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 6 ' +hlt + +global int_handler_47 +int_handler_47: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 7 ' +hlt + +global int_handler_48 +int_handler_48: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 8 ' +hlt + +global int_handler_49 +int_handler_49: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'4 9 ' +hlt + +global int_handler_50 +int_handler_50: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 0 ' +hlt + +global int_handler_51 +int_handler_51: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 1 ' +hlt + +global int_handler_52 +int_handler_52: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 2 ' +hlt + +global int_handler_53 +int_handler_53: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 3 ' +hlt + +global int_handler_54 +int_handler_54: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 4 ' +hlt + +global int_handler_55 +int_handler_55: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 5 ' +hlt + +global int_handler_56 +int_handler_56: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 6 ' +hlt + +global int_handler_57 +int_handler_57: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 7 ' +hlt + +global int_handler_58 +int_handler_58: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 8 ' +hlt + +global int_handler_59 +int_handler_59: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'5 9 ' +hlt + +global int_handler_60 +int_handler_60: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 0 ' +hlt + +global int_handler_61 +int_handler_61: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 1 ' +hlt + +global int_handler_62 +int_handler_62: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 2 ' +hlt + +global int_handler_63 +int_handler_63: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 3 ' +hlt + +global int_handler_64 +int_handler_64: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 4 ' +hlt + +global int_handler_65 +int_handler_65: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 5 ' +hlt + +global int_handler_66 +int_handler_66: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 6 ' +hlt + +global int_handler_67 +int_handler_67: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 7 ' +hlt + +global int_handler_68 +int_handler_68: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 8 ' +hlt + +global int_handler_69 +int_handler_69: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'6 9 ' +hlt + +global int_handler_70 +int_handler_70: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 0 ' +hlt + +global int_handler_71 +int_handler_71: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 1 ' +hlt + +global int_handler_72 +int_handler_72: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 2 ' +hlt + +global int_handler_73 +int_handler_73: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 3 ' +hlt + +global int_handler_74 +int_handler_74: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 4 ' +hlt + +global int_handler_75 +int_handler_75: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 5 ' +hlt + +global int_handler_76 +int_handler_76: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 6 ' +hlt + +global int_handler_77 +int_handler_77: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 7 ' +hlt + +global int_handler_78 +int_handler_78: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 8 ' +hlt + +global int_handler_79 +int_handler_79: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'7 9 ' +hlt + +global int_handler_80 +int_handler_80: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 0 ' +hlt + +global int_handler_81 +int_handler_81: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 1 ' +hlt + +global int_handler_82 +int_handler_82: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 2 ' +hlt + +global int_handler_83 +int_handler_83: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 3 ' +hlt + +global int_handler_84 +int_handler_84: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 4 ' +hlt + +global int_handler_85 +int_handler_85: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 5 ' +hlt + +global int_handler_86 +int_handler_86: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 6 ' +hlt + +global int_handler_87 +int_handler_87: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 7 ' +hlt + +global int_handler_88 +int_handler_88: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 8 ' +hlt + +global int_handler_89 +int_handler_89: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'8 9 ' +hlt + +global int_handler_90 +int_handler_90: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 0 ' +hlt + +global int_handler_91 +int_handler_91: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 1 ' +hlt + +global int_handler_92 +int_handler_92: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 2 ' +hlt + +global int_handler_93 +int_handler_93: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 3 ' +hlt + +global int_handler_94 +int_handler_94: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 4 ' +hlt + +global int_handler_95 +int_handler_95: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 5 ' +hlt + +global int_handler_96 +int_handler_96: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 6 ' +hlt + +global int_handler_97 +int_handler_97: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 7 ' +hlt + +global int_handler_98 +int_handler_98: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 8 ' +hlt + +global int_handler_99 +int_handler_99: +mov ax, 0x10 +mov gs, ax +mov dword [gs:0xB8000],'9 9 ' +hlt + diff --git a/arch/x86/idt.c b/arch/x86/idt.c @@ -1,7 +1,7 @@ #include <stdint.h> #include "idt.h" -void idt_set_entry(unsigned int pos, uint32_t base, +static void idt_set_entry(unsigned int pos, uint32_t base, uint16_t selector, uint8_t type_attributes) { idt[pos].base_lower = base & 0xffff; @@ -11,19 +11,217 @@ void idt_set_entry(unsigned int pos, uint32_t base, idt[pos].base_higher = (base >> 16) & 0xffff; } -extern void int_handler(); +extern void int_handler_0(); +extern void int_handler_1(); +extern void int_handler_2(); +extern void int_handler_3(); +extern void int_handler_4(); +extern void int_handler_5(); +extern void int_handler_6(); +extern void int_handler_7(); +extern void int_handler_8(); +extern void int_handler_9(); +extern void int_handler_10(); +extern void int_handler_11(); +extern void int_handler_12(); +extern void int_handler_13(); +extern void int_handler_14(); +extern void int_handler_15(); +extern void int_handler_16(); +extern void int_handler_17(); +extern void int_handler_18(); +extern void int_handler_19(); +extern void int_handler_20(); +extern void int_handler_21(); +extern void int_handler_22(); +extern void int_handler_23(); +extern void int_handler_24(); +extern void int_handler_25(); +extern void int_handler_26(); +extern void int_handler_27(); +extern void int_handler_28(); +extern void int_handler_29(); +extern void int_handler_30(); +extern void int_handler_31(); +extern void int_handler_32(); +extern void int_handler_33(); +extern void int_handler_34(); +extern void int_handler_35(); +extern void int_handler_36(); +extern void int_handler_37(); +extern void int_handler_38(); +extern void int_handler_39(); +extern void int_handler_40(); +extern void int_handler_41(); +extern void int_handler_42(); +extern void int_handler_43(); +extern void int_handler_44(); +extern void int_handler_45(); +extern void int_handler_46(); +extern void int_handler_47(); +extern void int_handler_48(); +extern void int_handler_49(); +extern void int_handler_50(); +extern void int_handler_51(); +extern void int_handler_52(); +extern void int_handler_53(); +extern void int_handler_54(); +extern void int_handler_55(); +extern void int_handler_56(); +extern void int_handler_57(); +extern void int_handler_58(); +extern void int_handler_59(); +extern void int_handler_60(); +extern void int_handler_61(); +extern void int_handler_62(); +extern void int_handler_63(); +extern void int_handler_64(); +extern void int_handler_65(); +extern void int_handler_66(); +extern void int_handler_67(); +extern void int_handler_68(); +extern void int_handler_69(); +extern void int_handler_70(); +extern void int_handler_71(); +extern void int_handler_72(); +extern void int_handler_73(); +extern void int_handler_74(); +extern void int_handler_75(); +extern void int_handler_76(); +extern void int_handler_77(); +extern void int_handler_78(); +extern void int_handler_79(); +extern void int_handler_80(); +extern void int_handler_81(); +extern void int_handler_82(); +extern void int_handler_83(); +extern void int_handler_84(); +extern void int_handler_85(); +extern void int_handler_86(); +extern void int_handler_87(); +extern void int_handler_88(); +extern void int_handler_89(); +extern void int_handler_90(); +extern void int_handler_91(); +extern void int_handler_92(); +extern void int_handler_93(); +extern void int_handler_94(); +extern void int_handler_95(); +extern void int_handler_96(); +extern void int_handler_97(); +extern void int_handler_98(); +extern void int_handler_99(); + void idt_setup() { idt_desc.limit = IDT_ENTRIES * sizeof(struct idt_entry) - 1; idt_desc.base = (uint32_t) (uintptr_t) idt; - // TODO: set some entries - for (int i = 0; i < IDT_ENTRIES; i++) { - idt_set_entry(i, (uint32_t)(uintptr_t)&int_handler, + idt_set_entry(0, (uint32_t)(uintptr_t)&int_handler_0, 0x8, 0x8e); + idt_set_entry(1, (uint32_t)(uintptr_t)&int_handler_1, 0x8, 0x8e); + idt_set_entry(2, (uint32_t)(uintptr_t)&int_handler_2, 0x8, 0x8e); + idt_set_entry(3, (uint32_t)(uintptr_t)&int_handler_3, 0x8, 0x8e); + idt_set_entry(4, (uint32_t)(uintptr_t)&int_handler_4, 0x8, 0x8e); + idt_set_entry(5, (uint32_t)(uintptr_t)&int_handler_5, 0x8, 0x8e); + idt_set_entry(6, (uint32_t)(uintptr_t)&int_handler_6, 0x8, 0x8e); + idt_set_entry(7, (uint32_t)(uintptr_t)&int_handler_7, 0x8, 0x8e); + idt_set_entry(8, (uint32_t)(uintptr_t)&int_handler_8, 0x8, 0x8e); + idt_set_entry(9, (uint32_t)(uintptr_t)&int_handler_9, 0x8, 0x8e); + idt_set_entry(10, (uint32_t)(uintptr_t)&int_handler_10, 0x8, 0x8e); + idt_set_entry(11, (uint32_t)(uintptr_t)&int_handler_11, 0x8, 0x8e); + idt_set_entry(12, (uint32_t)(uintptr_t)&int_handler_12, 0x8, 0x8e); + idt_set_entry(13, (uint32_t)(uintptr_t)&int_handler_13, 0x8, 0x8e); + idt_set_entry(14, (uint32_t)(uintptr_t)&int_handler_14, 0x8, 0x8e); + idt_set_entry(15, (uint32_t)(uintptr_t)&int_handler_15, 0x8, 0x8e); + idt_set_entry(16, (uint32_t)(uintptr_t)&int_handler_16, 0x8, 0x8e); + idt_set_entry(17, (uint32_t)(uintptr_t)&int_handler_17, 0x8, 0x8e); + idt_set_entry(18, (uint32_t)(uintptr_t)&int_handler_18, 0x8, 0x8e); + idt_set_entry(19, (uint32_t)(uintptr_t)&int_handler_19, 0x8, 0x8e); + idt_set_entry(20, (uint32_t)(uintptr_t)&int_handler_20, 0x8, 0x8e); + idt_set_entry(21, (uint32_t)(uintptr_t)&int_handler_21, 0x8, 0x8e); + idt_set_entry(22, (uint32_t)(uintptr_t)&int_handler_22, 0x8, 0x8e); + idt_set_entry(23, (uint32_t)(uintptr_t)&int_handler_23, 0x8, 0x8e); + idt_set_entry(24, (uint32_t)(uintptr_t)&int_handler_24, 0x8, 0x8e); + idt_set_entry(25, (uint32_t)(uintptr_t)&int_handler_25, 0x8, 0x8e); + idt_set_entry(26, (uint32_t)(uintptr_t)&int_handler_26, 0x8, 0x8e); + idt_set_entry(27, (uint32_t)(uintptr_t)&int_handler_27, 0x8, 0x8e); + idt_set_entry(28, (uint32_t)(uintptr_t)&int_handler_28, 0x8, 0x8e); + idt_set_entry(29, (uint32_t)(uintptr_t)&int_handler_29, 0x8, 0x8e); + idt_set_entry(30, (uint32_t)(uintptr_t)&int_handler_30, 0x8, 0x8e); + idt_set_entry(31, (uint32_t)(uintptr_t)&int_handler_31, 0x8, 0x8e); + idt_set_entry(32, (uint32_t)(uintptr_t)&int_handler_32, 0x8, 0x8e); + idt_set_entry(33, (uint32_t)(uintptr_t)&int_handler_33, 0x8, 0x8e); + idt_set_entry(34, (uint32_t)(uintptr_t)&int_handler_34, 0x8, 0x8e); + idt_set_entry(35, (uint32_t)(uintptr_t)&int_handler_35, 0x8, 0x8e); + idt_set_entry(36, (uint32_t)(uintptr_t)&int_handler_36, 0x8, 0x8e); + idt_set_entry(37, (uint32_t)(uintptr_t)&int_handler_37, 0x8, 0x8e); + idt_set_entry(38, (uint32_t)(uintptr_t)&int_handler_38, 0x8, 0x8e); + idt_set_entry(39, (uint32_t)(uintptr_t)&int_handler_39, 0x8, 0x8e); + idt_set_entry(40, (uint32_t)(uintptr_t)&int_handler_40, 0x8, 0x8e); + idt_set_entry(41, (uint32_t)(uintptr_t)&int_handler_41, 0x8, 0x8e); + idt_set_entry(42, (uint32_t)(uintptr_t)&int_handler_42, 0x8, 0x8e); + idt_set_entry(43, (uint32_t)(uintptr_t)&int_handler_43, 0x8, 0x8e); + idt_set_entry(44, (uint32_t)(uintptr_t)&int_handler_44, 0x8, 0x8e); + idt_set_entry(45, (uint32_t)(uintptr_t)&int_handler_45, 0x8, 0x8e); + idt_set_entry(46, (uint32_t)(uintptr_t)&int_handler_46, 0x8, 0x8e); + idt_set_entry(47, (uint32_t)(uintptr_t)&int_handler_47, 0x8, 0x8e); + idt_set_entry(48, (uint32_t)(uintptr_t)&int_handler_48, 0x8, 0x8e); + idt_set_entry(49, (uint32_t)(uintptr_t)&int_handler_49, 0x8, 0x8e); + idt_set_entry(50, (uint32_t)(uintptr_t)&int_handler_50, 0x8, 0x8e); + idt_set_entry(51, (uint32_t)(uintptr_t)&int_handler_51, 0x8, 0x8e); + idt_set_entry(52, (uint32_t)(uintptr_t)&int_handler_52, 0x8, 0x8e); + idt_set_entry(53, (uint32_t)(uintptr_t)&int_handler_53, 0x8, 0x8e); + idt_set_entry(54, (uint32_t)(uintptr_t)&int_handler_54, 0x8, 0x8e); + idt_set_entry(55, (uint32_t)(uintptr_t)&int_handler_55, 0x8, 0x8e); + idt_set_entry(56, (uint32_t)(uintptr_t)&int_handler_56, 0x8, 0x8e); + idt_set_entry(57, (uint32_t)(uintptr_t)&int_handler_57, 0x8, 0x8e); + idt_set_entry(58, (uint32_t)(uintptr_t)&int_handler_58, 0x8, 0x8e); + idt_set_entry(59, (uint32_t)(uintptr_t)&int_handler_59, 0x8, 0x8e); + idt_set_entry(60, (uint32_t)(uintptr_t)&int_handler_60, 0x8, 0x8e); + idt_set_entry(61, (uint32_t)(uintptr_t)&int_handler_61, 0x8, 0x8e); + idt_set_entry(62, (uint32_t)(uintptr_t)&int_handler_62, 0x8, 0x8e); + idt_set_entry(63, (uint32_t)(uintptr_t)&int_handler_63, 0x8, 0x8e); + idt_set_entry(64, (uint32_t)(uintptr_t)&int_handler_64, 0x8, 0x8e); + idt_set_entry(65, (uint32_t)(uintptr_t)&int_handler_65, 0x8, 0x8e); + idt_set_entry(66, (uint32_t)(uintptr_t)&int_handler_66, 0x8, 0x8e); + idt_set_entry(67, (uint32_t)(uintptr_t)&int_handler_67, 0x8, 0x8e); + idt_set_entry(68, (uint32_t)(uintptr_t)&int_handler_68, 0x8, 0x8e); + idt_set_entry(69, (uint32_t)(uintptr_t)&int_handler_69, 0x8, 0x8e); + idt_set_entry(70, (uint32_t)(uintptr_t)&int_handler_70, 0x8, 0x8e); + idt_set_entry(71, (uint32_t)(uintptr_t)&int_handler_71, 0x8, 0x8e); + idt_set_entry(72, (uint32_t)(uintptr_t)&int_handler_72, 0x8, 0x8e); + idt_set_entry(73, (uint32_t)(uintptr_t)&int_handler_73, 0x8, 0x8e); + idt_set_entry(74, (uint32_t)(uintptr_t)&int_handler_74, 0x8, 0x8e); + idt_set_entry(75, (uint32_t)(uintptr_t)&int_handler_75, 0x8, 0x8e); + idt_set_entry(76, (uint32_t)(uintptr_t)&int_handler_76, 0x8, 0x8e); + idt_set_entry(77, (uint32_t)(uintptr_t)&int_handler_77, 0x8, 0x8e); + idt_set_entry(78, (uint32_t)(uintptr_t)&int_handler_78, 0x8, 0x8e); + idt_set_entry(79, (uint32_t)(uintptr_t)&int_handler_79, 0x8, 0x8e); + idt_set_entry(80, (uint32_t)(uintptr_t)&int_handler_80, 0x8, 0x8e); + idt_set_entry(81, (uint32_t)(uintptr_t)&int_handler_81, 0x8, 0x8e); + idt_set_entry(82, (uint32_t)(uintptr_t)&int_handler_82, 0x8, 0x8e); + idt_set_entry(83, (uint32_t)(uintptr_t)&int_handler_83, 0x8, 0x8e); + idt_set_entry(84, (uint32_t)(uintptr_t)&int_handler_84, 0x8, 0x8e); + idt_set_entry(85, (uint32_t)(uintptr_t)&int_handler_85, 0x8, 0x8e); + idt_set_entry(86, (uint32_t)(uintptr_t)&int_handler_86, 0x8, 0x8e); + idt_set_entry(87, (uint32_t)(uintptr_t)&int_handler_87, 0x8, 0x8e); + idt_set_entry(88, (uint32_t)(uintptr_t)&int_handler_88, 0x8, 0x8e); + idt_set_entry(89, (uint32_t)(uintptr_t)&int_handler_89, 0x8, 0x8e); + idt_set_entry(90, (uint32_t)(uintptr_t)&int_handler_90, 0x8, 0x8e); + idt_set_entry(91, (uint32_t)(uintptr_t)&int_handler_91, 0x8, 0x8e); + idt_set_entry(92, (uint32_t)(uintptr_t)&int_handler_92, 0x8, 0x8e); + idt_set_entry(93, (uint32_t)(uintptr_t)&int_handler_93, 0x8, 0x8e); + idt_set_entry(94, (uint32_t)(uintptr_t)&int_handler_94, 0x8, 0x8e); + idt_set_entry(95, (uint32_t)(uintptr_t)&int_handler_95, 0x8, 0x8e); + idt_set_entry(96, (uint32_t)(uintptr_t)&int_handler_96, 0x8, 0x8e); + idt_set_entry(97, (uint32_t)(uintptr_t)&int_handler_97, 0x8, 0x8e); + idt_set_entry(98, (uint32_t)(uintptr_t)&int_handler_98, 0x8, 0x8e); + for (int i = 99; i < IDT_ENTRIES; i++) { + idt_set_entry(i, (uint32_t)(uintptr_t)&int_handler_99, 0x8, 0x8e); } - asm volatile("lidt (%0)" :: "m"(idt_desc)); + asm volatile("xchg %bx, %bx"); asm volatile("sti"); } diff --git a/arch/x86/pic.c b/arch/x86/pic.c @@ -0,0 +1,34 @@ +#include <arch/x86/io.h> + +#define PIC1_CMD 0x20 +#define PIC1_DATA 0x21 +#define PIC2_CMD 0xA0 +#define PIC2_DATA 0xA1 + +#define ICW1 0x11 // ICW1 initialize and ICW4 is needed, cascading + // 8 byte interrupts vectors +#define ICW4 0x01 // x86 architecture, normal EOI, not buffered, sequential + +void pic_init(int pic1_pos, int pic2_pos) { + unsigned char a1, a2; + + // save masks + a1 = inb(PIC1_DATA); + a2 = inb(PIC2_DATA); + + outb(PIC1_CMD, ICW1); + outb(PIC2_CMD, ICW1); + + outb(PIC1_DATA, pic1_pos); + outb(PIC2_DATA, pic2_pos); + + outb(PIC1_DATA, 4); // Master PIC: There is a slave at IRQ2 (0000 0100) + outb(PIC2_DATA, 2); // Slave PIC: cascade identity 0000 0010 + + outb(PIC1_DATA, ICW4); + outb(PIC2_DATA, ICW4); + + // restore saved masks + outb(PIC1_DATA, a1); + outb(PIC2_DATA, a2); +} diff --git a/arch/x86/pic.h b/arch/x86/pic.h @@ -0,0 +1,6 @@ +#ifndef PIC_H +#define PIC_H + +void pic_init(); + +#endif diff --git a/drivers/hid/keyboard/keyboard.c b/drivers/hid/keyboard/keyboard.c @@ -0,0 +1,92 @@ +// This file contains general functions that are used as an interface +// to other parts of the kernel and to user space programs, and are used +// by all keyboard drivers (e.g. PS2 and others) the same + +#include "keyboard.h" + +static int keyboard_callbacks_pos = 0; +static void (*keyboard_callbacks[MAX_CALLBACK_COUNT])(struct keyboard_event); + +// TODO: As long as we cannot allocate memory dynamically, use fixed one +static struct keyboard_event kbd_event; + +static bool shift_active = false; + +static bool keycode_is_printable[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, + + 0 ,0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 0 +}; + +static char keycode_to_char[256] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o' ,'p', 'a', 's', 'd', 'f', + 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', + + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + + ',', '.', '/', '\\', '\'', ';', '-', '=', ' ', ' ', ' ', '\t', ' ', + + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ']', '[', ' ', ' ', ' ', + + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '*', '+', '.', + + ' ' +}; + +static char keycode_to_char_shift[256] = { + '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O' ,'P', 'A', 'S', 'D', 'F', + 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', + + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + + '<', '>', '?', '|', '"', ':', '_', '+', ' ', ' ', ' ', '\t', ' ', + + ' ', ' ', ' ', ' ', ' ', ' ', ' ', '}', '{', ' ', ' ', ' ', + + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '*', '+', '.', + + ' ' +}; + +void keyboard_add_callback(void (*callback)(struct keyboard_event)) { + keyboard_callbacks[keyboard_callbacks_pos] = callback; + keyboard_callbacks_pos++; +} + +void keyboard_fire_event(enum keyboard_key kbdkey, bool released) { + if (kbdkey == KEY_LSHIFT || kbdkey == KEY_RSHIFT) { + shift_active = !released; + } + + kbd_event.key = kbdkey; + kbd_event.released = released; + + // TODO: We should make sure that they always match? + if (kbdkey < 256) { + kbd_event.printable = keycode_is_printable[kbdkey]; + + if (shift_active) { + kbd_event.ascii = keycode_to_char_shift[kbdkey]; + } else { + kbd_event.ascii = keycode_to_char[kbdkey]; + } + } + + for (int i = 0; i < keyboard_callbacks_pos; i++) { + keyboard_callbacks[i](kbd_event); + } +} diff --git a/drivers/hid/keyboard/keyboard.h b/drivers/hid/keyboard/keyboard.h @@ -0,0 +1,55 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include <stdbool.h> + +#define MAX_CALLBACK_COUNT 256 + +// TODO: Switch to #define instead of enum, so that we can define +// bits individually and restrict to required length (8 bits) +// currently it's int always +enum keyboard_key { + KEY_1 = 0, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, + + KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, + KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_A, KEY_S, KEY_D, + KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_Z, KEY_X, + KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, + + KEY_F1, KEY_F2, KEY_F3, + KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, + KEY_F12, + + KEY_COMMA, KEY_DOT, KEY_SLASH, + KEY_BACKSLASH, KEY_APOSTROPHE, KEY_SEMICOLON, KEY_MINUS, KEY_EQUALS, + KEY_BACKSPACE, KEY_SPACE, KEY_ENTER, KEY_TAB, KEY_ESC, + + KEY_LSHIFT, KEY_RSHIFT, KEY_ALT, KEY_ALTGR, KEY_LCTRL, + KEY_RCTRL, KEY_BACKTICK, KEY_RSQ_BRACKET, KEY_LSQ_BRACKET, + KEY_CAPSLOCK, KEY_NUMLOCK, KEY_SCROLLLOCK, + + KEY_0_KP, KEY_1_KP, KEY_2_KP, KEY_3_KP, KEY_4_KP, KEY_5_KP, KEY_6_KP, + KEY_7_KP, KEY_8_KP, KEY_9_KP, + KEY_MINUS_KP, KEY_TIMES_KP, KEY_PLUS_KP, KEY_DOT_KP, + + KEY_UNUSED +}; + +struct keyboard_event { + enum keyboard_key key; + bool released; // true if released event + char ascii; + bool printable; + // TODO: Add more useful fields + // some people have ctrl_pressed, shift_pressed, and stuff here +}; + +void keyboard_init(); +void keyboard_irq_handler(); + +void keyboard_add_callback(void (*callback)(struct keyboard_event)); + +// TODO: This should only be callable for functions in keyboard folder +void keyboard_fire_event(enum keyboard_key kbdkey, bool released); + +#endif diff --git a/drivers/hid/keyboard/ps2.c b/drivers/hid/keyboard/ps2.c @@ -0,0 +1,152 @@ +#include <stdbool.h> +#include <stdint.h> +#include <arch/x86/io.h> +#include "keyboard.h" + +// Mapping table from scancode set 2 standard keys (not multimedia) +// to the key codes +static enum keyboard_key s2_keycodes[256] = { + KEY_UNUSED, KEY_F9, KEY_UNUSED, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, + KEY_UNUSED, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_UNUSED, + KEY_UNUSED, KEY_ALT, KEY_LSHIFT, KEY_UNUSED, KEY_LCTRL, KEY_Q, KEY_1, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_UNUSED, + KEY_UNUSED, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_UNUSED, + KEY_UNUSED, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_UNUSED, + KEY_UNUSED, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_UNUSED, + KEY_UNUSED, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_UNUSED, + KEY_UNUSED, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_APOSTROPHE, KEY_UNUSED, KEY_LSQ_BRACKET, KEY_EQUALS, KEY_UNUSED, KEY_UNUSED, + KEY_CAPSLOCK, KEY_RSHIFT, KEY_ENTER, KEY_RSQ_BRACKET, KEY_UNUSED, KEY_BACKSLASH, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_BACKSPACE, KEY_UNUSED, KEY_UNUSED, KEY_1_KP, KEY_UNUSED, KEY_4_KP, + KEY_7_KP, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_0_KP, KEY_DOT_KP, KEY_2_KP, KEY_5_KP, + KEY_6_KP, KEY_8_KP, KEY_ESC, KEY_NUMLOCK, KEY_F11, KEY_PLUS_KP, KEY_3_KP, KEY_MINUS_KP, + KEY_TIMES_KP, KEY_9_KP, KEY_SCROLLLOCK, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_F7 +}; + +// All possible states for our keycode finite state machine +static void fsm_start(uint8_t); +static void fsm_release(uint8_t); +static void fsm_multimedia(uint8_t); +static void fsm_multimedia_release(uint8_t); +static void fsm_print_1(uint8_t); +static void fsm_print_2(uint8_t); +static void kbd_wait_outbuf(); +static void set_scancode(uint8_t); + + +// FSM: Keep track of the current state of the state machine +static void (*current_state)(uint8_t) = fsm_start; + +// The state machine start states for each scancode set +// TODO: Currently scancode set 1 and 3 are missing and will trigger +// a fault interrupt +static void (*scancode_state_starts[3])(uint8_t) = { 0x0, fsm_start, 0x0 }; + +void keyboard_init() { + set_scancode(2); +} + +void keyboard_irq_handler() { + uint8_t scancode; + + kbd_wait_outbuf(); + scancode = inb(0x60); + current_state(scancode); +} + +// Methods for waiting for keyboard +static void kbd_wait_outbuf() { + // TODO: Can we add some idle loops or is kbd controller so fast? + uint8_t status; + do { + status = inb(0x64); + } while ((status & 0x1) == 0); +} + +static void kbd_wait_inbuf() { + // TODO: Can we add some idle loops or is kbd controller so fast? + uint8_t status; + do { + status = inb(0x64); + } while ((status & 0x2) != 0); +} + +static void set_scancode(uint8_t scancode_nr) { + if (scancode_nr < 1 || scancode_nr > 3) + return; + + outb(0x60, 0xf0); + kbd_wait_inbuf(); + outb(0x60, scancode_nr); + kbd_wait_inbuf(); + + // disable translation + outb(0x64, 0x20); + kbd_wait_outbuf(); + uint8_t status = inb(0x60); + + kbd_wait_inbuf(); + outb(0x64, 0x60); + kbd_wait_inbuf(); + outb(0x60, status & 0x3f); + + current_state = scancode_state_starts[scancode_nr - 1]; +} + +// FSM function implementation +// These functions read scancodes and jump to correct next function +static void fsm_start(uint8_t byte) { + if (byte == 0xe0) { + current_state = fsm_multimedia; + } else if (byte == 0xf0) { + current_state = fsm_release; + } else { + if (s2_keycodes[byte] != KEY_UNUSED) { + keyboard_fire_event(s2_keycodes[byte], false); + } + } +} + +static void fsm_multimedia(uint8_t byte) { + if (byte == 0xf0) { + current_state = fsm_multimedia_release; + } else if (byte == 0x12) { + current_state = fsm_print_1; + } else { + // TODO: multimedia key byte pressed + current_state = fsm_start; + } +} + +static void fsm_release(uint8_t byte) { + if (s2_keycodes[byte] != KEY_UNUSED) { + keyboard_fire_event(s2_keycodes[byte], true); + } + + current_state = fsm_start; +} + +static void fsm_multimedia_release(uint8_t byte) { + char *vidmem = (char*) 0xb8000; + vidmem[0] = 'x'; + // TODO: Multimedia key byte released + current_state = fsm_start; +} + +static void fsm_print_1(uint8_t byte) { + if (byte == 0xe0) { + current_state = fsm_print_2; + } else { + // TODO: Failure + } +} + +static void fsm_print_2(uint8_t byte) { + if (byte == 0x7c) { + // TODO key = PRINT pressed + current_state = fsm_start; + } else { + // TODO: Failure + } +} diff --git a/include/arch/x86/io.c b/include/arch/x86/io.c @@ -0,0 +1,76 @@ +#include "io.h" +#include "math.h" + +static uint16_t curpos = 0; + +static void shift_screen_up() { + char *vidmem = (char*)0xb8000; + + // Move existing lines one row up + for (int line = 1; line < VIDEO_SCREEN_HEIGHT; line++) { + for (int line_byte = 0; line_byte < 2 * VIDEO_SCREEN_WIDTH; line_byte++) { + int offset = 2 * VIDEO_SCREEN_WIDTH * line + line_byte; + + vidmem[offset - 2 * VIDEO_SCREEN_WIDTH] = vidmem[offset]; + } + } + // Reset text on "new" line + for (int col = 0; col < VIDEO_SCREEN_WIDTH; col++) { + int offset = 2 * VIDEO_SCREEN_WIDTH * (VIDEO_SCREEN_HEIGHT - 1) + 2 * col; + + vidmem[offset] = ' '; + } + // Reset colors on "new" line + for (int col = 0; col < VIDEO_SCREEN_WIDTH; col++) { + int offset = 2 * VIDEO_SCREEN_WIDTH * (VIDEO_SCREEN_HEIGHT - 1) + 2 * col + 1; + + vidmem[offset] = 0xf; + } + + curpos -= VIDEO_SCREEN_WIDTH; +} + +static void increment_cursor() { + curpos++; + + if (curpos >= VIDEO_SCREEN_WIDTH * VIDEO_SCREEN_HEIGHT) { + shift_screen_up(); + } +} + +void kprint(char *str) { + for (int i = 0; str[i] != 0; i++) { + kprintc(str[i]); + } +} + +void kprintc(char c) { + char *vidmem = (char*)VIDMEM; + vidmem[2*curpos] = c; + vidmem[2*curpos + 1] = 0x9; + + increment_cursor(); +} + +static short no_of_digits(int value) { + short len = 0; + int tmp = 1; + + while (tmp < value) { + len++; + tmp = (tmp << 3) + (tmp << 1); + } + + return len; +} + +void kprinti(int value) { + short digits = no_of_digits(value); + + int divisor = (int)power(10, digits - 1); + for (int i = divisor; i > 0; i /= 10) { + short digit = value / i; + value %= i; + kprintc((char)(digit + 48)); + } +} diff --git a/include/arch/x86/io.h b/include/arch/x86/io.h @@ -0,0 +1,30 @@ +#ifndef IO_H +#define IO_H + +#include <stdint.h> + +#define VIDMEM 0xb8000 +#define VIDEO_SCREEN_WIDTH 80 +#define VIDEO_SCREEN_HEIGHT 25 + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outb(uint16_t port, uint8_t value) { + asm volatile("outb %0, %1" :: "a"(value), "Nd"(port)); +} + +static inline void io_wait() { + asm volatile("outb %%al, $0x80" :: "a"(0)); +} + +void kprint(char *str); + +void kprintc(char c); + +void kprinti(int value); + +#endif diff --git a/include/arch/x86/math.c b/include/arch/x86/math.c @@ -0,0 +1,8 @@ +long power(long number, int power) { + long tmp = number; + for (int i = 1; i < power; i++) { + tmp *= number; + } + + return tmp; +} diff --git a/include/arch/x86/math.h b/include/arch/x86/math.h @@ -0,0 +1 @@ +long power(long number, int power);