diff options
| author | Alexey Gavrilov <90127298+rebovas@users.noreply.github.com> | 2024-05-24 14:33:19 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-24 14:33:19 +0700 |
| commit | dc0b89fa63a181bd4add318bfd7a46344702f4e7 (patch) | |
| tree | 48e25b199ae3459e12c7202f7b18a37cd087bf9b /arch | |
| parent | 0a50b1758fd3da118408fd724825d0a50a9ecf17 (diff) | |
| parent | 5fbf41e967ed8e413ecf1e6abb72e8d285169df4 (diff) | |
Pic + Tuple + refactor PrimaryInitialization class
Diffstat (limited to 'arch')
| -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 |
10 files changed, 703 insertions, 147 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 |
