finished interrupts for now and a basic scheduler for that, start implementation on paging.
This commit is contained in:
6
makefile
6
makefile
@@ -8,11 +8,12 @@ build: prepare copygrub
|
|||||||
gcc -c src/kernel/graphics.c -o build/graphics.o -ffreestanding -O2 -Wall -Wextra -m32 # VGA graphics
|
gcc -c src/kernel/graphics.c -o build/graphics.o -ffreestanding -O2 -Wall -Wextra -m32 # VGA graphics
|
||||||
gcc -c src/kernel/tty.c -o build/tty.o -ffreestanding -O2 -Wall -Wextra -m32 # tty
|
gcc -c src/kernel/tty.c -o build/tty.o -ffreestanding -O2 -Wall -Wextra -m32 # tty
|
||||||
gcc -c src/kernel/interrupts.c -o build/interrupts.o -ffreestanding -O2 -Wall -Wextra -m32 # interrupts, C side
|
gcc -c src/kernel/interrupts.c -o build/interrupts.o -ffreestanding -O2 -Wall -Wextra -m32 # interrupts, C side
|
||||||
|
gcc -c src/kernel/scheduler.c -o build/scheduler.o -ffreestanding -O2 -Wall -Wextra -m32 # scheduler
|
||||||
|
|
||||||
gcc -c initrd/vga/main.c -o build/initrddir/vga_graph -ffreestanding -O2 -Wall -Wextra -m32 # initrd/vga driver
|
gcc -c initrd/vga/main.c -o build/initrddir/vga_graph -ffreestanding -O2 -Wall -Wextra -m32 # initrd/vga driver
|
||||||
|
|
||||||
tar -czf build/initrd build/initrddir/* # build initrd
|
tar -czf build/initrd build/initrddir/* # build initrd
|
||||||
gcc -z noexecstack -m32 -T linker.ld -o build/linked -ffreestanding -O2 -nostdlib build/interrupts.o build/intasm.o build/tty.o build/graphics.o build/boot.o build/kernel.o build/stdlib.o -fno-pie -fno-pic -no-pie # link
|
gcc -z noexecstack -m32 -T linker.ld -o build/linked -ffreestanding -O2 -nostdlib build/scheduler.o build/interrupts.o build/intasm.o build/tty.o build/graphics.o build/boot.o build/kernel.o build/stdlib.o -fno-pie -fno-pic -no-pie # link
|
||||||
|
|
||||||
cp build/linked build/grub/boot/kernel # copy kernel over to grub template
|
cp build/linked build/grub/boot/kernel # copy kernel over to grub template
|
||||||
cp build/initrd build/grub/boot/JPOS.initrd # copy initrd to grub template
|
cp build/initrd build/grub/boot/JPOS.initrd # copy initrd to grub template
|
||||||
@@ -21,7 +22,8 @@ build: prepare copygrub
|
|||||||
test: build
|
test: build
|
||||||
qemu-system-i386 \
|
qemu-system-i386 \
|
||||||
-boot d \
|
-boot d \
|
||||||
-cdrom build/live.iso
|
-cdrom build/live.iso \
|
||||||
|
-d int
|
||||||
copygrub:
|
copygrub:
|
||||||
cp grubtemplate -r build/grub
|
cp grubtemplate -r build/grub
|
||||||
prepare: clean
|
prepare: clean
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
#define CASCADE_IRQ 2
|
#define CASCADE_IRQ 2
|
||||||
#define IDT_MAX_DESCRIPTORS 32
|
#define IDT_MAX_DESCRIPTORS 256
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||||
@@ -35,9 +35,14 @@ typedef struct {
|
|||||||
} __attribute__((packed)) idtr_t;
|
} __attribute__((packed)) idtr_t;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t ds;
|
uint32_t ds;
|
||||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
|
||||||
|
uint32_t eax, ecx, edx, ebx;
|
||||||
|
uint32_t esp, ebp, esi, edi;
|
||||||
|
|
||||||
uint32_t int_no, err_code;
|
uint32_t int_no, err_code;
|
||||||
uint32_t eip, cs, eflags, useresp, ss;
|
|
||||||
|
//uint32_t eip, cs, eflags;
|
||||||
|
uint32_t useresp, ss;
|
||||||
} INT_registers_t;
|
} INT_registers_t;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t inuse;
|
uint8_t inuse;
|
||||||
@@ -53,7 +58,7 @@ inline void PIC_sendEOI(uint8_t irq) {
|
|||||||
void PIC_remap(int offset1, int offset2);
|
void PIC_remap(int offset1, int offset2);
|
||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
void INT_exhand(INT_registers_t regs);
|
void INT_exhand(INT_registers_t regs);
|
||||||
void INT_IRQ(uint8_t IRQ, INT_registers_t regs);
|
void INT_IRQ(INT_registers_t* regs);
|
||||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);
|
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);
|
||||||
void idt_init();
|
void idt_init();
|
||||||
void IRQ_registerhandler(uint8_t vector, void* callback);
|
void IRQ_registerhandler(uint8_t vector, void* callback);
|
||||||
|
|||||||
21
src/headers/keyboard.h
Normal file
21
src/headers/keyboard.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "stddef.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#define KEYBOARD_cmd_setled 0xED
|
||||||
|
#define KEYBOARD_cmd_echo 0xEE
|
||||||
|
#define KEYBOARD_cmd_setscanset 0xF0
|
||||||
|
#define KEYBOARD_cmd_enable 0xF4
|
||||||
|
#define KEYBOARD_cmd_disable 0xF5
|
||||||
|
#define KEYBOARD_cmd_reset 0xFF
|
||||||
|
#define KEYBOARD_resp_ACK 0xFA
|
||||||
|
#define KEYBOARD_resp_resend 0xFE
|
||||||
|
#define KEYBOARD_resp_err 0x00
|
||||||
|
#define KEYBOARD_resp_selftestpass 0xAA
|
||||||
|
#define KEYBOARD_resp_echo 0xEE
|
||||||
|
#define KEYBOARD_resp_testfail1 0xFC
|
||||||
|
#define KEYBOARD_resp_testfail2 0xFD
|
||||||
|
#define KEYBOARD_resp_err2 0xFF
|
||||||
|
#define KEYBOARD_cqsize 128
|
||||||
|
|
||||||
|
extern uint8_t KEYBOARD_cmdqueue[KEYBOARD_cqsize];
|
||||||
|
extern size_t KEYBOARD_cmdqueuesize;
|
||||||
0
src/headers/paging.h
Normal file
0
src/headers/paging.h
Normal file
21
src/headers/scheduler.h
Normal file
21
src/headers/scheduler.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "stddef.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#define SCHED_tasksize 128
|
||||||
|
#define SCHED_freq 1000
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t inUse;
|
||||||
|
uint8_t type;
|
||||||
|
size_t ticks;
|
||||||
|
void* callback;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
extern task_t tasks[SCHED_tasksize];
|
||||||
|
|
||||||
|
void tick();
|
||||||
|
size_t schedule_task(size_t tick, void* callback);
|
||||||
|
uint8_t schedule_sleep(size_t tick);
|
||||||
|
size_t schedule_task_fl(double time, void* callback);
|
||||||
|
uint8_t schedule_sleep_fl(double time);
|
||||||
|
task_t* schedule_getTask(size_t index);
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "../headers/graphics.h"
|
#include "../headers/graphics.h"
|
||||||
#include "../headers/tty.h"
|
#include "../headers/tty.h"
|
||||||
#include "../headers/interrupts.h"
|
#include "../headers/interrupts.h"
|
||||||
|
#include "../headers/scheduler.h"
|
||||||
|
|
||||||
struct multiboot_info {
|
struct multiboot_info {
|
||||||
uint32_t total_size;
|
uint32_t total_size;
|
||||||
@@ -55,16 +56,17 @@ void kernel_main(struct multiboot_info* header, uint32_t magic) {
|
|||||||
}
|
}
|
||||||
kputstr("OK\n");
|
kputstr("OK\n");
|
||||||
|
|
||||||
kputstr("Setting up interrupts: ");
|
|
||||||
idt_init();
|
|
||||||
kputstr("OK\n");
|
|
||||||
|
|
||||||
kputstr("Setting up IRQs: ");
|
kputstr("Setting up IRQs: ");
|
||||||
for (uint8_t i=0;i<16;i++) {
|
for (uint8_t i=0;i<16;i++) {
|
||||||
idt_set_descriptor(i+0x20, irq_stub_table[i], 0x8E);
|
idt_set_descriptor(i+0x20, irq_stub_table[i], 0x8E);
|
||||||
|
IRQ_entries[i].inuse = 0;
|
||||||
}
|
}
|
||||||
kputstr("OK\n");
|
kputstr("OK\n");
|
||||||
|
|
||||||
|
kputstr("Setting up interrupts: ");
|
||||||
|
idt_init();
|
||||||
|
kputstr("OK\n");
|
||||||
|
|
||||||
kputstr("Initializing PICs: ");
|
kputstr("Initializing PICs: ");
|
||||||
PIC_remap(0x20,0x28);
|
PIC_remap(0x20,0x28);
|
||||||
kputstr("OK\n");
|
kputstr("OK\n");
|
||||||
@@ -73,10 +75,8 @@ void kernel_main(struct multiboot_info* header, uint32_t magic) {
|
|||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
kputstr("OK\n");
|
kputstr("OK\n");
|
||||||
|
|
||||||
while (1) {}
|
|
||||||
|
|
||||||
kputstr("Initializing Timer: ");
|
kputstr("Initializing Timer: ");
|
||||||
uint32_t divisor = 1193180 / 1000;
|
uint32_t divisor = 1193180 / SCHED_freq;
|
||||||
uint8_t low = (uint8_t)(divisor & 0xFF);
|
uint8_t low = (uint8_t)(divisor & 0xFF);
|
||||||
uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
|
uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
|
||||||
outb(0x43, 0x36);
|
outb(0x43, 0x36);
|
||||||
@@ -84,5 +84,9 @@ void kernel_main(struct multiboot_info* header, uint32_t magic) {
|
|||||||
outb(0x40, high);
|
outb(0x40, high);
|
||||||
kputstr("OK\n");
|
kputstr("OK\n");
|
||||||
|
|
||||||
|
IRQ_registerhandler(0x00, &tick);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (1) {}
|
while (1) {}
|
||||||
}
|
}
|
||||||
@@ -72,11 +72,14 @@ void INT_exhand(INT_registers_t regs) {
|
|||||||
uitoa32(regs.int_no, temp);
|
uitoa32(regs.int_no, temp);
|
||||||
strcon(msg,temp);
|
strcon(msg,temp);
|
||||||
kpanic(msg);
|
kpanic(msg);
|
||||||
|
PIC_sendEOI(regs.int_no);
|
||||||
}
|
}
|
||||||
void INT_IRQ(INT_registers_t regs) {
|
void INT_IRQ(INT_registers_t* _regs) {
|
||||||
|
INT_registers_t regs = *_regs;
|
||||||
if (IRQ_entries[regs.int_no].inuse) {
|
if (IRQ_entries[regs.int_no].inuse) {
|
||||||
(void (*)(INT_registers_t))IRQ_entries[regs.int_no].callback(regs);
|
((void (*)(INT_registers_t))IRQ_entries[regs.int_no].callback)(regs);
|
||||||
}
|
}
|
||||||
|
PIC_sendEOI(regs.int_no);
|
||||||
}
|
}
|
||||||
void idt_init() {
|
void idt_init() {
|
||||||
idtr.base = (uint32_t)&idt[0];
|
idtr.base = (uint32_t)&idt[0];
|
||||||
@@ -89,6 +92,6 @@ void idt_init() {
|
|||||||
__asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT
|
__asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT
|
||||||
}
|
}
|
||||||
void IRQ_registerhandler(uint8_t vector, void* callback) {
|
void IRQ_registerhandler(uint8_t vector, void* callback) {
|
||||||
IRQ_entries[vector].inuse = 1;
|
|
||||||
IRQ_entries[vector].callback = callback;
|
IRQ_entries[vector].callback = callback;
|
||||||
|
IRQ_entries[vector].inuse = 1;
|
||||||
}
|
}
|
||||||
77
src/kernel/scheduler.c
Normal file
77
src/kernel/scheduler.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#include "../headers/scheduler.h"
|
||||||
|
|
||||||
|
task_t tasks[SCHED_tasksize];
|
||||||
|
uint8_t tasksbusy = 0;
|
||||||
|
|
||||||
|
void acquiretasks() {
|
||||||
|
while (tasksbusy) {}
|
||||||
|
tasksbusy = 1;
|
||||||
|
}
|
||||||
|
void freetasks() {
|
||||||
|
tasksbusy = 0;
|
||||||
|
}
|
||||||
|
void tick() {
|
||||||
|
if (tasksbusy) {return;}
|
||||||
|
acquiretasks();
|
||||||
|
for (size_t i=0;i<SCHED_tasksize;i++) {
|
||||||
|
if (tasks[i].inUse) {
|
||||||
|
tasks[i].ticks --;
|
||||||
|
if (tasks[i].ticks == 0) {
|
||||||
|
tasks[i].inUse = 0;
|
||||||
|
if (tasks[i].type == 0) { // callback
|
||||||
|
((void (*)())tasks[i].callback)();
|
||||||
|
} else if (tasks[i].type == 1) { // reset
|
||||||
|
*(uint8_t*)tasks[i].callback = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freetasks();
|
||||||
|
}
|
||||||
|
size_t schedule_task(size_t tick, void* callback) {
|
||||||
|
acquiretasks();
|
||||||
|
for (size_t i=0;i<SCHED_tasksize;i++) {
|
||||||
|
task_t* task = &tasks[i];
|
||||||
|
if (!task->inUse) {
|
||||||
|
task->inUse = 1;
|
||||||
|
task->ticks = tick;
|
||||||
|
task->callback = callback;
|
||||||
|
task->type = 0;
|
||||||
|
freetasks();
|
||||||
|
return i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freetasks();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t schedule_sleep(size_t tick) {
|
||||||
|
volatile uint8_t wait = 1;
|
||||||
|
acquiretasks();
|
||||||
|
for (size_t i=0;i<SCHED_tasksize+1;i++) {
|
||||||
|
if (i == SCHED_tasksize) {
|
||||||
|
freetasks();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
task_t* task = &tasks[i];
|
||||||
|
if (!task->inUse) {
|
||||||
|
task->inUse = 1;
|
||||||
|
task->ticks = tick;
|
||||||
|
task->callback = &wait;
|
||||||
|
task->type = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freetasks();
|
||||||
|
while (wait) {}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
size_t schedule_task_fl(double time, void* callback) {
|
||||||
|
return schedule_task(time*SCHED_freq, callback);
|
||||||
|
}
|
||||||
|
uint8_t schedule_sleep_fl(double time) {
|
||||||
|
return schedule_sleep(time*SCHED_freq);
|
||||||
|
}
|
||||||
|
task_t* schedule_getTask(size_t index) {
|
||||||
|
if (index == 0) {return 0x00;}
|
||||||
|
return &tasks[index-1];
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ void kpanic(char* msg) {
|
|||||||
|
|
||||||
for (uint16_t x=0;x<VGA_sizex;x++) {
|
for (uint16_t x=0;x<VGA_sizex;x++) {
|
||||||
for (uint16_t y=0;y<VGA_sizey;y++) {
|
for (uint16_t y=0;y<VGA_sizey;y++) {
|
||||||
VGA_setpix(x,y,(VGA_pixel){0x00,0xFF,0x00});
|
VGA_setpix(x,y,(VGA_pixel){(uint32_t)msg+x+(y*VGA_sizex)*3,(uint32_t)msg+x+(y*VGA_sizex)*3+1,(uint32_t)msg+x+(y*VGA_sizex)*3+2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size_t x=0;
|
size_t x=0;
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ extern INT_IRQ
|
|||||||
|
|
||||||
%macro isr_err_stub 1
|
%macro isr_err_stub 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
|
cli
|
||||||
push 0
|
push 0
|
||||||
push %1
|
push %1
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
mov ax, ds
|
mov ax, ds
|
||||||
push eax
|
push eax
|
||||||
mov ax, 0x08
|
mov ax, 0x10
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
|
|
||||||
call INT_exhand
|
call INT_exhand
|
||||||
|
|
||||||
pop eax
|
pop eax
|
||||||
@@ -24,12 +24,13 @@ isr_stub_%+%1:
|
|||||||
mov gs, ax
|
mov gs, ax
|
||||||
popa
|
popa
|
||||||
add esp, 8
|
add esp, 8
|
||||||
sti
|
|
||||||
iret
|
iret
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro isr_no_err_stub 1
|
%macro isr_no_err_stub 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
|
cli
|
||||||
;call INT_exhand
|
;call INT_exhand
|
||||||
sti
|
sti
|
||||||
iret
|
iret
|
||||||
@@ -37,18 +38,26 @@ isr_stub_%+%1:
|
|||||||
|
|
||||||
%macro irq_stub 1
|
%macro irq_stub 1
|
||||||
irq_stub_%+%1:
|
irq_stub_%+%1:
|
||||||
|
cli
|
||||||
push 0
|
push 0
|
||||||
push %1
|
push %1
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
|
xor eax, eax
|
||||||
mov ax, ds
|
mov ax, ds
|
||||||
push eax
|
push eax
|
||||||
mov ax, 0x08
|
mov ax, 0x10
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
|
|
||||||
|
mov eax, esp
|
||||||
|
push eax
|
||||||
|
|
||||||
call INT_IRQ
|
call INT_IRQ
|
||||||
|
|
||||||
|
add esp, 4
|
||||||
pop ebx
|
pop ebx
|
||||||
mov ds, bx
|
mov ds, bx
|
||||||
mov es, bx
|
mov es, bx
|
||||||
@@ -56,6 +65,8 @@ irq_stub_%+%1:
|
|||||||
mov gs, bx
|
mov gs, bx
|
||||||
popa
|
popa
|
||||||
add esp, 8
|
add esp, 8
|
||||||
|
sti
|
||||||
|
iret
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
isr_no_err_stub 0
|
isr_no_err_stub 0
|
||||||
|
|||||||
Reference in New Issue
Block a user