From c5b4666b50785c5be83e94b602cac70d81489440 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Oct 2022 01:43:00 +0300 Subject: [PATCH] Implemented PIC (untested code) --- Core/Interrupts/8259PIC.cpp | 123 ++++++++++++++++++++++++++++++++++++ Core/Interrupts/pic.hpp | 42 ++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 Core/Interrupts/8259PIC.cpp create mode 100644 Core/Interrupts/pic.hpp diff --git a/Core/Interrupts/8259PIC.cpp b/Core/Interrupts/8259PIC.cpp new file mode 100644 index 0000000..b04aeec --- /dev/null +++ b/Core/Interrupts/8259PIC.cpp @@ -0,0 +1,123 @@ +#include "pic.hpp" + +#include + +namespace PIC +{ + PIC::PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset) + { + this->MasterCommandPort = MasterCommandPort; + this->MasterDataPort = MasterDataPort; + this->SlaveCommandPort = SlaveCommandPort; + this->SlaveDataPort = SlaveDataPort; + this->MasterOffset = MasterOffset; + this->SlaveOffset = SlaveOffset; + + MasterMask = 0xFF; + SlaveMask = 0xFF; + + // ICW1 + outb(MasterCommandPort, 0x11); + outb(SlaveCommandPort, 0x11); + + // ICW2 + outb(MasterDataPort, MasterOffset); + outb(SlaveDataPort, SlaveOffset); + + // ICW3 + outb(MasterDataPort, 0x04); + outb(SlaveDataPort, 0x02); + + // ICW4 + outb(MasterDataPort, 0x01); + outb(SlaveDataPort, 0x01); + + // OCW1 + outb(MasterDataPort, MasterMask); + outb(SlaveDataPort, SlaveMask); + } + + PIC::~PIC() + { + outb(MasterDataPort, 0xFF); + outb(SlaveDataPort, 0xFF); + } + + void PIC::Mask(uint8_t IRQ) + { + uint16_t Port; + uint8_t Value; + + if (IRQ < 8) + { + Port = MasterDataPort; + Value = MasterMask & ~(1 << IRQ); + MasterMask = Value; + } + else + { + Port = SlaveDataPort; + Value = SlaveMask & ~(1 << (IRQ - 8)); + SlaveMask = Value; + } + + outb(Port, Value); + } + + void PIC::Unmask(uint8_t IRQ) + { + uint16_t Port; + uint8_t Value; + + if (IRQ < 8) + { + Port = MasterDataPort; + Value = MasterMask | (1 << IRQ); + MasterMask = Value; + } + else + { + Port = SlaveDataPort; + Value = SlaveMask | (1 << (IRQ - 8)); + SlaveMask = Value; + } + + outb(Port, Value); + } + + void PIC::SendEOI(uint8_t IRQ) + { + if (IRQ >= 8) + outb(SlaveCommandPort, 0x20); + + outb(MasterCommandPort, 0x20); + } + + PIT::PIT(uint16_t Port, uint16_t Frequency) + { + this->Port = Port; + this->Frequency = Frequency; + } + + PIT::~PIT() + { + } + + void PIT::PrepareSleep(uint32_t Milliseconds) + { + uint16_t Divisor = 1193182 / Frequency; + uint8_t Low = (uint8_t)(Divisor & 0xFF); + uint8_t High = (uint8_t)((Divisor >> 8) & 0xFF); + + outb(Port + 3, 0x36); + outb(Port + 0, Low); + outb(Port + 1, High); + } + + void PIT::PerformSleep() + { + uint8_t Value = inb(Port + 0); + while (Value != 0) + Value = inb(Port + 0); + } +} diff --git a/Core/Interrupts/pic.hpp b/Core/Interrupts/pic.hpp new file mode 100644 index 0000000..893e73b --- /dev/null +++ b/Core/Interrupts/pic.hpp @@ -0,0 +1,42 @@ +#ifndef __FENNIX_KERNEL_8259PIC_H__ +#define __FENNIX_KERNEL_8259PIC_H__ + +#include + +namespace PIC +{ + class PIC + { + private: + uint8_t MasterCommandPort; + uint8_t MasterDataPort; + uint8_t SlaveCommandPort; + uint8_t SlaveDataPort; + uint8_t MasterOffset; + uint8_t SlaveOffset; + uint8_t MasterMask; + uint8_t SlaveMask; + + public: + PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset); + ~PIC(); + void Mask(uint8_t IRQ); + void Unmask(uint8_t IRQ); + void SendEOI(uint8_t IRQ); + }; + + class PIT + { + private: + uint16_t Port; + uint16_t Frequency; + + public: + PIT(uint16_t Port, uint16_t Frequency); + ~PIT(); + void PrepareSleep(uint32_t Milliseconds); + void PerformSleep(); + }; +} + +#endif // !__FENNIX_KERNEL_8259PIC_H__