summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/PrimaryInit.cpp207
-rw-r--r--arch/x86/PrimaryInit.h39
-rw-r--r--arch/x86/ic/IPic.h40
-rw-r--r--arch/x86/ic/Pic.cpp304
-rw-r--r--arch/x86/ic/Pic.h115
-rw-r--r--arch/x86/idt/Idt.cpp36
-rw-r--r--arch/x86/idt/Idt.h14
-rw-r--r--arch/x86/port/Operations7
-rw-r--r--arch/x86/port/PortOps.cpp62
-rw-r--r--arch/x86/port/PortOps.h26
-rw-r--r--include/ISingleton.h12
-rw-r--r--include/Templates.h127
-rw-r--r--include/containers/Tuple.h98
-rw-r--r--kernel/kernel.c28
-rw-r--r--makefile2
15 files changed, 948 insertions, 169 deletions
diff --git a/arch/x86/PrimaryInit.cpp b/arch/x86/PrimaryInit.cpp
index 498a22b..bd03904 100644
--- a/arch/x86/PrimaryInit.cpp
+++ b/arch/x86/PrimaryInit.cpp
@@ -1,170 +1,162 @@
#include "PrimaryInit.h"
-#include "idt/Idt.h"
-#include "io/VGADisplay.h"
-
-
-struct InterruptFrame
-{
-#ifdef X86_64
- const uint64 ip;
- const uint64 cs;
- const uint64 flags;
-#else
- const uint32 ip;
- const uint32 cs;
- const uint32 flags;
-#endif
-};
// Test ISRs define start
-__attribute__((interrupt)) void isr0(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr0(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Divide error" << '\n';
};
-__attribute__((interrupt)) void isr1(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr1(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Debug exception" << '\n';
};
-__attribute__((interrupt)) void isr2(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr2(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "NMI interrupt" << '\n';
};
-__attribute__((interrupt)) void isr3(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr3(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Breakpoint" << '\n';
};
-__attribute__((interrupt)) void isr4(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr4(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Overflow" << '\n';
};
-__attribute__((interrupt)) void isr5(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr5(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Bound range exceed" << '\n';
};
-__attribute__((interrupt)) void isr6(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr6(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Invalid opcode" << '\n';
};
-__attribute__((interrupt)) void isr7(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr7(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "No math coprocessor" << '\n';
};
-__attribute__((interrupt)) void isr8(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr8(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Double fault" << '\n';
};
-__attribute__((interrupt)) void isr10(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr10(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Invalid TSS" << "\n";
};
-__attribute__((interrupt)) void isr11(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr11(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Segment not present" << "\n";
};
-__attribute__((interrupt)) void isr12(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr12(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Stack segment fault" << "\n";
};
-__attribute__((interrupt)) void isr13(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr13(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "#GP" << "\n";
};
-__attribute__((interrupt)) void isr14(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr14(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Page fault" << "\n";
};
-__attribute__((interrupt)) void isr16(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr16(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Math fault" << "\n";
};
-__attribute__((interrupt)) void isr17(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr17(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Alignment check" << "\n";
};
-__attribute__((interrupt)) void isr18(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr18(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Machine check" << "\n";
};
-__attribute__((interrupt)) void isr19(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr19(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "SIMD point exception" << "\n";
};
-__attribute__((interrupt)) void isr20(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isr20(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Virtualization exception" << "\n";
};
-__attribute__((interrupt)) void isr21(struct InterruptFrame *frame, uword errorCode)
+__attribute__((interrupt)) void isr21(const struct InterruptFrame *frame, const uword errorCode)
{
asm("cli\n\t");
out::display << "Control protection exception" << "\n";
};
-__attribute__((interrupt)) void isrUser(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isrUser(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "User-defined interrupt" << "\n";
};
-__attribute__((interrupt)) void isrKeyboard(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isrKeyboard(const struct InterruptFrame *frame)
{
asm("cli\n\t");
- out::display << "KINT ";
- uint8 buff[2];
-
- // PIC write EOI
- asm("in $0x60, %al");
- asm("mov %%al, %0" : "=r"(buff[0]));
- asm("in $0x64, %al");
- asm("mov %%al, %0" : "=r"(buff[1]));
- asm("mov $0x20, %al\n\t");
- asm("outb %al, $0x20\n\t");
- out::display << (uint32)buff[0] << ' ' << (uint32)buff[1] << '\n';
+ out::display << "KINT " << (uint32)PortOps::inb(0x60);
+
+ Pic::sendEoi();
};
-__attribute__((interrupt)) void isrTimer(struct InterruptFrame *frame)
+__attribute__((interrupt)) void isrTimer(const struct InterruptFrame *frame)
{
asm("cli\n\t");
out::display << "Timer interrupt" << "\n";
+
+ Pic::sendEoi();
};
//Test ISRs define end -------------------
+void isrPerform::perform(null null, DescInterrupt32 &desc) {};
+
+void isrPerform::perform(isr funp, DescInterrupt32 &desc)
+{
+ desc.setOffset((uint32)funp);
+ mngIdt.addDescriptor(desc);
+};
+
+void isrPerform::perform(isrExc funp, DescInterrupt32 &desc)
+{
+ desc.setOffset((uint32)funp);
+ mngIdt.addDescriptor(desc);
+};
+
void PrimaryInitialization::processorInitialize()
{
MngIdt &mngIdt = MngIdt::getInstance();
@@ -174,106 +166,39 @@ void PrimaryInitialization::processorInitialize()
mngGdt.addDescriptor(DescSeg32::flatDataKernel());
mngGdt.loadGdt();
-// Filling IDT start !!!REWRITE!!
+ InterruptFuncs intf = InterruptFuncs
+ (
+ isr0, isr1, isr2, isr3,
+ isr4, isr5, isr6, isr7,
+ isr8, nullptr, isr10, isr11,
+ isr12, isr13, isr14, nullptr,
+ isr16, isr17, isr18, isr19,
+ isr20, isr21, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+ isrTimer, isrKeyboard
+ );
+
DescInterrupt32 descInt = DescInterrupt32::TrapKernelLong
(
- (uint32)isr0,
+ NULL,
mngGdt.getCodeSegmentKernel()
);
- // Int 0
- mngIdt.addDescriptor(descInt);
-
- // Int 1
- descInt.setOffset((uint32)isr1);
- mngIdt.addDescriptor(descInt);
-
- // Int 2
- descInt.setOffset((uint32)isr2);
- mngIdt.addDescriptor(descInt);
-
- // Int 3
- descInt.setOffset((uint32)isr3);
- mngIdt.addDescriptor(descInt);
-
- // Int 4
- descInt.setOffset((uint32)isr4);
- mngIdt.addDescriptor(descInt);
-
- // Int 5
- descInt.setOffset((uint32)isr5);
- mngIdt.addDescriptor(descInt);
-
- // Int 6
- descInt.setOffset((uint32)isr6);
- mngIdt.addDescriptor(descInt);
-
- // Int 7
- descInt.setOffset((uint32)isr7);
- mngIdt.addDescriptor(descInt);
-
- // Int 8
- descInt.setOffset((uint32)isr8);
- mngIdt.addDescriptor(descInt);
-
- // Int 10
- descInt.setOffset((uint32)isr10);
- mngIdt.addDescriptor(descInt);
-
- // Int 11
- descInt.setOffset((uint32)isr11);
- mngIdt.addDescriptor(descInt);
-
- // Int 12
- descInt.setOffset((uint32)isr12);
- mngIdt.addDescriptor(descInt);
-
- // Int 13
- descInt.setOffset((uint32)isr13);
- mngIdt.addDescriptor(descInt);
-
- // Int 14
- descInt.setOffset((uint32)isr14);
- mngIdt.addDescriptor(descInt);
-
- // Int 16
- descInt.setOffset((uint32)isr16);
- mngIdt.addDescriptor(descInt);
-
- // Int 17
- descInt.setOffset((uint32)isr17);
- mngIdt.addDescriptor(descInt);
-
- // Int 18
- descInt.setOffset((uint32)isr18);
- mngIdt.addDescriptor(descInt);
-
- // Int 19
- descInt.setOffset((uint32)isr19);
- mngIdt.addDescriptor(descInt);
-
- // Int 20
- descInt.setOffset((uint32)isr20);
- mngIdt.addDescriptor(descInt);
-
- // Int 21
- descInt.setOffset((uint32)isr21);
- mngIdt.addDescriptor(descInt);
-
- // Int 32
- descInt.setOffset((uint32)isrTimer);
- mngIdt.setDescriptor(descInt, 32);
-
- // Int 33
- descInt.setOffset((uint32)isrKeyboard);
- mngIdt.setDescriptor(descInt, 33);
-//Filling IDT end ------------------------------
-
+ intf.foreach<isrPerform>(descInt);
mngIdt.loadIdt();
-//------------
};
void PrimaryInitialization::devicesInitialize()
{
out::display = VGADisplay();
+ picSingle = SingletonPic();
+
+ Pic *pic = picSingle.getInstance();
+
+ uint8 intn = mngIdt.getIrqInterruptStart();
+ while(intn < mngIdt.getIrqInterruptStart() + Pic::numberIrq)
+ {
+ pic->enableIrq(intn++ - mngIdt.getIrqInterruptStart());
+ }
};
diff --git a/arch/x86/PrimaryInit.h b/arch/x86/PrimaryInit.h
index 540ad41..239595d 100644
--- a/arch/x86/PrimaryInit.h
+++ b/arch/x86/PrimaryInit.h
@@ -1,10 +1,49 @@
#include "gdt/Gdt.h"
#include "io/VGADisplay.h"
#include "idt/Idt.h"
+#include "ic/Pic.h"
+#include <containers/Tuple.h>
+struct InterruptFrame
+{
+#ifdef X86_64
+ uint64 ip;
+ uint64 cs;
+ uint64 flags;
+#else
+ uint32 ip;
+ uint32 cs;
+ uint32 flags;
+#endif
+};
+
+using isr = void (*)(const InterruptFrame *frame);
+using isrExc= void (*)(const InterruptFrame *frame, uword errorCode);
+using null = decltype(nullptr);
+using InterruptFuncs = parameters<repeat<8, isr>::toList,
+ isrExc,
+ null,
+ repeat<5, isrExc>::toList,
+ null,
+ isr,
+ isrExc,
+ repeat<3, isr>::toList,
+ isrExc,
+ repeat<10, null>::toList,
+ repeat<2, isr>::toList
+ >::submitTo<Tuple>;
+struct isrPerform
+{
+ static void perform(isr funp, DescInterrupt32 &desc);
+ static void perform(isrExc funp, DescInterrupt32 &desc);
+ static void perform(null null, DescInterrupt32 &desc);
+};
+
class PrimaryInitialization
{
+ private:
+ SingletonPic picSingle;
protected:
virtual void processorInitialize();
virtual void devicesInitialize();
diff --git a/arch/x86/ic/IPic.h b/arch/x86/ic/IPic.h
new file mode 100644
index 0000000..9bb1b4f
--- /dev/null
+++ b/arch/x86/ic/IPic.h
@@ -0,0 +1,40 @@
+#ifndef IPIC_H
+#define IPIC_H
+
+#include <types.h>
+
+
+// Defines
+// ICW1
+
+#define IC4 1
+#define SNGL 2
+#define ADI 4
+#define LTIM 8
+
+// ICW4
+
+#define PM 1
+#define AEOI 2
+#define MSBUF 4
+#define BUF 8
+#define SFNM 16
+
+// PIC
+
+#define PICM_CTRL 0x20
+#define PICM_DATA 0x21
+#define PICS_CTRL 0xA0
+#define PICS_DATA 0xA1
+
+//-------------
+
+class ICW
+{
+ public:
+ virtual const uint8 toByteMasterPic() const = 0;
+ virtual const uint8 toByteSlavePic() const = 0;
+ virtual const uint8 getNumber() const = 0;
+};
+
+#endif
diff --git a/arch/x86/ic/Pic.cpp b/arch/x86/ic/Pic.cpp
new file mode 100644
index 0000000..77d9041
--- /dev/null
+++ b/arch/x86/ic/Pic.cpp
@@ -0,0 +1,304 @@
+#include "Pic.h"
+
+
+bool SingletonPic::isEntityAfter = false;
+
+ICW1::ICW1(const uint8 icw)
+{
+ word = byteHigh | (icw & 0x0f);
+};
+
+ICW1::ICW1()
+{
+ word = wordDefault;
+};
+
+bool ICW1::isExpectIcw4()
+{
+ return word & IC4;
+};
+
+const uint8 ICW1::toByteMasterPic() const
+{
+ return word;
+}
+
+const uint8 ICW1::toByteSlavePic() const
+{
+ return word;
+}
+
+const uint8 ICW1::getNumber() const
+{
+ return 1;
+};
+
+ICW2::ICW2()
+{
+ lvtAddr = mngIdt.getIrqInterruptStart();
+};
+
+ICW2::ICW2(const uint8 icw)
+{
+ if(icw >= 0xff - Pic::numberIrq) lvtAddr = MngIdt::firstSystemIntNumber;
+ else lvtAddr = icw;
+};
+
+const uint8 ICW2::getNumber() const
+{
+ return 2;
+};
+
+const uint8 ICW2::toByteMasterPic() const
+{
+ if(lvtAddr >= 0xff - Pic::numberIrq) return MngIdt::firstSystemIntNumber;
+ else return lvtAddr;
+};
+
+const uint8 ICW2::toByteSlavePic() const
+{
+ if(lvtAddr >= 0xff - 8) return MngIdt::firstSystemIntNumber + 8;
+ else return lvtAddr + 8;
+};
+
+ICW3::ICW3()
+{
+ irqConnPrimaryPic = irqTwoLine;
+ irqConnSecondaryPic = irqTwoLineBinary;
+};
+
+ICW3::ICW3(const uint8 icwMaster)
+{
+ uint8 oneAmount = 0;
+ uint8 icwMasterCpy = icwMaster;
+
+ while(icwMasterCpy)
+ {
+ oneAmount += icwMasterCpy & 0x01;
+ icwMasterCpy >>= 1;
+ }
+
+ if(oneAmount > 1)
+ {
+ *this = ICW3();
+ }
+ else
+ {
+ irqConnPrimaryPic = icwMaster;
+
+ uint8 icwMasterBinary = 0;
+ icwMasterCpy = icwMaster;
+
+ while(icwMasterCpy)
+ {
+ icwMasterBinary++;
+ icwMasterCpy >>= 1;
+ }
+ irqConnSecondaryPic = icwMasterBinary;
+ }
+};
+
+
+const uint8 ICW3::toByteMasterPic() const
+{
+ return irqConnPrimaryPic;
+};
+
+const uint8 ICW3::toByteSlavePic() const
+{
+ return irqConnSecondaryPic;
+};
+
+const uint8 ICW3::getNumber() const
+{
+ return 3;
+};
+
+ICW4::ICW4()
+{
+ word = defaultWord;
+};
+
+ICW4::ICW4(uint8 icw)
+{
+ word = icw & 0x1f;
+};
+
+const uint8 ICW4::toByteMasterPic() const
+{
+ return word;
+};
+
+const uint8 ICW4::toByteSlavePic() const
+{
+ return word;
+};
+
+const uint8 ICW4::getNumber() const
+{
+ return 4;
+};
+
+bool Pic::isIcwsCorrect(const ICW *icws[numberWords])
+{
+ for(uint8 idx = 0; idx < numberWords; idx++)
+ {
+ const ICW *currIcw = icws[idx];
+ if(currIcw->getNumber() != idx + 1)
+ {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+void Pic::disableIrq(uint8 irqNumber)
+{
+ bool isMasterPic = irqNumber < 8;
+ uint8 irqBits = 0x1 << (isMasterPic ? irqNumber : irqNumber - 8);
+ uint8 imr = PortOps::inb(isMasterPic ? PICM_DATA : PICS_DATA);
+
+ uint8 port = isMasterPic ? PICM_DATA : PICS_DATA;
+ PortOps::outb(port, imr | irqBits);
+};
+
+bool Pic::enableIrq(uint8 irqNumber)
+{
+ bool isMasterPic = irqNumber < 8;
+ uint8 irqBits = ~(0x1 << (isMasterPic ? irqNumber : irqNumber - 8));
+ uint8 imr = PortOps::inb(isMasterPic ? PICM_DATA : PICS_DATA);
+
+ if(!mngIdt.isInterruptSet(mngIdt.getIrqInterruptStart() + irqNumber))
+ {
+ // ISR not set in IDT
+ return true;
+ }
+
+ uint8 port = isMasterPic ? PICM_DATA : PICS_DATA;
+ PortOps::outb(port, imr & irqBits);
+
+ return false;
+};
+
+void Pic::disable()
+{
+ // Stop recive interrupts
+ PortOps::outb(PICM_DATA, 0xff);
+ PortOps::outb(PICS_DATA, 0xff);
+};
+
+Pic::Pic(const ICW *icws[numberWords])
+{
+ if(!isIcwsCorrect(icws))
+ {
+ *this = Pic();
+ return;
+ }
+
+ // Set ICW1 to command registers
+ PortOps::outb(PICM_CTRL, icws[NULL]->toByteMasterPic());
+ PortOps::outb(PICS_CTRL, icws[NULL]->toByteSlavePic());
+
+ for(uint8 idx = 1; idx < numberWords; idx++)
+ {
+ const ICW *currIcw = icws[idx];
+
+ if((icws[0]->toByteMasterPic() & IC4) or idx < 3)
+ {
+ PortOps::outb(PICM_DATA, currIcw->toByteMasterPic());
+ PortOps::outb(PICS_DATA, currIcw->toByteSlavePic());
+ }
+ }
+
+ // Clear data registers
+ PortOps::outb(PICM_DATA, 0x0);
+ PortOps::outb(PICS_DATA, 0x0);
+
+ // Set properties
+ icw1 = ICW1(*(ICW1 *)icws[0]);
+ icw2 = ICW2(*(ICW2 *)icws[1]);
+ icw2 = ICW2(*(ICW2 *)icws[2]);
+ icw2 = ICW2(*(ICW2 *)icws[3]);
+
+ // Disable interrupt recieve
+ Pic::disable();
+};
+
+Pic::Pic()
+{
+ ICW1 icw1;
+ ICW2 icw2;
+ ICW3 icw3;
+ ICW4 icw4;
+
+ const ICW *icws[numberWords] = {&icw1, &icw2, &icw3, &icw4};
+ *this = Pic(icws);
+};
+
+uint8 Pic::getIsrMaster()
+{
+ PortOps::outb(PICM_CTRL, readIsr);
+ return PortOps::inb(PICM_CTRL);
+};
+
+uint8 Pic::getIsrSlave()
+{
+ PortOps::outb(PICS_CTRL, readIsr);
+ return PortOps::inb(PICS_CTRL);
+};
+
+void Pic::sendEoi()
+{
+ // Recognize is the interrupt running and on which PIC is it
+ // Further, check AEOI bit in ICW4
+ // Send EOI if AEOI bit not set
+ uint16 isrFull = (uint16)getIsrSlave() << Pic::numberIrq | (uint16)getIsrMaster();
+ bool intOnMaster = (isrFull & 0x00ff) > 0;
+ bool intOnSlave = (isrFull & 0xff00) > 0;
+
+ // Interrupt not executed - EOI not send
+ if(intOnMaster == 0 and intOnSlave == 0) return;
+ // Interrupt expected only on master PIC
+ else if(intOnMaster and !intOnSlave)
+ {
+ PortOps::outb(PICM_CTRL, eoiCommand);
+ }
+ // Interrupt expected only on slave PIC
+ else if(!intOnMaster and intOnSlave)
+ {
+ PortOps::outb(PICS_CTRL, eoiCommand);
+ }
+};
+
+SingletonPic::SingletonPic() : Pic()
+{
+ if(isEntityAfter == false)
+ {
+ isEntityFirst = true;
+ isEntityAfter = true;
+ }
+ else
+ {
+ isEntityFirst = false;
+ }
+};
+
+SingletonPic::SingletonPic(const ICW *icws[numberWords]) : Pic(icws)
+{
+ if(isEntityAfter == false)
+ {
+ isEntityFirst = true;
+ isEntityAfter = true;
+ }
+ else
+ {
+ isEntityFirst = false;
+ }
+};
+
+Pic *SingletonPic::getInstance()
+{
+ if(isEntityFirst) return (Pic *)this;
+ return nullptr;
+};
diff --git a/arch/x86/ic/Pic.h b/arch/x86/ic/Pic.h
new file mode 100644
index 0000000..9739e05
--- /dev/null
+++ b/arch/x86/ic/Pic.h
@@ -0,0 +1,115 @@
+#ifndef PIC_H
+#define PIC_H
+
+#include "../idt/Idt.h"
+#include "../port/Operations"
+#include "IPic.h"
+#include <ISingleton.h>
+
+class ICW1 : public ICW
+{
+ private:
+ uint8 word;
+ public:
+ // Const part of ICW1 is high byte
+ const static uint8 byteHigh = 0x10;
+ // Inittialize bit and ICW4 recieve bit
+ const static uint8 wordDefault = byteHigh | 0x01;
+ ICW1();
+ ICW1(const uint8 icw);
+ bool isExpectIcw4();
+ virtual const uint8 toByteMasterPic() const override final;
+ virtual const uint8 toByteSlavePic() const override final;
+ virtual const uint8 getNumber() const override final;
+};
+
+class ICW2 : public ICW
+{
+ private:
+ uint8 lvtAddr;
+ public:
+ ICW2();
+ ICW2(const uint8 icw);
+ virtual const uint8 toByteMasterPic() const override final;
+ virtual const uint8 toByteSlavePic() const override final;
+ virtual const uint8 getNumber() const override final;
+};
+
+class ICW3 : public ICW
+{
+ private:
+ const static uint8 irqTwoLine = 0x4;
+ const static uint8 irqTwoLineBinary = 0x2;
+ uint8 irqConnPrimaryPic;
+ uint8 irqConnSecondaryPic;
+ public:
+ ICW3();
+ ICW3(const uint8 icwMaster);
+ virtual const uint8 toByteMasterPic() const override final;
+ virtual const uint8 toByteSlavePic() const override final;
+ virtual const uint8 getNumber() const override final;
+};
+
+class ICW4 : public ICW
+{
+ private:
+ static const uint8 defaultWord = 0x01;
+ uint8 word;
+ public:
+ ICW4();
+ ICW4(const uint8 icw);
+ virtual const uint8 toByteMasterPic() const override final;
+ virtual const uint8 toByteSlavePic() const override final;
+ virtual const uint8 getNumber() const override final;
+};
+
+class Pic
+{
+ protected:
+
+ static const uint8 numberWords = 4;
+ static const uint8 readIrr = 0xa;
+ static const uint8 readIsr = 0xb;
+ static const uint8 eoiCommand = 0x20;
+
+ private:
+ ICW1 icw1;
+ ICW2 icw2;
+ ICW3 icw3;
+ ICW4 icw4;
+ bool isIcwsCorrect(const ICW *icws[numberWords]);
+
+ protected:
+ Pic();
+ Pic(const ICW *icws[numberWords]);
+ Pic(const Pic &) = default;
+
+ public:
+ static const uint8 numberIrq = 16;
+ // Valid equals from 0 to 7 and from 8 to 15
+ // Return true if ISR not set, false is success
+ bool enableIrq(uint8 irqNumber);
+ void disableIrq(uint8 irqNumber);
+ static uint8 getIsrMaster();
+ static uint8 getIsrSlave();
+ static uint8 getIrrMaster();
+ static void sendEoi();
+ // Set IMR to -xff
+ static void disable();
+};
+
+// Be more careful with instance of Pic.
+// When SingletonPic instance been deleted, Pic instance not be more exist
+class SingletonPic : public Pic, public ISingleton<Pic>
+{
+ private:
+ static bool isEntityAfter;
+ bool isEntityFirst;
+
+ public:
+ SingletonPic();
+ SingletonPic(const ICW *icws[numberWords]);
+ virtual Pic *getInstance() override final;
+};
+
+#endif
diff --git a/arch/x86/idt/Idt.cpp b/arch/x86/idt/Idt.cpp
index cd263fb..e24cbfe 100644
--- a/arch/x86/idt/Idt.cpp
+++ b/arch/x86/idt/Idt.cpp
@@ -30,7 +30,7 @@ DescInterrupt32::DescInterrupt32(uint32 offset, uint16 selector, uint8 attr)
}
};
-uint64 DescInterrupt32::getDescriptor()
+uint64 DescInterrupt32::getDescriptor() const
{
uint64 desc = 0;
@@ -42,6 +42,11 @@ uint64 DescInterrupt32::getDescriptor()
return desc;
};
+uint32 DescInterrupt32::getOffset() const
+{
+ return offsetLow | offsetHight << 16;
+};
+
DescInterrupt32 DescInterrupt32::InterruptKernelLong(uint32 offset, uint16 selector)
{
return DescInterrupt32(
@@ -86,6 +91,7 @@ MngIdt::MngIdt()
currIdx = NULL;
idtLoaded = false;
isInitialize = true;
+ irqInterruptStart = firstSystemIntNumber;
}
};
@@ -97,10 +103,24 @@ bool MngIdt::canDescriptorWrite(uint8 idx)
bool MngIdt::addDescriptor(DescInterrupt32 desc)
{
- if(!canDescriptorWrite(currIdx) or isIntReserved(currIdx)) return false;
+ uint64 descqw = desc.getDescriptor();
+
+ if(!canDescriptorWrite(currIdx) or isIntReserved(currIdx)
+ or desc.getOffset() == NULL) return false;
+
+ idt[currIdx] = descqw;
+
+ uint8 attributes = descqw >> 40;
+
+ if((attributes & RING_DRIVERSH or
+ attributes & RING_DRIVERSL) and
+ (irqInterruptStart == firstSystemIntNumber))
+ {
+ irqInterruptStart = (uint8)(descqw >> 16);
+ }
- idt[currIdx] = desc.getDescriptor();
while(isIntReserved(++currIdx));
+
return true;
};
@@ -168,3 +188,13 @@ void DescInterrupt32::setDpl(uint8 dpl)
{
attributes = (dpl & 0x03) << 5;
};
+
+bool MngIdt::isInterruptSet(uint8 numberInterrupt)
+{
+ return idt[numberInterrupt];
+};
+
+uint8 MngIdt::getIrqInterruptStart()
+{
+ return irqInterruptStart;
+};
diff --git a/arch/x86/idt/Idt.h b/arch/x86/idt/Idt.h
index 7370526..3054fd5 100644
--- a/arch/x86/idt/Idt.h
+++ b/arch/x86/idt/Idt.h
@@ -35,8 +35,9 @@ class DescInterrupt32
void setOffset(uint32 offset);
void setGateType(uint8 gateType);
void setDpl(uint8 dpl);
- uint64 getDescriptor();
- static DescInterrupt32 InterruptKernelLong(uint32 offset,
+ uint64 getDescriptor() const;
+ uint32 getOffset() const;
+ static DescInterrupt32 InterruptKernelLong(uint32 offset,
uint16 selector);
static DescInterrupt32 TrapKernelLong(uint32 offset,
uint16 selector);
@@ -47,7 +48,7 @@ class MngIdt
{
private:
const static uint8 reservedIntSize = 12;
- constexpr static uint8 reservedInts[reservedIntSize] =
+ constexpr static uint8 reservedInts[reservedIntSize] =
{
9, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
@@ -58,7 +59,12 @@ class MngIdt
static bool isInitialize;
static bool idtLoaded;
uint8 currIdx;
+ // Start number of interrupts that service IRQ
+ // Accpet this number as first interrupt descriptor
+ // with dpl = 2 or 3 (drivers)
+ uint8 irqInterruptStart;
public:
+ const static uint8 firstSystemIntNumber = 0x20;
MngIdt();
MngIdt(const MngIdt &) = delete;
bool addDescriptor(DescInterrupt32 desc);
@@ -66,6 +72,8 @@ class MngIdt
bool canDescriptorWrite(uint8 idx);
bool loadIdt();
static MngIdt &getInstance();
+ uint8 getIrqInterruptStart();
+ bool isInterruptSet(uint8 numberInterrupt);
};
extern MngIdt mngIdt;
diff --git a/arch/x86/port/Operations b/arch/x86/port/Operations
new file mode 100644
index 0000000..4812518
--- /dev/null
+++ b/arch/x86/port/Operations
@@ -0,0 +1,7 @@
+#ifndef PORTOPEARATION_H
+#define PORTOPEARATION_H
+
+#include "PortOps.h"
+
+#endif
+
diff --git a/arch/x86/port/PortOps.cpp b/arch/x86/port/PortOps.cpp
new file mode 100644
index 0000000..4b418dd
--- /dev/null
+++ b/arch/x86/port/PortOps.cpp
@@ -0,0 +1,62 @@
+#include "PortOps.h"
+
+
+void PortOps::outb(portadr port, regb value)
+{
+ asm("outb %b0, %w1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+};
+
+void PortOps::outw(portadr port, regw value)
+{
+ asm("out %w0, %w1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+};
+
+void PortOps::outl(portadr port, regl value)
+{
+ asm("out %k0, %w1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+};
+
+regb PortOps::inb(portadr port)
+{
+ regb res;
+
+ asm("in %w1, %b0"
+ : "=a"(res)
+ : "Nd"(port)
+ : "memory");
+
+ return res;
+};
+
+regw PortOps::inw(portadr port)
+{
+ regw res;
+
+ asm("in %w1, %w0"
+ : "=a"(res)
+ : "Nd"(port)
+ : "memory");
+
+ return res;
+};
+
+regl PortOps::inl(portadr port)
+{
+ regl res;
+
+ asm("in %w1, %k0"
+ : "=a"(res)
+ : "Nd"(port)
+ : "memory");
+
+ return res;
+};
diff --git a/arch/x86/port/PortOps.h b/arch/x86/port/PortOps.h
new file mode 100644
index 0000000..7db3a5f
--- /dev/null
+++ b/arch/x86/port/PortOps.h
@@ -0,0 +1,26 @@
+#ifndef PORT_H
+#define PORT_H
+
+#include <types.h>
+
+
+using regb = uint8;
+using regw = uint16;
+using regl = uint32;
+using portadr = uint16;
+
+class PortOps
+{
+ public:
+ static void outb(portadr port, regb value);
+ static void outw(portadr port, regw value);
+ static void outl(portadr port, regl value);
+ // Get byte from port
+ static regb inb(portadr port);
+ // Get word from port
+ static regw inw(portadr port);
+ // Get double word from port
+ static regl inl(portadr port);
+};
+
+#endif
diff --git a/include/ISingleton.h b/include/ISingleton.h
new file mode 100644
index 0000000..1dcd0d1
--- /dev/null
+++ b/include/ISingleton.h
@@ -0,0 +1,12 @@
+#ifndef SINGLETON_H
+#define SINGLETON_H
+
+
+template <typename T>
+class ISingleton
+{
+ public:
+ virtual T *getInstance() = 0;
+};
+
+#endif
diff --git a/include/Templates.h b/include/Templates.h
new file mode 100644
index 0000000..8a1bd95
--- /dev/null
+++ b/include/Templates.h
@@ -0,0 +1,127 @@
+#ifndef TEMPLATES_H
+#define TEMPLATES_H
+
+
+#include <types.h>
+
+template<typename T, T val>
+struct constant
+{
+ static constexpr T value = val;
+ T& operator()() {return value;}
+};
+
+template<typename T, typename U>
+struct isSame
+{
+ using cnst = constant<bool, false>;
+ bool static inline constexpr val(){return cnst::value;};
+ constexpr operator bool() const {return cnst::value;}
+ bool constexpr operator()() {return cnst::value;}
+};
+
+template<typename T>
+struct isSame<T, T>
+{
+ using cnst = constant<bool, true>;
+ constexpr operator bool() const {return cnst::value;}
+ bool static inline constexpr val(){return cnst::value;};
+ bool constexpr operator()() {return cnst::value;}
+};
+
+template <typename ... params>
+struct parametersOperations
+{
+ template<typename Head, typename ... Tail>
+ using first = Head;
+
+ template<typename Head, typename ... Tail>
+ using tail = parametersOperations<Tail ...>;
+
+ // Append operation
+ template<typename Head, typename ... Tail>
+ struct append
+ {
+ using result = parametersOperations<params ..., Head>::template append<Tail ...>::result;
+ };
+
+ template<template <typename ... NestedList> typename NestedType, typename ... NestedList, typename ... OuterList>
+ requires(isSame<NestedType<>, parametersOperations<>>::val())
+ struct append<NestedType<NestedList ...>, OuterList ...>
+ {
+ using result = parametersOperations<params..., NestedList ...>::template append<OuterList ...>::result;
+ };
+
+ template<template <typename ... NestedList> typename NestedType, typename ... NestedList>
+ requires(isSame<NestedType<>, parametersOperations<>>::val())
+ struct append<NestedType<NestedList ...>>
+ {
+ using result = parametersOperations<params..., NestedList ...>;
+ };
+
+ template<typename One>
+ struct append<One> {using result = parametersOperations<params ..., One>;};
+};
+
+template< unsigned I, typename T>
+struct cut
+{
+ using process = cut<I - 1, typename T::baseType>::process;
+};
+
+template<typename T>
+struct cut<0, T>
+{
+ using process = cut<0, T>;
+ using result = T;
+};
+
+template<uint16 N, typename Head, typename ... Args>
+struct reper
+{
+ using toList = typename reper<N-1, Head, Head, Args ...>::toList;
+};
+
+template<uint16 N, typename Type>
+struct repeat
+{
+ using toList = typename reper<N-1, Type>::toList;
+};
+
+template<typename Type>
+struct repeat<0, Type> {};
+
+template<typename Head, typename ... Args>
+struct reper<0, Head, Args ...>
+{
+ using toList = parametersOperations<Head, Args ...>;
+};
+
+template<typename Root, typename toType>
+struct switchRoot {using result = toType;};
+
+template<template <typename ... RootList> typename RootType, template <typename ... toTypeListArgs> typename toType, typename ... RootList, typename ... toTypeListArgs>
+struct switchRoot<RootType<RootList ...>, toType<toTypeListArgs ...>>{using result = toType<RootList ...>;};
+
+template<typename arg, template<typename ... toTypeListArgs> typename toType, typename ... toTypeListArgs>
+struct switchRoot<arg, toType<toTypeListArgs ...>>{using result = toType<arg>;};
+
+template<typename arg, typename ... args>
+struct parameters
+{
+ public:
+ using baseType = parameters<args ...>;
+ using types = parametersOperations<>::template append<arg, typename baseType::types>::result;
+ template<template <typename ... > typename T>
+ using submitTo = switchRoot<types, T<>>::result;
+};
+
+template<typename arg>
+struct parameters<arg>
+{
+ public:
+ using types = arg;
+ template<template <typename ... > typename T>
+ using submitTo = switchRoot<types, T<>>::result;
+};
+#endif
diff --git a/include/containers/Tuple.h b/include/containers/Tuple.h
new file mode 100644
index 0000000..cf870d1
--- /dev/null
+++ b/include/containers/Tuple.h
@@ -0,0 +1,98 @@
+#ifndef CONTAINERSTUPLE_H
+#define CONTAINERSTUPLE_H
+
+
+#include <Templates.h>
+
+template<typename Head = void, typename ... Tail>
+class Tuple : public Tuple<Tail ...>
+{
+ private:
+ using valueType = Head;
+ valueType value;
+ public:
+ using baseType = Tuple<Tail ...>;
+ Tuple(Head val_, Tail ... args) : baseType(args ...), value(val_) {};
+
+ static constexpr unsigned int length() {return sizeof...(Tail) + 1;}
+ valueType getValue() {return value;};
+
+ template<uint16 indx>
+ auto get()
+ {
+ using returnType = cut<indx, Tuple>::process::result;
+ return static_cast<returnType>(*this);
+ };
+
+ /*
+ Create the class/struct before using the method
+ F is this class/struct to pass in method trought template argument.
+ F must contain a static method/s named "perform"
+ that will perform something action for every value in tuple object.
+ F must contain as many implementations
+ as there are different types in the template
+ F::perform() for the first argument accept tuple value,
+ next arguments optional
+ */
+ template<typename F, uint16 If = length() - 1, uint16 ... I,
+ typename Mid = void, typename ... T>
+ void foreach(T ... arg)
+ {
+ if constexpr(If != NULL)
+ {
+ foreach<F, If - 1, If, I ...>(arg ...);
+ }
+ else
+ {
+ (F::perform(get<If>().getValue(), arg ...));
+ (F::perform(get<I>().getValue(), arg ...), ...);
+ }
+ };
+};
+
+template<>
+class Tuple<>
+{
+ public:
+ static constexpr unsigned int length() {return 0;}
+};
+
+template<typename Head>
+class Tuple<Head>
+{
+ private:
+ using valueType = Head;
+ valueType value;
+ public:
+ using baseType = Tuple<>;
+ Tuple(Head val_) : value(val_) {};
+ Tuple() : value(valueType()) {};
+
+ static constexpr unsigned int length() {return 1;}
+ valueType getValue() {return value;};
+
+ template<uint16 indx>
+ auto get()
+ {
+ if constexpr (indx == NULL) return *this;
+ else static_assert(!indx, "Tuple::get<indx>: Out of bounds");
+ };
+
+ /*
+ Create the class/struct before using the method
+ F is this class/struct to pass in method trought template argument.
+ F must contain a static method/s named "perform"
+ that will perform something action for every value in tuple object.
+ F must contain as many implementations
+ as there are different types in the template
+ F::perform() for the first argument accept tuple value,
+ next arguments optional
+ */
+ template<typename F, typename ... T>
+ void foreach(T ... arg)
+ {
+ F::perform(value, arg ...);
+ };
+};
+
+#endif
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 09152b8..c280755 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -1,6 +1,7 @@
+
#include "../arch/SecondaryInit.h"
-#include "../drivers/acpi/Acpi.h"
-#include <StringOperations.h>
+#include "../arch/x86/ic/Pic.h"
+
void empty() {};
@@ -8,26 +9,11 @@ void main()
{
SecondaryInitialization init;
- init.devicesInitialize();
init.processorInitialize();
+ init.devicesInitialize();
out::display << "Hello, World!\n";
- Rsdp *rsdp = (Rsdp *)StringOperations::findInMemory(Rsdp::signatureString,
- MemArea(
- Rsdp::romAreaStart,
- Rsdp::romAreaEnd));
- const Rsdt *rsdt = rsdp->getRsdt();
- const Entry *entry = rsdt->getEntry(1);
- const Madt *madt = (Madt *)entry;
- const Ics *icsEntry[10] = {madt->getIcs(0),
- madt->getIcs(1),
- madt->getIcs(2),
- madt->getIcs(3),
- madt->getIcs(4),
- madt->getIcs(5),
- madt->getIcs(6),
- madt->getIcs(7),
- madt->getIcs(8)};
- const IoapicStruct *ioapicStruct = (IoapicStruct *)icsEntry[1];
- empty();
+
+ asm("sti");
+ while(true);
};
diff --git a/makefile b/makefile
index aaf6cc3..fc3286a 100644
--- a/makefile
+++ b/makefile
@@ -2,7 +2,7 @@ CC = i686-elf-g++
LD = ld
ASM = nasm
# test -O2 flag
-CFLAGS = -c -m32 -Wall -ffreestanding -nostdinc -nostdlib -fno-rtti -mgeneral-regs-only
+CFLAGS = -std=c++20 -c -m32 -Wall -ffreestanding -nostdinc -nostdlib -fno-rtti -mgeneral-regs-only
AFLAGS = -f elf32
LDFLAGS = -m elf_i386 $(patsubst %,-L%,$(subst :, ,$(LIBS_PATH))) -lgcc
QEMUFLAGS =