diff options
| author | Alexey Gavrilov <rebovas@yahoo.com> | 2024-05-24 14:07:47 +0700 |
|---|---|---|
| committer | Alexey Gavrilov <rebovas@yahoo.com> | 2024-05-24 14:07:47 +0700 |
| commit | 5fbf41e967ed8e413ecf1e6abb72e8d285169df4 (patch) | |
| tree | 48e25b199ae3459e12c7202f7b18a37cd087bf9b | |
| parent | 0a50b1758fd3da118408fd724825d0a50a9ecf17 (diff) | |
Pic + Tuple + refactor PrimaryInitialization class
| -rw-r--r-- | arch/x86/PrimaryInit.cpp | 207 | ||||
| -rw-r--r-- | arch/x86/PrimaryInit.h | 39 | ||||
| -rw-r--r-- | arch/x86/ic/IPic.h | 40 | ||||
| -rw-r--r-- | arch/x86/ic/Pic.cpp | 304 | ||||
| -rw-r--r-- | arch/x86/ic/Pic.h | 115 | ||||
| -rw-r--r-- | arch/x86/idt/Idt.cpp | 36 | ||||
| -rw-r--r-- | arch/x86/idt/Idt.h | 14 | ||||
| -rw-r--r-- | arch/x86/port/Operations | 7 | ||||
| -rw-r--r-- | arch/x86/port/PortOps.cpp | 62 | ||||
| -rw-r--r-- | arch/x86/port/PortOps.h | 26 | ||||
| -rw-r--r-- | include/ISingleton.h | 12 | ||||
| -rw-r--r-- | include/Templates.h | 127 | ||||
| -rw-r--r-- | include/containers/Tuple.h | 98 | ||||
| -rw-r--r-- | kernel/kernel.c | 28 | ||||
| -rw-r--r-- | makefile | 2 |
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); }; @@ -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 = |
