Kernel: Rework interrupt mechanism
All interruptrable classes now inherit from Interruptable which has methdo handle_irq which is called on a interrupt.
This commit is contained in:
@@ -4,51 +4,56 @@
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
|
||||
class APIC final : public InterruptController
|
||||
namespace Kernel
|
||||
{
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
private:
|
||||
uint32_t read_from_local_apic(ptrdiff_t);
|
||||
void write_to_local_apic(ptrdiff_t, uint32_t);
|
||||
|
||||
private:
|
||||
~APIC() { ASSERT_NOT_REACHED(); }
|
||||
static APIC* create();
|
||||
friend class InterruptController;
|
||||
|
||||
private:
|
||||
struct Processor
|
||||
class APIC final : public InterruptController
|
||||
{
|
||||
enum Flags : uint8_t
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
private:
|
||||
uint32_t read_from_local_apic(ptrdiff_t);
|
||||
void write_to_local_apic(ptrdiff_t, uint32_t);
|
||||
|
||||
private:
|
||||
~APIC() { ASSERT_NOT_REACHED(); }
|
||||
static APIC* create();
|
||||
friend class InterruptController;
|
||||
|
||||
private:
|
||||
struct Processor
|
||||
{
|
||||
Enabled = 1,
|
||||
OnlineCapable = 2,
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
Enabled = 1,
|
||||
OnlineCapable = 2,
|
||||
};
|
||||
uint8_t processor_id;
|
||||
uint8_t apic_id;
|
||||
uint8_t flags;
|
||||
};
|
||||
uint8_t processor_id;
|
||||
uint8_t apic_id;
|
||||
uint8_t flags;
|
||||
|
||||
struct IOAPIC
|
||||
{
|
||||
uint8_t id;
|
||||
Kernel::paddr_t paddr;
|
||||
Kernel::vaddr_t vaddr;
|
||||
uint32_t gsi_base;
|
||||
uint8_t max_redirs;
|
||||
|
||||
uint32_t read(uint8_t offset);
|
||||
void write(uint8_t offset, uint32_t data);
|
||||
};
|
||||
|
||||
private:
|
||||
BAN::Vector<Processor> m_processors;
|
||||
Kernel::paddr_t m_local_apic_paddr = 0;
|
||||
Kernel::vaddr_t m_local_apic_vaddr = 0;
|
||||
BAN::Vector<IOAPIC> m_io_apics;
|
||||
uint8_t m_irq_overrides[0x100] {};
|
||||
};
|
||||
|
||||
struct IOAPIC
|
||||
{
|
||||
uint8_t id;
|
||||
Kernel::paddr_t paddr;
|
||||
Kernel::vaddr_t vaddr;
|
||||
uint32_t gsi_base;
|
||||
uint8_t max_redirs;
|
||||
|
||||
uint32_t read(uint8_t offset);
|
||||
void write(uint8_t offset, uint32_t data);
|
||||
};
|
||||
|
||||
private:
|
||||
BAN::Vector<Processor> m_processors;
|
||||
Kernel::paddr_t m_local_apic_paddr = 0;
|
||||
Kernel::vaddr_t m_local_apic_vaddr = 0;
|
||||
BAN::Vector<IOAPIC> m_io_apics;
|
||||
uint8_t m_irq_overrides[0x100] {};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
|
||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||
|
||||
namespace IDT
|
||||
namespace Kernel::IDT
|
||||
{
|
||||
|
||||
void initialize();
|
||||
void register_irq_handler(uint8_t irq, void(*f)());
|
||||
[[noreturn]] void force_triple_fault();
|
||||
|
||||
}
|
||||
97
kernel/include/kernel/Input/PS2Config.h
Normal file
97
kernel/include/kernel/Input/PS2Config.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::Input::PS2
|
||||
{
|
||||
|
||||
enum IOPort : uint8_t
|
||||
{
|
||||
DATA = 0x60,
|
||||
STATUS = 0x64,
|
||||
COMMAND = 0x64,
|
||||
};
|
||||
|
||||
enum Status : uint8_t
|
||||
{
|
||||
OUTPUT_FULL = (1 << 0),
|
||||
INPUT_FULL = (1 << 1),
|
||||
SYSTEM = (1 << 2),
|
||||
DEVICE_OR_CONTROLLER = (1 << 3),
|
||||
TIMEOUT_ERROR = (1 << 6),
|
||||
PARITY_ERROR = (1 << 7),
|
||||
};
|
||||
|
||||
enum Config : uint8_t
|
||||
{
|
||||
INTERRUPT_FIRST_PORT = (1 << 0),
|
||||
INTERRUPT_SECOND_PORT = (1 << 1),
|
||||
SYSTEM_FLAG = (1 << 2),
|
||||
ZERO1 = (1 << 3),
|
||||
CLOCK_FIRST_PORT = (1 << 4),
|
||||
CLOCK_SECOND_PORT = (1 << 5),
|
||||
TRANSLATION_FIRST_PORT = (1 << 6),
|
||||
ZERO2 = (1 << 7),
|
||||
};
|
||||
|
||||
enum Command : uint8_t
|
||||
{
|
||||
READ_CONFIG = 0x20,
|
||||
WRITE_CONFIG = 0x60,
|
||||
DISABLE_SECOND_PORT = 0xA7,
|
||||
ENABLE_SECOND_PORT = 0xA8,
|
||||
TEST_SECOND_PORT = 0xA9,
|
||||
TEST_CONTROLLER = 0xAA,
|
||||
TEST_FIRST_PORT = 0xAB,
|
||||
DISABLE_FIRST_PORT = 0xAD,
|
||||
ENABLE_FIRST_PORT = 0xAE,
|
||||
WRITE_TO_SECOND_PORT = 0xD4,
|
||||
};
|
||||
|
||||
enum Response : uint8_t
|
||||
{
|
||||
TEST_FIRST_PORT_PASS = 0x00,
|
||||
TEST_SECOND_PORT_PASS = 0x00,
|
||||
TEST_CONTROLLER_PASS = 0x55,
|
||||
SELF_TEST_PASS = 0xAA,
|
||||
ACK = 0xFA,
|
||||
};
|
||||
|
||||
enum DeviceCommand : uint8_t
|
||||
{
|
||||
ENABLE_SCANNING = 0xF4,
|
||||
DISABLE_SCANNING = 0xF5,
|
||||
IDENTIFY = 0xF2,
|
||||
RESET = 0xFF,
|
||||
};
|
||||
|
||||
enum IRQ : uint8_t
|
||||
{
|
||||
DEVICE0 = 1,
|
||||
DEVICE1 = 12,
|
||||
};
|
||||
|
||||
enum KBResponse : uint8_t
|
||||
{
|
||||
KEY_ERROR_OR_BUFFER_OVERRUN1 = 0x00,
|
||||
SELF_TEST_PASSED = 0xAA,
|
||||
ECHO_RESPONSE = 0xEE,
|
||||
RESEND = 0xFE,
|
||||
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
|
||||
};
|
||||
|
||||
enum KBScancode : uint8_t
|
||||
{
|
||||
SET_SCANCODE_SET1 = 1,
|
||||
SET_SCANCODE_SET2 = 2,
|
||||
SET_SCANCODE_SET3 = 3,
|
||||
};
|
||||
|
||||
enum KBLeds : uint8_t
|
||||
{
|
||||
SCROLL_LOCK = (1 << 0),
|
||||
NUM_LOCK = (1 << 1),
|
||||
CAPS_LOCK = (1 << 2),
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
class PS2Device : public CharacterDevice
|
||||
class PS2Device : public CharacterDevice, public Interruptable
|
||||
{
|
||||
public:
|
||||
virtual ~PS2Device() {}
|
||||
virtual void on_byte(uint8_t) = 0;
|
||||
|
||||
|
||||
public:
|
||||
PS2Device()
|
||||
: CharacterDevice(Mode::IRUSR | Mode::IRGRP, 0, 0)
|
||||
@@ -33,11 +33,8 @@ namespace Kernel::Input
|
||||
BAN::ErrorOr<void> reset_device(uint8_t);
|
||||
BAN::ErrorOr<void> set_scanning(uint8_t, bool);
|
||||
|
||||
static void device0_irq();
|
||||
static void device1_irq();
|
||||
|
||||
private:
|
||||
PS2Device* m_devices[2] { nullptr, nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Kernel::Input
|
||||
public:
|
||||
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
|
||||
|
||||
virtual void on_byte(uint8_t) override;
|
||||
virtual void handle_irq() override;
|
||||
virtual void update() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,22 +5,42 @@
|
||||
#define DISABLE_INTERRUPTS() asm volatile("cli")
|
||||
#define ENABLE_INTERRUPTS() asm volatile("sti")
|
||||
|
||||
class InterruptController
|
||||
namespace Kernel
|
||||
{
|
||||
public:
|
||||
virtual ~InterruptController() {}
|
||||
|
||||
virtual void eoi(uint8_t) = 0;
|
||||
virtual void enable_irq(uint8_t) = 0;
|
||||
virtual bool is_in_service(uint8_t) = 0;
|
||||
class Interruptable
|
||||
{
|
||||
public:
|
||||
Interruptable() = default;
|
||||
|
||||
static void initialize(bool force_pic);
|
||||
static InterruptController& get();
|
||||
void set_irq(int irq);
|
||||
void enable_interrupt();
|
||||
void disable_interrupt();
|
||||
|
||||
void enter_acpi_mode();
|
||||
virtual void handle_irq() = 0;
|
||||
|
||||
private:
|
||||
bool m_using_apic { false };
|
||||
};
|
||||
private:
|
||||
int m_irq { -1 };
|
||||
};
|
||||
|
||||
bool interrupts_enabled();
|
||||
class InterruptController
|
||||
{
|
||||
public:
|
||||
virtual ~InterruptController() {}
|
||||
|
||||
virtual void eoi(uint8_t) = 0;
|
||||
virtual void enable_irq(uint8_t) = 0;
|
||||
virtual bool is_in_service(uint8_t) = 0;
|
||||
|
||||
static void initialize(bool force_pic);
|
||||
static InterruptController& get();
|
||||
|
||||
void enter_acpi_mode();
|
||||
|
||||
private:
|
||||
bool m_using_apic { false };
|
||||
};
|
||||
|
||||
bool interrupts_enabled();
|
||||
|
||||
}
|
||||
@@ -2,17 +2,22 @@
|
||||
|
||||
#include <kernel/InterruptController.h>
|
||||
|
||||
class PIC final : public InterruptController
|
||||
namespace Kernel
|
||||
{
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
static void remap();
|
||||
static void mask_all();
|
||||
class PIC final : public InterruptController
|
||||
{
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
private:
|
||||
static PIC* create();
|
||||
friend class InterruptController;
|
||||
};
|
||||
static void remap();
|
||||
static void mask_all();
|
||||
|
||||
private:
|
||||
static PIC* create();
|
||||
friend class InterruptController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Errors.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/SpinLock.h>
|
||||
#include <kernel/Storage/ATAController.h>
|
||||
|
||||
@@ -9,7 +10,7 @@ namespace Kernel
|
||||
|
||||
class ATADevice;
|
||||
|
||||
class ATABus
|
||||
class ATABus : public Interruptable
|
||||
{
|
||||
public:
|
||||
enum class DeviceType
|
||||
@@ -27,7 +28,7 @@ namespace Kernel
|
||||
|
||||
ATAController& controller() { return m_controller; }
|
||||
|
||||
void on_irq();
|
||||
virtual void handle_irq() override;
|
||||
|
||||
private:
|
||||
ATABus(ATAController& controller, uint16_t base, uint16_t ctrl)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <BAN/Errors.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Terminal/TTY.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -34,7 +36,7 @@ namespace Kernel
|
||||
uint32_t m_height { 0 };
|
||||
};
|
||||
|
||||
class SerialTTY final : public TTY
|
||||
class SerialTTY final : public TTY, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<SerialTTY>> create(Serial);
|
||||
@@ -45,6 +47,8 @@ namespace Kernel
|
||||
|
||||
virtual void update() override;
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
protected:
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
@@ -55,6 +59,7 @@ namespace Kernel
|
||||
private:
|
||||
BAN::String m_name;
|
||||
Serial m_serial;
|
||||
BAN::CircularQueue<uint8_t, 128> m_input;
|
||||
|
||||
public:
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class HPET final : public Timer
|
||||
class HPET final : public Timer, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(bool force_pic);
|
||||
@@ -13,6 +14,8 @@ namespace Kernel
|
||||
virtual uint64_t ms_since_boot() const override;
|
||||
virtual timespec time_since_boot() const override;
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
private:
|
||||
HPET() = default;
|
||||
BAN::ErrorOr<void> initialize(bool force_pic);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PIT_IRQ 0
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class PIT final : public Timer
|
||||
class PIT final : public Timer, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<PIT>> create();
|
||||
@@ -16,8 +14,13 @@ namespace Kernel
|
||||
virtual uint64_t ms_since_boot() const override;
|
||||
virtual timespec time_since_boot() const override;
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
volatile uint64_t m_system_time { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user