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:
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);