started adding IRQ and clock sources. non-pc target are broken
This commit is contained in:
parent
bc5bf258a0
commit
cf16b1c37c
15 changed files with 171 additions and 15 deletions
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -14,5 +14,5 @@ void drivers_init() {
|
|||
setMainTTY(&term);
|
||||
--term;
|
||||
initVectors();
|
||||
asm volatile("svc #0");
|
||||
asm volatile("CPSIE aif");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "../../hw/pc/8259/pic.hpp"
|
||||
#include <base.hpp>
|
||||
#include <regs.h>
|
||||
#include <irq.hpp>
|
||||
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;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../../../hw/pc/8259/pic.hpp"
|
||||
#include "../../../hw/pc/idt/idt.hpp"
|
||||
#include "../../../hw/pc/pmm/pmm.hpp"
|
||||
|
||||
#include <base.hpp>
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -29,5 +29,4 @@ void drivers_init() {
|
|||
initIDT();
|
||||
PIC::initPIC(0x20, 0x28);
|
||||
asm volatile("sti");
|
||||
asm volatile("int $32");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <irq.hpp>
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -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<<number);
|
||||
}
|
||||
void IRQ_IO::unmask(int number) {
|
||||
*((volatile int*)0x10001004)|=1<<number;
|
||||
}
|
||||
static IRQ_IO irq;
|
||||
__attribute__((constructor))
|
||||
static void init_irq() {
|
||||
irqs = (IRQ*)&irq;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,12 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <irq.hpp>
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "pic.hpp"
|
||||
#include "../io.hpp"
|
||||
#include <regs.h>
|
||||
#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<uint8_t>(0x43, 0x34);
|
||||
out<uint8_t>(0x40, 156);
|
||||
out<uint8_t>(0x40, 46);
|
||||
}
|
||||
namespace PIC {
|
||||
auto sendEOI(bool slave) -> void {
|
||||
if (slave) { out<unsigned char>(PIC2_COMMAND, PIC_EOI); }
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <irq.hpp>
|
||||
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.
|
||||
|
|
26
kernel/src/include/irq.hpp
Normal file
26
kernel/src/include/irq.hpp
Normal file
|
@ -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;
|
12
kernel/src/irq.cpp
Normal file
12
kernel/src/irq.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <irq.hpp>
|
||||
IRQ *irqs;
|
||||
static void* do_nothing(void *a) {return a;}
|
||||
IRQ::IRQ() {
|
||||
for(int i=0;i<MAX_IRQ;i++)
|
||||
handlers[i]=&do_nothing;
|
||||
}
|
||||
IRQ::~IRQ() {}
|
||||
void* IRQ::handleIRQ(void *data) {return data;}
|
||||
|
||||
void IRQ::mask(int number) {};
|
||||
void IRQ::unmask(int number) {};
|
|
@ -12,9 +12,6 @@ void main() {
|
|||
drivers_init();
|
||||
*out << "Hello!\n";
|
||||
*out << "テスト\n";
|
||||
while(true) {
|
||||
out->puti((*pmm, 1));
|
||||
*out << "\n";
|
||||
}
|
||||
for(;;);
|
||||
for (auto dtor = &start_dtors; dtor != &end_dtors; dtor++) (**dtor)();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue