diff --git a/Makefile b/Makefile
index 4611669..aa43673 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc
CPP = ${HOME}/opt/cross/bin/i686-elf-g++
CFLAGS = -ffreestanding -O2 -Wall -Wextra
-OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o
+OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o
SRC_DIR = src
BUILD_DIR = build
@@ -24,7 +24,7 @@ all: clean build
build: build_kernel run
run:
- $(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio
+ $(EMULATOR) -d int -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std
build_kernel: $(OBJ_LINK_LIST)
@@ -55,5 +55,12 @@ $(BUILD_DIR)/crtn.o:
$(BUILD_DIR)/io.o:
$(CPP) -c $(SRC_DIR)/kernel/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti
+
$(BUILD_DIR)/MMU.o:
- $(CPP) -c $(SRC_DIR)/kernel/MMU.cpp -o $(BUILD_DIR)/MMU.o $(CFLAGS) -fno-exceptions -fno-rtti
\ No newline at end of file
+ $(CPP) -c $(SRC_DIR)/kernel/MMU.cpp -o $(BUILD_DIR)/MMU.o $(CFLAGS) -fno-exceptions -fno-rtti
+
+$(BUILD_DIR)/idt.o:
+ $(CPP) -c $(SRC_DIR)/kernel/arch/i386/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti
+
+$(BUILD_DIR)/pic.o:
+ $(CPP) -c $(SRC_DIR)/kernel/arch/i386/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti
diff --git a/README.md b/README.md
index 5383904..6aa56a7 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,9 @@ ________________________
The first scrolling boot screen. 😲
+
+W.I.P - Working on interrupt handling
+
________________________
### The goal
diff --git a/screenshots/Screenshot from 2021-06-21 14-26-39.png b/screenshots/Screenshot from 2021-06-21 14-26-39.png
new file mode 100644
index 0000000..30c104f
--- /dev/null
+++ b/screenshots/Screenshot from 2021-06-21 14-26-39.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:73b9d3ed540e1bc0b6d55114a00f9aa688006b38a542c1bf048d90b791a748ce
+size 141605
diff --git a/screenshots/WIP_interruptHandling.png b/screenshots/WIP_interruptHandling.png
new file mode 100644
index 0000000..6c22b50
--- /dev/null
+++ b/screenshots/WIP_interruptHandling.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bfbde3cc43610681eca3f38e56d8af1d0e5d0ad2f465cb743a5b8ea5c3adbe47
+size 16282
diff --git a/src/kernel/arch/i386/boot.s b/src/kernel/arch/i386/boot.s
index 99fa270..2de2f8d 100644
--- a/src/kernel/arch/i386/boot.s
+++ b/src/kernel/arch/i386/boot.s
@@ -20,10 +20,430 @@ stack_bottom:
.skip 16384 # 16 KiB
stack_top:
+.section .text
+
+/*
+* Interupt handlers
+*/
+# NOTE: I have no clue how I should use these macros.
+# Have tried to use them in a myriad of ways, none would actually work
+.macro irs_NoErrCode code:req
+ .globl irs\code
+ irs\code:
+ cli
+ pushb $0
+ pushb \code
+ jmp irs_common
+.endm
+
+.macro irs_ErrCode code
+ .globl irs\code
+ irs\code:
+ cli
+ pushb \code
+ jmp irs_common
+.endm
+
+.globl irs0
+irs0:
+ cli
+ push $0
+ push $0
+ jmp irs_common
+
+.globl irs1
+irs1:
+ cli
+ push $0
+ push $1
+ jmp irs_common
+
+.globl irs2
+irs2:
+ cli
+ push $0
+ push $2
+ jmp irs_common
+
+.globl irs3
+irs3:
+ cli
+ push $0
+ push $3
+ jmp irs_common
+
+.globl irs4
+irs4:
+ cli
+ push $0
+ push $4
+ jmp irs_common
+
+.globl irs5
+irs5:
+ cli
+ push $0
+ push $5
+ jmp irs_common
+
+.globl irs6
+irs6:
+ cli
+ push $0
+ push $6
+ jmp irs_common
+
+.globl irs7
+irs7:
+ cli
+ push $0
+ push $7
+ jmp irs_common
+
+.globl irs8
+irs8:
+ cli
+ push $0
+ push $8
+ jmp irs_common
+
+.globl irs9
+irs9:
+ cli
+ push $0
+ push $9
+ jmp irs_common
+
+.globl irs10
+irs10:
+ cli
+ push $0
+ push $10
+ jmp irs_common
+
+.globl irs11
+irs11:
+ cli
+ push $0
+ push $11
+ jmp irs_common
+
+.globl irs12
+irs12:
+ cli
+ push $0
+ push $12
+ jmp irs_common
+
+.globl irs13
+irs13:
+ cli
+ push $13
+ jmp irs_common
+
+.globl irs14
+irs14:
+ cli
+ push $0
+ push $14
+ jmp irs_common
+
+.globl irs15
+irs15:
+ cli
+ push $0
+ push $15
+ jmp irs_common
+
+.globl irs16
+irs16:
+ cli
+ push $0
+ push $16
+ jmp irs_common
+
+.globl irs17
+irs17:
+ cli
+ push $0
+ push $17
+ jmp irs_common
+
+.globl irs18
+irs18:
+ cli
+ push $0
+ push $18
+ jmp irs_common
+
+.globl irs19
+irs19:
+ cli
+ push $0
+ push $19
+ jmp irs_common
+
+.globl irs20
+irs20:
+ cli
+ push $0
+ push $20
+ jmp irs_common
+
+.globl irs21
+irs21:
+ cli
+ push $0
+ push $21
+ jmp irs_common
+
+.globl irs22
+irs22:
+ cli
+ push $0
+ push $22
+ jmp irs_common
+
+.globl irs23
+irs23:
+ cli
+ push $0
+ push $23
+ jmp irs_common
+
+.globl irs24
+irs24:
+ cli
+ push $0
+ push $24
+ jmp irs_common
+
+.globl irs25
+irs25:
+ cli
+ push $0
+ push $25
+ jmp irs_common
+
+.globl irs26
+irs26:
+ cli
+ push $0
+ push $26
+ jmp irs_common
+
+.globl irs27
+irs27:
+ cli
+ push $0
+ push $27
+ jmp irs_common
+
+.globl irs28
+irs28:
+ cli
+ push $0
+ push $28
+ jmp irs_common
+
+.globl irs29
+irs29:
+ cli
+ push $0
+ push $29
+ jmp irs_common
+
+.globl irs30
+irs30:
+ cli
+ push $0
+ push $30
+ jmp irs_common
+
+.globl irs31
+irs31:
+ cli
+ push $0
+ push $31
+ jmp irs_common
-.text
+.globl irq0
+irq0:
+ cli
+ push $0
+ push $0
+ jmp irq_common
+
+.globl irq1
+irq1:
+ cli
+ push $0
+ push $1
+ jmp irq_common
+
+.globl irq2
+irq2:
+ cli
+ push $0
+ push $2
+ jmp irq_common
+
+.globl irq3
+irq3:
+ cli
+ push $0
+ push $3
+ jmp irq_common
+
+.globl irq4
+irq4:
+ cli
+ push $0
+ push $4
+ jmp irq_common
+
+.globl irq5
+irq5:
+ cli
+ push $0
+ push $5
+ jmp irq_common
+
+.globl irq6
+irq6:
+ cli
+ push $0
+ push $6
+ jmp irq_common
+
+.globl irq7
+irq7:
+ cli
+ push $0
+ push $7
+ jmp irq_common
+
+.globl irq8
+irq8:
+ cli
+ push $0
+ push $8
+ jmp irq_common
+
+.globl irq9
+irq9:
+ cli
+ push $0
+ push $9
+ jmp irq_common
+
+.globl irq10
+irq10:
+ cli
+ push $0
+ push $10
+ jmp irq_common
+
+.globl irq11
+irq11:
+ cli
+ push $0
+ push $11
+ jmp irq_common
+
+
+.globl irq12
+irq12:
+ cli
+ push $0
+ push $12
+ jmp irq_common
+
+.globl irq13
+irq13:
+ cli
+ push $0
+ push $13
+ jmp irq_common
+
+.globl irq14
+irq14:
+ cli
+ push $0
+ push $14
+ jmp irq_common
+
+.globl irq15
+irq15:
+ cli
+ push $0
+ push $15
+ jmp irq_common
+
+irq_common:
+ pusha
+
+ mov %ds, %ax
+ push %eax
+
+ mov $0x10, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ call irq_handler
+
+ pop %eax
+
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ popa
+ add $8, %esp # cleans push error and irs code
+ sti
+ iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
+
+
+irs_common:
+ pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
+
+
+ mov %ds, %ax
+ push %eax
+
+ /* load the kernel data segment descriptor*/
+
+ mov $0x10, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ call irs_handler
+
+ pop %eax
+
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ popa
+ add $8, %esp # cleans push error and irs code
+ sti
+ iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
+
+.globl idt_flush
+idt_flush:
+ mov 4(%esp), %eax
+ lidt (%eax)
+ ret
+
.globl enablePaging
enablePaging:
push %ebp
@@ -35,7 +455,6 @@ enablePaging:
pop %ebp
ret
-.text
.globl loadPageDirectory
loadPageDirectory:
push %ebp
@@ -46,25 +465,91 @@ loadPageDirectory:
pop %ebp
ret
-
-.section .text
.global _start
.type _start, @function
_start:
-
-
-
+ /*Setup the stack pointer to point to the beginning of our stack */
+ /* I believe its a hight address growing down to lower adress for the stack on x86*/
mov $stack_top, %esp
-
-
-
- call _init
- call kernel_main
-
-
+ call early_main
cli
-1: hlt
- jmp 1b
-
+ load_gdt:
+ lgdt gdt
-.size _start, . - _start
\ No newline at end of file
+ # set the segment selecters
+
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ ljmp $0x08, $flush
+
+ flush:
+
+
+ #load idt
+ call init_idt
+ sti
+
+ # Try enable A20
+ # mov $0x2401, %ax
+ # int $0x15
+
+
+ # enable protected mode
+ mov %cr0, %eax
+ or $1, %eax
+ mov %eax, %cr0
+
+
+ call kernel_main
+
+
+ cli
+ 1: hlt
+ jmp 1b
+
+
+
+
+ /* Tell processor to use our gdt*/
+ gdt:
+ .word (gdt_end - gdt_start -1) # Size of the GDT in bytes minus 1 for math reasons
+ .int gdt_start # linear address of our GDT
+
+
+
+
+.att_syntax
+
+
+.size _start, . - _start
+
+
+/*
+* Create the GDT
+*/
+.section .data
+gdt_start:
+gdt_null:
+.long 0x0
+.long 0x0
+
+gdt_kcode:
+.word 0xFFFF # limit
+.word 0x0 # base
+.byte 0x0 # base
+.byte 0b10011010 # 1st flags | type flags
+.byte 0b11001111 # 2nd flags | limit
+.byte 0x0 # base
+
+gdt_kdata:
+.word 0xFFFF # limit
+.word 0x0 # base
+.byte 0x0 # base
+.byte 0b10010010 # 1st flags | type flags
+.byte 0b11001111 # 2nd flags | limit
+.byte 0x0 # base
+gdt_end:
\ No newline at end of file
diff --git a/src/kernel/arch/i386/gdt/gdtc.cpp b/src/kernel/arch/i386/gdt/gdtc.cpp
new file mode 100644
index 0000000..f21e80f
--- /dev/null
+++ b/src/kernel/arch/i386/gdt/gdtc.cpp
@@ -0,0 +1,29 @@
+#include "gdtc.h"
+
+
+gdtEntry_t gdt[3];
+
+
+void gdtSetGate(int num, uint64_t base, uint64_t limit, uint8_t access,
+ uint8_t gran){
+ gdt[num].lBase = (base & 0xFFFF);
+ gdt[num].mBase = (base >> 16) & 0xFF;
+ gdt[num].hBase = (base >> 24) & 0xFF;
+
+ gdt[num].lLimit = (limit & 0xFFFF);
+ gdt[num].granularity = ((limit >> 16) & 0x0F);
+
+ gdt[num].granularity |= (gran & 0xF0);
+ gdt[num].access = access;
+}
+
+void setupGdt(){
+ gdtPointer.limit = (sizeof(gdtEntry_t) * 3) - 1;
+ gdtPointer.base = &gdt;
+
+ gdtSetGate(0, 0, 0, 0, 0);
+ gdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
+ gdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+
+ loadGdt();
+}
diff --git a/src/kernel/arch/i386/gdt/gdtc.h b/src/kernel/arch/i386/gdt/gdtc.h
new file mode 100644
index 0000000..2b34997
--- /dev/null
+++ b/src/kernel/arch/i386/gdt/gdtc.h
@@ -0,0 +1,20 @@
+#include
+extern "c"{
+
+typedef struct {
+ uint16_t lLimit;
+ uint16_t lBase;
+ uint8_t mBase;
+ uint8_t access;
+ uint8_t granularity;
+ uint8_t hBase;
+} gdtEntry_t;
+
+struct {
+ uint16_t limit;
+ uint32_t base;
+} gdtPointer;
+
+extern void loadGdt();
+void setupGdt();
+}
\ No newline at end of file
diff --git a/src/kernel/arch/i386/idt/idt.cpp b/src/kernel/arch/i386/idt/idt.cpp
new file mode 100644
index 0000000..4722109
--- /dev/null
+++ b/src/kernel/arch/i386/idt/idt.cpp
@@ -0,0 +1,146 @@
+#include "idt.h"
+//#include "scancodes/set1.h"
+
+IDT_entry idt_table[256];
+IDT_ptr idt_ptr;
+
+void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){
+ idt_table[num].offset_1 = base & 0xFFFF;
+ idt_table[num].selector = sel;
+ idt_table[num].zero = 0;
+ idt_table[num].type_attr = flags;
+ idt_table[num].offset_2 = (base >> 16) & 0xFFFF;
+
+};
+
+
+void irs_handler (registers regs) {
+ kterm_writestring("received interrupt!\n");
+
+ printf("(IRS) Interrupt number: %d \n", regs.int_no);
+
+ if( regs.int_no == 13){
+ printf(" Error code: %d \n", regs.err_code);
+
+ }
+
+}
+
+
+
+void irq_handler (registers regs) {
+
+
+ if ( regs.int_no != 0) {
+ kterm_writestring("received interrupt!\n");
+ printf("(IRQ) Interrupt number: %d \n", regs.int_no);
+
+ }
+
+ if ( regs.int_no == 1 ){
+ // Keyboard interrupt !!
+
+ int scan;
+ register int i;
+
+ // Read scancode
+
+ scan = inb(0x60);
+
+ // Send ack message!
+ i = inb(0x61);
+ outb(0x61, i|0x80);
+ outb(0x61, i);
+ kterm_writestring("A key was pressed/released\n");
+ printf( "Scancode: %x\n", scan);
+
+
+ }
+
+
+
+ outb(0x20, 0x20); // send end of interrupt to master
+
+ if ( regs.int_no > 8 && regs.int_no <= 15) {
+ outb(0xA0, 0x20); // send end of interrupt to slave
+ }
+
+
+ if( regs.int_no == 13){
+ printf(" Error code: %d \n", regs.err_code);
+
+ }
+
+}
+
+
+
+
+
+void init_idt(){
+ // Initialise the IDT pointer
+ idt_ptr.length = sizeof(IDT_entry) * 255;
+ idt_ptr.base = (uint32_t)&idt_table;
+
+
+ // TODO: Set everything to zero first
+
+ set_id_entry(0, (uint32_t) irs0 , 0x08, 0x8F);
+ set_id_entry(1, (uint32_t) irs1 , 0x08, 0x8E);
+ set_id_entry(2, (uint32_t) irs2 , 0x08, 0x8E);
+ set_id_entry(3, (uint32_t) irs3 , 0x08, 0x8E);
+ set_id_entry(4, (uint32_t) irs4 , 0x08, 0x8E);
+ set_id_entry(5, (uint32_t) irs5 , 0x08, 0x8E);
+ set_id_entry(6, (uint32_t) irs6 , 0x08, 0x8E);
+ set_id_entry(7, (uint32_t) irs7 , 0x08, 0x8E);
+ set_id_entry(8, (uint32_t) irs8 , 0x08, 0x8E);
+ set_id_entry(9, (uint32_t) irs9 , 0x08, 0x8E);
+ set_id_entry(10, (uint32_t) irs10 , 0x08, 0x8E);
+ set_id_entry(11, (uint32_t) irs11 , 0x08, 0x8E);
+ set_id_entry(12, (uint32_t) irs12 , 0x08, 0x8E);
+ set_id_entry(13, (uint32_t) irs13 , 0x08, 0x8E);
+ set_id_entry(14, (uint32_t) irs14 , 0x08, 0x8E);
+ set_id_entry(15, (uint32_t) irs15 , 0x08, 0x8E);
+ set_id_entry(16, (uint32_t) irs16 , 0x08, 0x8E);
+ set_id_entry(17, (uint32_t) irs17 , 0x08, 0x8E);
+ set_id_entry(18, (uint32_t) irs18 , 0x08, 0x8E);
+ set_id_entry(19, (uint32_t) irs19 , 0x08, 0x8E);
+ set_id_entry(20, (uint32_t) irs20 , 0x08, 0x8E);
+ set_id_entry(21, (uint32_t) irs21 , 0x08, 0x8E);
+ set_id_entry(22, (uint32_t) irs22 , 0x08, 0x8E);
+ set_id_entry(23, (uint32_t) irs23 , 0x08, 0x8E);
+ set_id_entry(24, (uint32_t) irs24 , 0x08, 0x8E);
+ set_id_entry(25, (uint32_t) irs25 , 0x08, 0x8E);
+ set_id_entry(26, (uint32_t) irs26 , 0x08, 0x8E);
+ set_id_entry(27, (uint32_t) irs27 , 0x08, 0x8E);
+ set_id_entry(28, (uint32_t) irs28 , 0x08, 0x8E);
+ set_id_entry(29, (uint32_t) irs29 , 0x08, 0x8E);
+ set_id_entry(30, (uint32_t) irs30 , 0x08, 0x8E);
+ set_id_entry(31, (uint32_t) irs31 , 0x08, 0x8E);
+
+
+ //print_serial("Remapping PIC\n");
+ PIC_remap(0x20, 0x28);
+
+
+ // pic IRQ Table
+ set_id_entry(32, (uint32_t)irq0, 0x08, 0x8E);
+ set_id_entry(33, (uint32_t)irq1, 0x08, 0x8E);
+ set_id_entry(34, (uint32_t)irq2, 0x08, 0x8E);
+ set_id_entry(35, (uint32_t)irq3, 0x08, 0x8E);
+ set_id_entry(36, (uint32_t)irq4, 0x08, 0x8E);
+ set_id_entry(37, (uint32_t)irq5, 0x08, 0x8E);
+ set_id_entry(38, (uint32_t)irq6, 0x08, 0x8E);
+ set_id_entry(39, (uint32_t)irq7, 0x08, 0x8E);
+ set_id_entry(40, (uint32_t)irq8, 0x08, 0x8E);
+ set_id_entry(41, (uint32_t)irq9, 0x08, 0x8E);
+ set_id_entry(42, (uint32_t)irq10, 0x08, 0x8E);
+ set_id_entry(43, (uint32_t)irq11, 0x08, 0x8E);
+ set_id_entry(44, (uint32_t)irq12, 0x08, 0x8E);
+ set_id_entry(45, (uint32_t)irq13, 0x08, 0x8E);
+ set_id_entry(46, (uint32_t)irq14, 0x08, 0x8E);
+ set_id_entry(47, (uint32_t)irq15, 0x08, 0x8E);
+
+
+ idt_flush((uint32_t)&idt_ptr);
+}
diff --git a/src/kernel/arch/i386/idt/idt.h b/src/kernel/arch/i386/idt/idt.h
new file mode 100644
index 0000000..b616b85
--- /dev/null
+++ b/src/kernel/arch/i386/idt/idt.h
@@ -0,0 +1,80 @@
+#pragma once
+
+#include "stdint.h"
+#include "stddef.h"
+#include "../vga/colors.h"
+#include "../pic/pic.h"
+
+extern "C"{
+ #include "../tty/kterm.h"
+}
+#define AS_KERNEL() ( kterm_writestring("[KERNEL]:"))
+
+
+extern "C" {
+ struct __attribute__((__packed__)) IDT_entry {
+ uint16_t offset_1;
+ uint16_t selector;
+ uint8_t zero;
+ uint8_t type_attr;
+ uint16_t offset_2;
+ };
+
+ struct __attribute__((__packed__)) IDT_ptr {
+ unsigned short length;
+ unsigned long base;
+ };
+
+ struct registers {
+ uint32_t ds; // Data segment selector
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
+ uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
+ uint32_t eip, cs, eflags, useresp, ss;
+ };
+
+
+ extern void idt_flush(uint32_t);
+ void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags);
+ void init_idt();
+
+ void irq_handler (registers regs);
+
+ void irs_handler (registers regs);
+
+ extern void irs0 ();
+ extern void irs1 ();
+ extern void irs2 ();
+ extern void irs3 ();
+ extern void irs4 ();
+ extern void irs5 ();
+ extern void irs6 ();
+ extern void irs7 ();
+ extern void irs8 ();
+ extern void irs9 ();
+ extern void irs10 ();
+ extern void irs11 ();
+ extern void irs12 ();
+ extern void irs13 ();
+ extern void irs14 ();
+ extern void irs15 ();
+ extern void irs16 ();
+ extern void irs17 ();
+ extern void irs18 ();
+ extern void irs19 ();
+ extern void irs20 ();
+ extern void irs21 ();
+ extern void irs22 ();
+ extern void irs23 ();
+ extern void irs24 ();
+ extern void irs25 ();
+ extern void irs26 ();
+ extern void irs27 ();
+ extern void irs28 ();
+ extern void irs29 ();
+ extern void irs30 ();
+ extern void irs31 ();
+
+
+
+
+}
diff --git a/src/kernel/arch/i386/idt/scancodes/set1.h b/src/kernel/arch/i386/idt/scancodes/set1.h
new file mode 100644
index 0000000..2fe6b17
--- /dev/null
+++ b/src/kernel/arch/i386/idt/scancodes/set1.h
@@ -0,0 +1,184 @@
+#pragma once
+
+
+
+
+
+
+// ScanCode set 1
+int ScanCodeToKeyCode [0xD8];
+
+/* key pressed scancode */
+ScanCodeToKeyCode[0x01] = 4017; // escape pressed
+ScanCodeToKeyCode[0x02] = 4018; // 1 pressed
+ScanCodeToKeyCode[0x03] = 4019; // 2 pressed
+ScanCodeToKeyCode[0x04] = 4020; // 3 pressed
+ScanCodeToKeyCode[0x05] ="" // 4 pressed
+ScanCodeToKeyCode[0x06] ="" // 5 pressed
+ScanCodeToKeyCode[0x07] ="" // 6 pressed
+ScanCodeToKeyCode[0x08] ="" // 7 pressed
+ScanCodeToKeyCode[0x09] ="" // 8 pressed
+ScanCodeToKeyCode[0x0A] ="" // 9 pressed
+ScanCodeToKeyCode[0x0B] ="" // 0 (zero) pressed
+ScanCodeToKeyCode[0x0C] ="" // - pressed
+ScanCodeToKeyCode[0x0D] ="" // = pressed
+ScanCodeToKeyCode[0x0E] ="" // backspace pressed
+ScanCodeToKeyCode[0x0F] ="" // tab pressed
+ScanCodeToKeyCode[0x10] ="" // Q pressed
+ScanCodeToKeyCode[0x11] ="" // W pressed
+ScanCodeToKeyCode[0x12] ="" // E pressed
+ScanCodeToKeyCode[0x13] ="" // R pressed
+ScanCodeToKeyCode[0x14] ="" // T pressed
+ScanCodeToKeyCode[0x15] ="" // Y pressed
+ScanCodeToKeyCode[0x16] ="" // U pressed
+ScanCodeToKeyCode[0x17] ="" // I pressed
+ScanCodeToKeyCode[0x18] ="" // O pressed
+ScanCodeToKeyCode[0x19] ="" // P pressed
+ScanCodeToKeyCode[0x1A] ="" // [ pressed
+ScanCodeToKeyCode[0x1B] ="" // ] pressed
+ScanCodeToKeyCode[0x1C] ="" // enter pressed
+ScanCodeToKeyCode[0x1D] ="" // left control pressed
+ScanCodeToKeyCode[0x1E] ="" // A pressed
+ScanCodeToKeyCode[0x1F] ="" // S pressed
+ScanCodeToKeyCode[0x20] ="" // D pressed
+ScanCodeToKeyCode[0x21] ="" // F pressed
+ScanCodeToKeyCode[0x22] ="" // G pressed
+ScanCodeToKeyCode[0x23] ="" // H pressed
+ScanCodeToKeyCode[0x24] ="" // J pressed
+ScanCodeToKeyCode[0x25] ="" // K pressed
+ScanCodeToKeyCode[0x26] ="" // L pressed
+ScanCodeToKeyCode[0x27] ="" // ; pressed
+ScanCodeToKeyCode[0x28] ="" // ' (single quote) pressed
+ScanCodeToKeyCode[0x29] ="" // ` (back tick) pressed
+ScanCodeToKeyCode[0x2A] ="" // left shift pressed
+ScanCodeToKeyCode[0x2B] ="" // \ pressed
+ScanCodeToKeyCode[0x2C] ="" // Z pressed
+ScanCodeToKeyCode[0x2D] ="" // X pressed
+ScanCodeToKeyCode[0x2E] ="" // C pressed
+ScanCodeToKeyCode[0x2F] ="" // V pressed
+ScanCodeToKeyCode[0x30] ="" // B pressed
+ScanCodeToKeyCode[0x31] ="" // N pressed
+ScanCodeToKeyCode[0x32] ="" // M pressed
+ScanCodeToKeyCode[0x33] ="" // , pressed
+ScanCodeToKeyCode[0x34] ="" // . pressed
+ScanCodeToKeyCode[0x35] ="" // / pressed
+ScanCodeToKeyCode[0x36] ="" // right shift pressed
+ScanCodeToKeyCode[0x37] ="" // (keypad) * pressed
+ScanCodeToKeyCode[0x38] ="" // left alt pressed
+ScanCodeToKeyCode[0x39] ="" // space pressed
+ScanCodeToKeyCode[0x3A] ="" // CapsLock pressed
+ScanCodeToKeyCode[0x3B] ="" // F1 pressed
+ScanCodeToKeyCode[0x3C] ="" // F2 pressed
+ScanCodeToKeyCode[0x3D] ="" // F3 pressed
+ScanCodeToKeyCode[0x3E] ="" // F4 pressed
+ScanCodeToKeyCode[0x3F] ="" // F5 pressed
+ScanCodeToKeyCode[0x40] ="" // F6 pressed
+ScanCodeToKeyCode[0x41] ="" // F7 pressed
+ScanCodeToKeyCode[0x42] ="" // F8 pressed
+ScanCodeToKeyCode[0x43] ="" // F9 pressed
+ScanCodeToKeyCode[0x44] ="" // F10 pressed
+ScanCodeToKeyCode[0x45] ="" // NumberLock pressed
+ScanCodeToKeyCode[0x46] ="" // ScrollLock pressed
+ScanCodeToKeyCode[0x47] ="" // (keypad) 7 pressed
+ScanCodeToKeyCode[0x48] ="" // (keypad) 8 pressed
+ScanCodeToKeyCode[0x49] ="" // (keypad) 9 pressed
+ScanCodeToKeyCode[0x4A] ="" // (keypad) - pressed
+ScanCodeToKeyCode[0x4B] ="" // (keypad) 4 pressed
+ScanCodeToKeyCode[0x4C] ="" // (keypad) 5 pressed
+ScanCodeToKeyCode[0x4D] ="" // (keypad) 6 pressed
+ScanCodeToKeyCode[0x4E] ="" // (keypad) + pressed
+ScanCodeToKeyCode[0x4F] ="" // (keypad) 1 pressed
+ScanCodeToKeyCode[0x50] ="" // (keypad) 2 pressed
+ScanCodeToKeyCode[0x51] ="" // (keypad) 3 pressed
+ScanCodeToKeyCode[0x52] ="" // (keypad) 0 pressed
+ScanCodeToKeyCode[0x53] ="" // (keypad) . pressed
+ScanCodeToKeyCode[0x57] ="" // F11 pressed
+ScanCodeToKeyCode[0x58] ="" // F12 pressed
+
+
+/* key released scanCode.""*/
+ScanCodeToKeyCode[0x81] ="" // escape released
+ScanCodeToKeyCode[0x82] ="" // 1 released
+ScanCodeToKeyCode[0x83] ="" // 2 released
+ScanCodeToKeyCode[0x84] ="" // 3 released
+ScanCodeToKeyCode[0x85] ="" // 4 released
+ScanCodeToKeyCode[0x86] ="" // 5 released
+ScanCodeToKeyCode[0x87] ="" // 6 released
+ScanCodeToKeyCode[0x88] ="" // 7 released
+ScanCodeToKeyCode[0x89] ="" // 8 released
+ScanCodeToKeyCode[0x8A] ="" // 9 released
+ScanCodeToKeyCode[0x8B] ="" // 0 (zero) released
+ScanCodeToKeyCode[0x8C] ="" // - released
+ScanCodeToKeyCode[0x8D] ="" // = released
+ScanCodeToKeyCode[0x8E] ="" // backspace released
+ScanCodeToKeyCode[0x8F] ="" // tab released
+ScanCodeToKeyCode[0x90] ="" // Q released
+ScanCodeToKeyCode[0x91] ="" // W released
+ScanCodeToKeyCode[0x92] ="" // E released
+ScanCodeToKeyCode[0x93] ="" // R released
+ScanCodeToKeyCode[0x94] ="" // T released
+ScanCodeToKeyCode[0x95] ="" // Y released
+ScanCodeToKeyCode[0x96] ="" // U released
+ScanCodeToKeyCode[0x97] ="" // I released
+ScanCodeToKeyCode[0x98] ="" // O released
+ScanCodeToKeyCode[0x99] ="" // P released
+ScanCodeToKeyCode[0x9A] ="" // [ released
+ScanCodeToKeyCode[0x9B] ="" // ] released
+ScanCodeToKeyCode[0x9C] ="" // enter released
+ScanCodeToKeyCode[0x9D] ="" // left control released
+ScanCodeToKeyCode[0x9E] ="" // A released
+ScanCodeToKeyCode[0x9F] ="" // S released
+ScanCodeToKeyCode[0xA0] ="" // D released
+ScanCodeToKeyCode[0xA1] ="" // F released
+ScanCodeToKeyCode[0xA2] ="" // G released
+ScanCodeToKeyCode[0xA3] ="" // H released
+ScanCodeToKeyCode[0xA4] ="" // J released
+ScanCodeToKeyCode[0xA5] ="" // K released
+ScanCodeToKeyCode[0xA6] ="" // L released
+ScanCodeToKeyCode[0xA7] ="" // ; released
+ScanCodeToKeyCode[0xA8] ="" // ' (single quote) released
+ScanCodeToKeyCode[0xA9] ="" // ` (back tick) released
+ScanCodeToKeyCode[0xAA] ="" // left shift released
+ScanCodeToKeyCode[0xAB] ="" // \ released
+ScanCodeToKeyCode[0xAC] ="" // Z released
+ScanCodeToKeyCode[0xAD] ="" // X released
+ScanCodeToKeyCode[0xAE] ="" // C released
+ScanCodeToKeyCode[0xAF] ="" // V released
+ScanCodeToKeyCode[0xB0] ="" // B released
+ScanCodeToKeyCode[0xB1] ="" // N released
+ScanCodeToKeyCode[0xB2] ="" // M released
+ScanCodeToKeyCode[0xB3] ="" // , released
+ScanCodeToKeyCode[0xB4] ="" // . released
+ScanCodeToKeyCode[0xB5] ="" // / released
+ScanCodeToKeyCode[0xB6] ="" // right shift released
+ScanCodeToKeyCode[0xB7] ="" // (keypad) * released
+ScanCodeToKeyCode[0xB8] ="" // left alt released
+ScanCodeToKeyCode[0xB9] ="" // space released
+ScanCodeToKeyCode[0xBA] ="" // CapsLock released
+ScanCodeToKeyCode[0xBB] ="" // F1 released
+ScanCodeToKeyCode[0xBC] ="" // F2 released
+ScanCodeToKeyCode[0xBD] ="" // F3 released
+ScanCodeToKeyCode[0xBE] ="" // F4 released
+ScanCodeToKeyCode[0xBF] ="" // F5 released
+ScanCodeToKeyCode[0xC0] ="" // F6 released
+ScanCodeToKeyCode[0xC1] ="" // F7 released
+ScanCodeToKeyCode[0xC2] ="" // F8 released
+ScanCodeToKeyCode[0xC3] ="" // F9 released
+ScanCodeToKeyCode[0xC4] ="" // F10 released
+ScanCodeToKeyCode[0xC5] ="" // NumberLock released
+ScanCodeToKeyCode[0xC6] ="" // ScrollLock released
+ScanCodeToKeyCode[0xC7] ="" // (keypad) 7 released
+ScanCodeToKeyCode[0xC8] ="" // (keypad) 8 released
+ScanCodeToKeyCode[0xC9] ="" // (keypad) 9 released
+ScanCodeToKeyCode[0xCA] ="" // (keypad) - released
+ScanCodeToKeyCode[0xCB] ="" // (keypad) 4 released
+ScanCodeToKeyCode[0xCC] ="" // (keypad) 5 released
+ScanCodeToKeyCode[0xCD] ="" // (keypad) 6 released
+ScanCodeToKeyCode[0xCE] ="" // (keypad) + released
+ScanCodeToKeyCode[0xCF] ="" // (keypad) 1 released
+ScanCodeToKeyCode[0xD0] ="" // (keypad) 2 released
+ScanCodeToKeyCode[0xD1] ="" // (keypad) 3 released
+ScanCodeToKeyCode[0xD2] ="" // (keypad) 0 released
+ScanCodeToKeyCode[0xD3] ="" // (keypad) . released
+ScanCodeToKeyCode[0xD7] ="" // F11 released
+ScanCodeToKeyCode[0xD8] ="" // F12 released
\ No newline at end of file
diff --git a/src/kernel/arch/i386/pic/pic.cpp b/src/kernel/arch/i386/pic/pic.cpp
new file mode 100644
index 0000000..5f1967c
--- /dev/null
+++ b/src/kernel/arch/i386/pic/pic.cpp
@@ -0,0 +1,62 @@
+#include "pic.h"
+
+extern "C" void PIC_sendEOI (unsigned char irq){
+ if(irq >= 8)
+ outb(PIC2_COMMAND, PIC_EOI);
+ outb(PIC1_COMMAND, PIC_EOI);
+}
+
+/* Helper func */
+static uint16_t __pic_get_irq_reg(int ocw3)
+{
+ /* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
+ * represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
+ outb(PIC1_COMMAND, ocw3);
+ outb(PIC2_COMMAND, ocw3);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}
+
+/* Returns the combined value of the cascaded PICs irq request register */
+uint16_t pic_get_irr(void)
+{
+ return __pic_get_irq_reg(PIC_READ_IRR);
+}
+
+/* Returns the combined value of the cascaded PICs in-service register */
+uint16_t pic_get_isr(void)
+{
+ return __pic_get_irq_reg(PIC_READ_ISR);
+}
+
+
+void PIC_remap (int offset1, int offset2 ){
+ unsigned char a1, a2;
+
+ a1 = inb(PIC1_DATA);
+ a2 = inb(PIC2_DATA);
+
+
+ // Start initialization
+
+ outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
+ io_wait();
+ outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
+ io_wait();
+ outb(PIC1_DATA, offset1);
+ io_wait();
+ outb(PIC2_DATA, offset2);
+ io_wait();
+ outb(PIC1_DATA, 4);
+ io_wait();
+ outb(PIC2_DATA, 2);
+ io_wait();
+
+ outb(PIC1_DATA, ICW4_8086);
+ io_wait();
+ outb(PIC2_DATA, ICW4_8086);
+ io_wait();
+
+ outb(PIC1_DATA, a1);
+ outb(PIC2_DATA, a2);
+
+}
\ No newline at end of file
diff --git a/src/kernel/arch/i386/pic/pic.h b/src/kernel/arch/i386/pic/pic.h
new file mode 100644
index 0000000..5358f5a
--- /dev/null
+++ b/src/kernel/arch/i386/pic/pic.h
@@ -0,0 +1,57 @@
+#pragma once
+#include "../../../io.h"
+
+#define PIC1 0x20 /* IO base address for master PIC */
+#define PIC2 0xA0 /* IO base address for slave PIC */
+#define PIC1_COMMAND PIC1
+#define PIC1_DATA (PIC1+1)
+#define PIC2_COMMAND PIC2
+#define PIC2_DATA (PIC2+1)
+
+
+#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
+#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
+#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
+#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
+#define ICW1_INIT 0x10 /* Initialization - required! */
+
+#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
+#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
+#define ICW4_SFNM 0x10 /* Special fully nested (not) */
+
+#define PIC_EOI 0x20
+#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
+#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
+
+extern "C"{
+
+extern void irq0 ();
+extern void irq1 ();
+extern void irq2 ();
+extern void irq3 ();
+extern void irq4 ();
+extern void irq5 ();
+extern void irq6 ();
+extern void irq7 ();
+extern void irq8 ();
+extern void irq9 ();
+extern void irq10 ();
+extern void irq11 ();
+extern void irq12 ();
+extern void irq13 ();
+extern void irq14 ();
+extern void irq15 ();
+
+void PIC_sendEOI (unsigned char irq);
+
+}
+
+
+static uint16_t __pic_get_irq_reg(int ocw3);
+uint16_t pic_get_irr(void);
+uint16_t pic_get_isr(void);
+
+
+void PIC_remap (int offset1, int offset2 );
\ No newline at end of file
diff --git a/src/kernel/arch/i386/tty/kterm.c b/src/kernel/arch/i386/tty/kterm.c
index 2021e22..7ec9ae1 100644
--- a/src/kernel/arch/i386/tty/kterm.c
+++ b/src/kernel/arch/i386/tty/kterm.c
@@ -62,15 +62,17 @@ void kterm_scrollup(){
}
void kterm_put (char c) {
-
if(++kterm_column == VGA_WIDTH || c == '\n' ) {
kterm_column = 0;
- if(kterm_row == VGA_HEIGHT-1) {
+ if(kterm_row == VGA_HEIGHT-1 ) {
kterm_scrollup();
} else {
kterm_row ++;
}
-
+ }
+ if ( c == '\r'){
+ kterm_column = 0;
+ return;
}
if(c == '\n') return;
@@ -90,3 +92,99 @@ void kterm_writestring(const char* data ){
kterm_write(data, strlen(data));
}
+
+static void itoa (char *buf, int base, int d) {
+ char *p = buf;
+ char *p1, *p2;
+ unsigned long ud = d;
+ int divisor = 10;
+ if ( base == 'd' && d < 0){
+ *p++ = '-';
+ buf++;
+ ud = -d;
+ } else if (base == 'x'){
+ divisor = 16;
+ }
+
+ do {
+ int remainder = ud % divisor;
+
+ *p++ = (remainder < 10 ) ? remainder + '0' : remainder + 'a' -10;
+ } while(ud /= divisor);
+
+ /*terminate buf*/
+ *p =0;
+ p1 = buf;
+ p2 = p -1;
+
+ while (p1 < p2)
+ {
+ char tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+ p1++;
+ p2--;
+
+ }
+
+}
+
+void printf ( const char *format, ...) {
+
+ char **arg = (char **)&format;
+ int c;
+ char buf[20];
+
+ arg++;
+
+ while ((c = *format++) != 0){
+ if( c != '%')
+ kterm_put(c);
+ else{
+ char *p, *p2;
+ int pad0 = 0, pad = 0;
+
+ c = *format++;
+ if(c =='0'){
+ pad0 = 1;
+ c = *format++;
+ }
+
+ if ( c >= '0' && c <= '9'){
+ pad = c - '0';
+ c = *format++;
+ }
+
+ switch (c)
+ {
+ case 'd':
+
+ case 'u':
+ case 'x':
+ itoa(buf, c, *((int *) arg++));
+
+ p = buf;
+ goto string;
+ break;
+
+ case 's':
+ p = *arg++;
+ if(!p)
+ p = "(null)";
+
+ string:
+ for (p2 = p; *p2; p2++);
+ for (; p2 < p + pad; p2++)
+ kterm_put(pad0 ? '0': ' ');
+ while (*p)
+ kterm_put(*p++);
+ break;
+
+
+ default:
+ kterm_put(*((int *)arg++));
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/kernel/arch/i386/tty/kterm.h b/src/kernel/arch/i386/tty/kterm.h
index 6cf784e..d9f704f 100644
--- a/src/kernel/arch/i386/tty/kterm.h
+++ b/src/kernel/arch/i386/tty/kterm.h
@@ -17,7 +17,14 @@ void kterm_write(const char*, size_t);
void kterm_writestring(const char*);
void kterm_scrollup();
+
+void printf ( const char *format, ...);
+
+static void itoa (char *buf, int base, int d);
+
#define KernelTag "[Kernel]: "
#define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\
kterm_write(KernelTag, 10 ), \
- kterm_resetcolor())
\ No newline at end of file
+ kterm_resetcolor())
+
+
diff --git a/src/kernel/io.cpp b/src/kernel/io.cpp
index 11dbc3b..f9ed07d 100644
--- a/src/kernel/io.cpp
+++ b/src/kernel/io.cpp
@@ -56,4 +56,12 @@ void outsw(unsigned short , const void *,
void outsl(unsigned short , const void *,
unsigned long ){
- }
\ No newline at end of file
+ }
+
+void io_wait(void)
+{
+ /* TODO: This is probably fragile. */
+ asm volatile ( "jmp 1f\n\t"
+ "1:jmp 2f\n\t"
+ "2:" );
+}
\ No newline at end of file
diff --git a/src/kernel/io.h b/src/kernel/io.h
index 8b729f9..c7fd561 100644
--- a/src/kernel/io.h
+++ b/src/kernel/io.h
@@ -40,4 +40,5 @@ void outsb(unsigned short port, const void *addr,
void outsw(unsigned short port, const void *addr,
unsigned long count);
void outsl(unsigned short port, const void *addr,
- unsigned long count);
\ No newline at end of file
+ unsigned long count);
+void io_wait();
\ No newline at end of file
diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp
index 14f0321..6764040 100644
--- a/src/kernel/kernel.cpp
+++ b/src/kernel/kernel.cpp
@@ -16,7 +16,6 @@ class Test {
~Test();
};
-
Test::Test(){
kterm_writestring("Create a test object\n");
};
@@ -52,7 +51,6 @@ static int init_serial() {
return 0;
}
-
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
@@ -73,6 +71,11 @@ char read_serial() {
return inb(PORT);
}
+void print_serial(const char* string ){
+ for(size_t i = 0; i < strlen(string); i ++){
+ write_serial(string[i]);
+ }
+}
void test_serial(){
/** Serial test **/
@@ -92,12 +95,32 @@ void test_serial(){
kterm_writestring("\n");
}
-
extern "C" {
+
+ void early_main(){
+
+ init_serial();
+ print_serial("\033[31;42mEarly main called!\n");
+
+ }
+
void kernel_main (void) {
+
+ print_serial("Kernel main called!\n");
+
+
/** initialize terminal interface */
kterm_init();
+ /** Setup the MMU **/
+ //kterm_writestring("Starting MMU...\n");
+ //auto mmu = MMU();
+ //mmu.enable();
+ //kterm_writestring("MMU enabled!\n");
+
+
+
+
/** Wrtite stuff to the screen to test the terminal**/
kterm_writestring("Hello world!\n");
kterm_writestring("We got newline support!\n");
@@ -114,22 +137,27 @@ extern "C" {
auto testObject = Test();
testObject.printMe();
- /** Setup the MMU **/
- kterm_writestring("Starting MMU...\n");
- auto mmu = MMU();
- mmu.enable();
- kterm_writestring("MMU enabled!\n");
-
+ /** test interrupt handlers **/
+ //asm volatile ("int $0x03");
+ //asm volatile ("int $0x04");
+
+ while (true){
+ //Read time indefinetely
+ read_rtc();
+ printf( "UTC time: %2d-%2d-%2d %2d:%2d:%2d : (YY-MM-DD h:mm:ss)\r" ,year, month, day, hour, minute, second);
+ delay(1000);
+ }
+
+
/** Lets start using the serial port for debugging .. **/
// Hopefully once we go into realmode or do something that
// cause the screen to go black.. this serial comms part will give
// some situational awareness
//Serial serialbus = Serial::init();
- test_serial();
}
diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h
index 080869a..eed09c0 100644
--- a/src/kernel/kernel.h
+++ b/src/kernel/kernel.h
@@ -1,7 +1,10 @@
#pragma once
extern "C" {
-#include "../libc/include/string.h"
-#include "arch/i386/tty/kterm.h"
+ #include "../libc/include/string.h"
+ #include "arch/i386/tty/kterm.h"
}
+
+#include "arch/i386/idt/idt.h"
#include "MMU.h"
#include "io.h"
+#include "time.h"
diff --git a/src/kernel/time.h b/src/kernel/time.h
new file mode 100644
index 0000000..6a098b7
--- /dev/null
+++ b/src/kernel/time.h
@@ -0,0 +1,151 @@
+#define CURRENT_YEAR 2021 // Change this each year!
+
+int century_register = 0x00; // Set by ACPI table parsing code if possible
+
+unsigned char second;
+unsigned char minute;
+unsigned char hour;
+unsigned char day;
+unsigned char month;
+unsigned int year;
+
+
+
+enum {
+ cmos_address = 0x70,
+ cmos_data = 0x71
+};
+
+int get_update_in_progress_flag() {
+ outb(cmos_address, 0x0A);
+ return (inb(cmos_data) & 0x80);
+}
+
+unsigned char get_RTC_register(int reg) {
+ outb(cmos_address, reg);
+ return inb(cmos_data);
+}
+
+void read_rtc() {
+ unsigned char century;
+ unsigned char last_second;
+ unsigned char last_minute;
+ unsigned char last_hour;
+ unsigned char last_day;
+ unsigned char last_month;
+ unsigned char last_year;
+ unsigned char last_century;
+ unsigned char registerB;
+
+ // Note: This uses the "read registers until you get the same values twice in a row" technique
+ // to avoid getting dodgy/inconsistent values due to RTC updates
+
+ while (get_update_in_progress_flag()); // Make sure an update isn't in progress
+ second = get_RTC_register(0x00);
+ minute = get_RTC_register(0x02);
+ hour = get_RTC_register(0x04);
+ day = get_RTC_register(0x07);
+ month = get_RTC_register(0x08);
+ year = get_RTC_register(0x09);
+ if(century_register != 0) {
+ century = get_RTC_register(century_register);
+ }
+
+ do {
+ last_second = second;
+ last_minute = minute;
+ last_hour = hour;
+ last_day = day;
+ last_month = month;
+ last_year = year;
+ last_century = century;
+
+ while (get_update_in_progress_flag()); // Make sure an update isn't in progress
+ second = get_RTC_register(0x00);
+ minute = get_RTC_register(0x02);
+ hour = get_RTC_register(0x04);
+ day = get_RTC_register(0x07);
+ month = get_RTC_register(0x08);
+ year = get_RTC_register(0x09);
+ if(century_register != 0) {
+ century = get_RTC_register(century_register);
+ }
+ } while( (last_second != second) || (last_minute != minute) || (last_hour != hour) ||
+ (last_day != day) || (last_month != month) || (last_year != year) ||
+ (last_century != century) );
+
+ registerB = get_RTC_register(0x0B);
+
+ // Convert BCD to binary values if necessary
+
+ if (!(registerB & 0x04)) {
+ second = (second & 0x0F) + ((second / 16) * 10);
+ minute = (minute & 0x0F) + ((minute / 16) * 10);
+ hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80);
+ day = (day & 0x0F) + ((day / 16) * 10);
+ month = (month & 0x0F) + ((month / 16) * 10);
+ year = (year & 0x0F) + ((year / 16) * 10);
+ if(century_register != 0) {
+ century = (century & 0x0F) + ((century / 16) * 10);
+ }
+ }
+
+ // Convert 12 hour clock to 24 hour clock if necessary
+
+ if (!(registerB & 0x02) && (hour & 0x80)) {
+ hour = ((hour & 0x7F) + 12) % 24;
+ }
+
+ // Calculate the full (4-digit) year
+
+ if(century_register != 0) {
+ year += century * 100;
+ } else {
+ year += (CURRENT_YEAR / 100) * 100;
+ if(year < CURRENT_YEAR) year += 100;
+ }
+}
+
+
+/*
+void ReadFromCMOS(unsigned char array[])
+{
+ unsigned char tvalue, index;
+
+ for (index = 0; index < 128; index++)
+ {
+ asm(
+ "cli\n\t" // Disable interrupts
+ "mov al, index\n\t" // Move index address
+ // since the 0x80 bit of al is not set, NMI is active
+ "out 0x70,al\n\t" // Copy address to CMOS register
+ // some kind of real delay here is probably best
+ "in al,0x71\n\t" // Fetch 1 byte to al
+ "sti\n\t" // Enable interrupts
+ "mov tvalue,al\n\t");
+
+ array[index] = tvalue;
+ }
+}
+*/
+
+/*
+void WriteTOCMOS(unsigned char array[])
+{
+ unsigned char index;
+
+ for(index = 0; index < 128; index++)
+ {
+ unsigned char tvalue = array[index];
+
+ asm("cli\n\t" // Clear interrupts
+ "mov al,index\n\t" // move index address
+ "out 0x70,al\n\t" // copy address to CMOS register
+ /* some kind of real delay here is probably best
+ "mov al,tvalue\n\t" // move value to al
+ "out 0x71,al\n\t" // write 1 byte to CMOS
+ "sti\n\\t" ); // Enable interrupts
+
+ }
+}
+*/
\ No newline at end of file
diff --git a/src/kernel/timer.cpp b/src/kernel/timer.cpp
new file mode 100644
index 0000000..35a8a4a
--- /dev/null
+++ b/src/kernel/timer.cpp
@@ -0,0 +1,27 @@
+#include "timer.h"
+
+uint32_t tick = 0;
+
+
+static void timer_callback (registers_t regs ){
+ tick ++ ;
+ kterm_writestring ("tick passed!");
+}
+
+void init_timer (uint32_t frequency){
+ // register timer callback
+
+ uint32_t divisor = 1193180 / frequency;
+
+ // Send the commmand byte
+ outb(0x43, 0x36);
+
+ // Divisor has to be sent byt-wise , so will send lower then upper bytes
+ uint8_t low = (uint8_t) (divisor & 0xFF);
+ uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF);
+
+ outb(0x40, low);
+ outb(0x40, high);
+
+
+}
\ No newline at end of file
diff --git a/src/kernel/timer.h b/src/kernel/timer.h
new file mode 100644
index 0000000..db8be78
--- /dev/null
+++ b/src/kernel/timer.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include
+#include
+
+void init_timer (uint32_t frequency);
\ No newline at end of file