diff --git a/kernel/arch/arm/3ds11/start.cpp b/kernel/arch/arm/3ds11/start.cpp index d425139..b77a5b9 100644 --- a/kernel/arch/arm/3ds11/start.cpp +++ b/kernel/arch/arm/3ds11/start.cpp @@ -14,5 +14,7 @@ void drivers_init() { setMainTTY(&term); --term; initVectors(); - asm volatile("svc #0"); + *((volatile uint32_t*)0x17E00600)=67108; + *((volatile uint32_t*)0x17E00608=3; + asm volatile("CPSIE aif"); } diff --git a/kernel/arch/arm/3ds9/start.cpp b/kernel/arch/arm/3ds9/start.cpp index ed32066..c8d1f00 100644 --- a/kernel/arch/arm/3ds9/start.cpp +++ b/kernel/arch/arm/3ds9/start.cpp @@ -16,5 +16,10 @@ void drivers_init() { setMainTTY(&term); --term; initVectors(); - asm volatile("svc #0"); + //Init 1000Hz timer + *((volatile uint16_t*)0x10003002)=0; + *((volatile uint16_t*)0x10003000)=65; + *((volatile uint16_t*)0x10003002)=0b11000011; + *((volatile uint32_t*)0x10001000)|=1<<8; + asm volatile("CPSIE aif"); } diff --git a/kernel/arch/arm/raspi2/start.cpp b/kernel/arch/arm/raspi2/start.cpp index 63de620..35df741 100644 --- a/kernel/arch/arm/raspi2/start.cpp +++ b/kernel/arch/arm/raspi2/start.cpp @@ -14,5 +14,5 @@ void drivers_init() { setMainTTY(&term); --term; initVectors(); - asm volatile("svc #0"); + asm volatile("CPSIE aif"); } diff --git a/kernel/arch/x86/interrupt.cpp b/kernel/arch/x86/interrupt.cpp index 7ec7d53..3ceac78 100644 --- a/kernel/arch/x86/interrupt.cpp +++ b/kernel/arch/x86/interrupt.cpp @@ -1,6 +1,7 @@ #include "../../hw/pc/8259/pic.hpp" #include #include +#include void print_regdump(cpu_state *state) { (*out << "eax: ").puti(state->eax); (*out << " ebx: ").puti(state->ebx); @@ -18,14 +19,17 @@ extern "C" cpu_state *handleINT(cpu_state *state) { *out << "Interrupt "; out->puti(state->intr); *out << " occurred!\n"; + cpu_state *new_cpu=state; if (state->intr < 32) { out->setColor(Color::RED); print_regdump(state); *out << "KERNEL PANIC: Unhandled CPU exception\n"; for (;;) ; + } else if(state->intr < 48) { + new_cpu=(cpu_state*)irqs->handleIRQ(new_cpu); } - return state; + return new_cpu; } extern "C" void panic2(cpu_state *state) { state->esp = (uintptr_t)state; diff --git a/kernel/arch/x86/pc/start.cpp b/kernel/arch/x86/pc/start.cpp index 9d4598c..ff3a5a4 100644 --- a/kernel/arch/x86/pc/start.cpp +++ b/kernel/arch/x86/pc/start.cpp @@ -8,6 +8,7 @@ #include "../../../hw/pc/8259/pic.hpp" #include "../../../hw/pc/idt/idt.hpp" #include "../../../hw/pc/pmm/pmm.hpp" + #include static multiboot_info_t *mb_info; #ifndef ENABLE_FRAMEBUFFER @@ -28,5 +29,4 @@ void drivers_init() { initIDT(); PIC::initPIC(0x20, 0x28); asm volatile("sti"); - asm volatile("int $0x20"); } diff --git a/kernel/arch/x86_64/pc/start.cpp b/kernel/arch/x86_64/pc/start.cpp index 3ebfcd2..ff3a5a4 100644 --- a/kernel/arch/x86_64/pc/start.cpp +++ b/kernel/arch/x86_64/pc/start.cpp @@ -29,5 +29,4 @@ void drivers_init() { initIDT(); PIC::initPIC(0x20, 0x28); asm volatile("sti"); - asm volatile("int $32"); } diff --git a/kernel/hw/3ds11/vectorinit/vectorinit.cpp b/kernel/hw/3ds11/vectorinit/vectorinit.cpp index bcd4946..09dbdec 100644 --- a/kernel/hw/3ds11/vectorinit/vectorinit.cpp +++ b/kernel/hw/3ds11/vectorinit/vectorinit.cpp @@ -24,3 +24,33 @@ void initVectors() { vectors[10] = branch_macro; vectors[11] = (uintptr_t)&data_abort; } + +IRQ_IO::IRQ_IO() { + *((volatile uint32_t*)0x17E00100)=1; + *((volatile uint32_t*)0x17E00104)=0xF0; + for(int i=0;i<32;i+=4) { + *((volatile uint32_t*)(0x7E01100+i))=~0; + } + uint32_t intid; + while((intid=*((volatile uint32_t*)0x7E00118))!=1023) { + *((volatile uint32_t*)0x7E00110)=intid; + } +} +IRQ_IO::~IRQ_IO() {} + +void IRQ_IO::handleIRQ(void *data) { + uint32_t interrupt=*((volatile uint32_t*)0x7E0010C); + int intid = interrupt & 255; + data = handlers[intid](data); + *((volatile uint32_t*)0x7E00110) = interrupt; + return data; +} + +void IRQ_IO::mask(int number) {} +void IRQ_IO::unmask(int number) {} + +static IRQ_IO irq; +__attribute__((constructor)) +static void init_irq() { + irqs = (IRQ*)&irq; +} diff --git a/kernel/hw/3ds11/vectorinit/vectorinit.hpp b/kernel/hw/3ds11/vectorinit/vectorinit.hpp index 4004a27..9d983eb 100644 --- a/kernel/hw/3ds11/vectorinit/vectorinit.hpp +++ b/kernel/hw/3ds11/vectorinit/vectorinit.hpp @@ -1,2 +1,12 @@ +#pragma once #include +#include void initVectors(); + +struct IRQ_IO { + IRQ_IO(); + virtual ~IRQ_IO(); + virtual void* handleIRQ(void *data); + virtual void mask(int number); + virtual void unmask(int number); +}; diff --git a/kernel/hw/3ds9/vectorinit/vectorinit.cpp b/kernel/hw/3ds9/vectorinit/vectorinit.cpp index aace978..0309eee 100644 --- a/kernel/hw/3ds9/vectorinit/vectorinit.cpp +++ b/kernel/hw/3ds9/vectorinit/vectorinit.cpp @@ -9,8 +9,6 @@ void svc_call(); void undefined_op(); void flushAll(); } -#pragma GCC push_options -#pragma GCC optimize("O0") void initVectors() { uintptr_t *vectors = (uintptr_t *)0x08000000; // branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC @@ -28,4 +26,31 @@ void initVectors() { vectors[11] = (uintptr_t)&data_abort; flushAll(); } -#pragma GCC pop_options + +IRQ_IO::IRQ_IO() { + *((volatile uint32_t*)0x10001000)=~0; + *((volatile uint32_t*)0x10001004)=0; +} +IRQ_IO::~IRQ_IO() {} + +void* IRQ_IO::handleIRQ(void *data) { + //Call IRQ handlers until all IRQs are done. + int bit; + while(bit=__builtin_ffs(*((volatile int*)0x10001004))) { + data = handlers[bit-1](data); + *((volatile int*)0x10001004)&=~(1<<(bit-1)); + } + return data; +} + +void IRQ_IO::mask(int number) { + *((volatile int*)0x10001004)&=~(1< +#include void initVectors(); + +struct IRQ_IO { + IRQ_IO(); + virtual ~IRQ_IO(); + virtual void* handleIRQ(void *data); + virtual void mask(int number); + virtual void unmask(int number); +}; diff --git a/kernel/hw/pc/8259/pic.cpp b/kernel/hw/pc/8259/pic.cpp index 93e164a..6293b29 100644 --- a/kernel/hw/pc/8259/pic.cpp +++ b/kernel/hw/pc/8259/pic.cpp @@ -1,5 +1,6 @@ #include "pic.hpp" #include "../io.hpp" +#include #define PIC1 0x20 #define PIC2 0xA0 #define PIC1_COMMAND PIC1 @@ -19,6 +20,33 @@ #define ICW4_BUF_SLAVE 0x04 #define ICW4_BUF_MASTER 0x0C #define ICW4_SFNM 0x10 +IRQ_PIC::IRQ_PIC() { + PIC::initPIC(0x20, 0x28); +} +IRQ_PIC::~IRQ_PIC() { + PIC::disable(); +} +void* IRQ_PIC::handleIRQ(void *data) { + cpu_state* cpu = (cpu_state*)data; + auto val = handlers[cpu->intr-0x20](data); + PIC::sendEOI(cpu->intr > 0x27); + return val; +} +void IRQ_PIC::mask(int number) { + PIC::mask(number); +} +void IRQ_PIC::unmask(int number) { + PIC::unmask(number); +} +static IRQ_PIC irqpic; +__attribute__((constructor)) +static void initIRQ() { + irqs = &irqpic; + //Init pic + out(0x43, 0x34); + out(0x40, 156); + out(0x40, 46); +} namespace PIC { auto sendEOI(bool slave) -> void { if (slave) { out(PIC2_COMMAND, PIC_EOI); } diff --git a/kernel/hw/pc/8259/pic.hpp b/kernel/hw/pc/8259/pic.hpp index 6803bf5..d46b055 100644 --- a/kernel/hw/pc/8259/pic.hpp +++ b/kernel/hw/pc/8259/pic.hpp @@ -1,5 +1,13 @@ #pragma once #include +#include +struct IRQ_PIC: IRQ { + IRQ_PIC(); + virtual ~IRQ_PIC(); + virtual void* handleIRQ(void *data); + virtual void mask(int number); + virtual void unmask(int number); +}; /** * Namespace contains function to control the Programmable Interrupt Controller */ @@ -7,8 +15,8 @@ namespace PIC { auto sendEOI(bool slave) -> void; ///< Signals the PIC that the interrupt has ended auto initPIC(int off1, int off2) -> void; ///< Initializes the pic/remaps it auto disable() -> void; ///< disables PIC completely -auto maskIRQ(int no) -> void; ///< disables a single IRQ -auto unmaskIRQ(int no) -> void; ///< reenables a single IRQ +auto mask(int no) -> void; ///< disables a single IRQ +auto unmask(int no) -> void; ///< reenables a single IRQ auto disableSlave() -> void; ///< disables IRQ2 and 8-15 auto enableSlave() -> void; ///< reenables at least IRQ2 auto isSpurious(bool slave) -> bool; ///< Return if this isn't an actual IRQ. diff --git a/kernel/src/include/irq.hpp b/kernel/src/include/irq.hpp new file mode 100644 index 0000000..c68a448 --- /dev/null +++ b/kernel/src/include/irq.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "../../../config.h" +constexpr int same_string(char const* lhs, char const* rhs) { + return !__builtin_strcmp(lhs, rhs); +} +constexpr int get_max_irq() { + if constexpr(same_string(ARCH, "x86") || same_string(ARCH, "x86_64")) { + return 32; + } else if constexpr(same_string(SYSTEM, "3ds9")) { + return 30; + } else if constexpr(same_string(SYSTEM, "3ds11")) { + return 256; + } else { + return 32; + } +} +#define MAX_IRQ get_max_irq() +struct IRQ { + void*(*handlers[MAX_IRQ])(void*); + IRQ(); + virtual ~IRQ(); + virtual void* handleIRQ(void *data); + virtual void mask(int number); + virtual void unmask(int number); +}; +extern IRQ *irqs; diff --git a/kernel/src/irq.cpp b/kernel/src/irq.cpp new file mode 100644 index 0000000..0fbfa47 --- /dev/null +++ b/kernel/src/irq.cpp @@ -0,0 +1,12 @@ +#include +IRQ *irqs; +static void* do_nothing(void *a) {return a;} +IRQ::IRQ() { + for(int i=0;iputi((*pmm, 1)); - *out << "\n"; - } + for(;;); for (auto dtor = &start_dtors; dtor != &end_dtors; dtor++) (**dtor)(); }