//
// http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
//
#include "kernel.h" // general kernel config & includes
#include "console.h" // this will allow us to write to screen
#include "x86.h"
#include "../lib/logger/log.h" // logger facilities
#define FOOLOS_MODULE_NAME "kernel"
// TODO: cleanup . WHHYY can i compile it without the includes!??
///////
// interrupt handler prototypes
// todo: move somewhere else!?
void int_def_handler();
void int_clock_handler();
void int_kb_handler();
void int_floppy_handler();
////////// KERNEL MAIN///// /////
//
uint32_t read_eip();
void int_irq0(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Divide by 0"); X86_IRQ_END }
void int_irq1(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Single step (debugger)"); X86_IRQ_END }
void int_irq2(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Non Maskable Interrupt"); X86_IRQ_END }
void int_irq3(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Breakpoint (debugger)"); X86_IRQ_END }
void int_irq4(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Overflow"); X86_IRQ_END }
void int_irq5(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Bounds check"); X86_IRQ_END }
void int_irq6(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Undefined OP Code"); X86_IRQ_END }
void int_irq7(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"No coprocessor"); X86_IRQ_END }
void int_irq8(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Double Fault"); X86_IRQ_END }
void int_irq9(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor Segment Overrun"); X86_IRQ_END }
void int_irq10(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Invalid TSS"); X86_IRQ_END }
void int_irq11(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Segment Not Present"); X86_IRQ_END }
void int_irq12(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Stack Segment Overrun"); X86_IRQ_END }
void show_error(uint32_t err)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"interrupt error code: 0x%08x",err);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"External Event: %x",err&0b001);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Location: %x",err&0b110);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Selector: %x",err&0b1111111111111000);
}
void int_irq13()
{
X86_IRQ_BEGIN
uint32_t err;
asm("pop %eax"); // get Error Code
asm ("mov %%eax, %0":"=r"(err));
show_error(err);
panic(FOOLOS_MODULE_NAME,"General Protection Fault");
X86_IRQ_END
}
void int_irq14(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Page Fault"); X86_IRQ_END }
void int_irq15(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Unassigned"); X86_IRQ_END }
void int_irq16(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor error"); X86_IRQ_END }
void int_irq17(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Alignment Check"); X86_IRQ_END }
void int_irq18(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Machine Check"); X86_IRQ_END }
void enable_a20()
{
//; ;enable A20
//; ;http://www.brokenthorn.com/Resources/OSDev9.html
//; ;Method 3.1: Enables A20 through keyboard controller
//; ;Not all keyboard controllers support this
asm("mov $0xdd, %al");// ; command 0xdd: enable a20
//; ;mov al, 0xdf ; command 0xdf: disable a20
asm("outb %al, $0x64");// ; send command to controller
}
// heart of our operating system.
void kernel_main(uint32_t initial_stack)
{
//
// We want to get output to the screen as fast as possible!
//
// Our Fool-Boot-Loader did set up VESA already for us.
// The desired VESA mode is hardcoded in [boot/mbr.asm].
//
// The [vesa_init(...)] function requires:
//
// * the addresses of the vbeinfo struct
// * the address of the vbemodeinfo struct (for selected mode).
// * the address of our Fool-Font binary data.
//
// The first two paramters are hardcoded in [boot/mbr.asm],
// while the last one is set in the Makefile. The font binary
// is integrated in the kernel image.
//
// this function returns the physical base address of
// our video memory
//
uint32_t vesa_physbase=vesa_init(0x8300,0x8400,0x7200);
// initial stack
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"initial esp: 0x%08X",initial_stack);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"enable A20");
enable_a20();
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"setup PIC");
pic_setup();
// PIT config (timer)
timer_init();
// we know that here, the bootloader placed the mamory map!
mem_init(0x7c00+0x400,*((uint16_t *)(0x7c00+0x600)));
// paging (pass the vesa physbase address for identity mapping)
vmem_init(vesa_physbase);
//
// init and interrupt decriptor table
int_init(0x08);
int_install();
// setup custom interrupts
// remember that we shifted all interrupts with the pic by 32
// so clock = 32 (irq 0)
// keyboard = 33 (irq 1)
// floppy = 38 (irq 6)
// etc..
// install PIT interrupt handler
int_install_ir(32, 0b10001110, 0x08,&int_clock_handler);
// install keyboard interrupt handler
int_install_ir(33, 0b10001110, 0x08,&int_kb_handler);
// install floppy interrupt handler
int_install_ir(38, 0b10001110, 0x08,&int_floppy_handler);
// exceptions
int_install_ir(0, 0b10001110, 0x08,&int_irq0);
int_install_ir(1, 0b10001110, 0x08,&int_irq1);
int_install_ir(2, 0b10001110, 0x08,&int_irq2);
int_install_ir(3, 0b10001110, 0x08,&int_irq3);
int_install_ir(4, 0b10001110, 0x08,&int_irq4);
int_install_ir(5, 0b10001110, 0x08,&int_irq5);
int_install_ir(6, 0b10001110, 0x08,&int_irq6);
int_install_ir(7, 0b10001110, 0x08,&int_irq7);
int_install_ir(8, 0b10001110, 0x08,&int_irq8);
int_install_ir(9, 0b10001110, 0x08,&int_irq9);
int_install_ir(10, 0b10001110, 0x08,&int_irq10);
int_install_ir(11, 0b10001110, 0x08,&int_irq11);
int_install_ir(12, 0b10001110, 0x08,&int_irq12);
int_install_ir(13, 0b10001110, 0x08,&int_irq13);
int_install_ir(14, 0b10001110, 0x08,&int_irq14);
int_install_ir(15, 0b10001110, 0x08,&int_irq15);
int_install_ir(16, 0b10001110, 0x08,&int_irq16);
int_install_ir(17, 0b10001110, 0x08,&int_irq17);
int_install_ir(18, 0b10001110, 0x08,&int_irq18);
// now we can enable interrupts back again
int_enable();
// int x=10/0;
// pci
pci_init();
// floppy
// floppy_init();
//init shell
shell_init();
// multitasking
task_init();
/*
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test mem");
// test a20 disabled / wrap
uint8_t *memtest=0x0;
uint8_t *memtest2=0b10000000000000000000;
*memtest=0xaf;
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test mem %x",*(memtest2-1));
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test mem %x",*memtest2);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"test mem %x",*(memtest2+1));
*/
/* stack pointer test?
uint32_t *esp=0x90000;
for(int i=0;i<10;i++)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"esp: %x",*esp);
esp--;
}
*/
while(1)
{
}
}