summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlexey Gavrilov <90127298+rebovas@users.noreply.github.com>2024-05-24 14:33:19 +0700
committerGitHub <noreply@github.com>2024-05-24 14:33:19 +0700
commitdc0b89fa63a181bd4add318bfd7a46344702f4e7 (patch)
tree48e25b199ae3459e12c7202f7b18a37cd087bf9b /arch
parent0a50b1758fd3da118408fd724825d0a50a9ecf17 (diff)
parent5fbf41e967ed8e413ecf1e6abb72e8d285169df4 (diff)
Merge pull request #9 from rebovas/interrupts_picHEADmain
Pic + Tuple + refactor PrimaryInitialization class
Diffstat (limited to 'arch')
-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
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