Kernel: Replace PIC with APIC
If APIC/IOAPIC is not found, we fallback to PIC Interrupts don't seem to work on real hardware (?)
This commit is contained in:
parent
7efa5bfb75
commit
0bdb01ee04
|
@ -0,0 +1,350 @@
|
||||||
|
#include <kernel/APIC.h>
|
||||||
|
#include <kernel/CPUID.h>
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
#include <kernel/IO.h>
|
||||||
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/panic.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
#include <kernel/Serial.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace APIC
|
||||||
|
{
|
||||||
|
|
||||||
|
static bool s_using_fallback_pic = false;
|
||||||
|
|
||||||
|
static uint32_t s_local_apic = 0;
|
||||||
|
static uint32_t s_io_apic = 0;
|
||||||
|
|
||||||
|
static uint8_t s_overrides[0x100];
|
||||||
|
|
||||||
|
struct RSDPDescriptor
|
||||||
|
{
|
||||||
|
char signature[8];
|
||||||
|
uint8_t checksum;
|
||||||
|
char OEMID[6];
|
||||||
|
uint8_t revision;
|
||||||
|
uint32_t rsdt_address;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct RSDPDescriptor20
|
||||||
|
{
|
||||||
|
RSDPDescriptor firstPart;
|
||||||
|
uint32_t length;
|
||||||
|
uint64_t xsdt_address;
|
||||||
|
uint8_t extended_checksum;
|
||||||
|
uint8_t reserved[3];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct ACPISDTHeader
|
||||||
|
{
|
||||||
|
char signature[4];
|
||||||
|
uint32_t length;
|
||||||
|
uint8_t eevision;
|
||||||
|
uint8_t checksum;
|
||||||
|
char OEMID[6];
|
||||||
|
char OEM_table_id[8];
|
||||||
|
uint32_t OEM_revision;
|
||||||
|
uint32_t creator_id;
|
||||||
|
uint32_t creator_revision;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct RSDT
|
||||||
|
{
|
||||||
|
ACPISDTHeader header;
|
||||||
|
uint32_t sdt_pointer[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XSDT
|
||||||
|
{
|
||||||
|
ACPISDTHeader header;
|
||||||
|
uint64_t sdt_pointer[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MADT
|
||||||
|
{
|
||||||
|
ACPISDTHeader header;
|
||||||
|
uint32_t local_apic;
|
||||||
|
uint32_t flags;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct MADTEntry
|
||||||
|
{
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t length;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t processor_id;
|
||||||
|
uint8_t apic_id;
|
||||||
|
uint32_t flags;
|
||||||
|
} __attribute__((packed)) lapic;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t ioapic_id;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint32_t ioapic_address;
|
||||||
|
uint32_t gsi_base;
|
||||||
|
} __attribute__((packed)) ioapic;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t bus_source;
|
||||||
|
uint8_t irq_source;
|
||||||
|
uint32_t gsi;
|
||||||
|
uint16_t flags;
|
||||||
|
} __attribute__((packed)) interrupt_source_override;
|
||||||
|
};
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
union RedirectionEntry
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t vector : 8;
|
||||||
|
uint64_t delivery_mode : 3;
|
||||||
|
uint64_t destination_mode : 1;
|
||||||
|
uint64_t delivery_status : 1;
|
||||||
|
uint64_t pin_polarity : 1;
|
||||||
|
uint64_t remote_irr : 1;
|
||||||
|
uint64_t trigger_mode : 1;
|
||||||
|
uint64_t mask : 1;
|
||||||
|
uint64_t reserved : 39;
|
||||||
|
uint64_t destination : 8;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t lo_dword;
|
||||||
|
uint32_t hi_dword;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t ReadLocalAPIC(uint32_t offset);
|
||||||
|
static void WriteLocalAPIC(uint32_t offset, uint32_t value);
|
||||||
|
static uint32_t ReadIOAPIC(uint8_t reg);
|
||||||
|
static void WriteIOAPIC(uint8_t reg, uint32_t value);
|
||||||
|
|
||||||
|
|
||||||
|
static bool IsRSDP(RSDPDescriptor* rsdp)
|
||||||
|
{
|
||||||
|
if (memcmp(rsdp->signature, "RSD PTR ", 8) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t checksum = 0;
|
||||||
|
for (uint32_t i = 0; i < sizeof(RSDPDescriptor); i++)
|
||||||
|
checksum += ((uint8_t*)rsdp)[i];
|
||||||
|
if (checksum != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsdp->revision == 2)
|
||||||
|
{
|
||||||
|
RSDPDescriptor20* rsdp20 = (RSDPDescriptor20*)rsdp;
|
||||||
|
uint8_t checksum = 0;
|
||||||
|
for (uint32_t i = 0; i < sizeof(RSDPDescriptor20); i++)
|
||||||
|
checksum += ((uint8_t*)rsdp20)[i];
|
||||||
|
if (checksum != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RSDPDescriptor* LocateRSDP()
|
||||||
|
{
|
||||||
|
// Look in main BIOS area below 1 MB
|
||||||
|
for (uint32_t addr = 0x000E0000; addr < 0x000FFFFF; addr += 16)
|
||||||
|
if (IsRSDP((RSDPDescriptor*)addr))
|
||||||
|
return (RSDPDescriptor*)addr;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidACPISDTHeader(ACPISDTHeader* header)
|
||||||
|
{
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for (uint32_t i = 0; i < header->length; i++)
|
||||||
|
sum += ((uint8_t*)header)[i];
|
||||||
|
return sum == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename SDT>
|
||||||
|
static void GetAPIC(SDT* root)
|
||||||
|
{
|
||||||
|
uint32_t sdt_entry_count = (root->header.length - sizeof(root->header)) / sizeof(*(root->sdt_pointer));
|
||||||
|
for (uint32_t i = 0; i < sdt_entry_count; i++)
|
||||||
|
{
|
||||||
|
ACPISDTHeader* header = (ACPISDTHeader*)root->sdt_pointer[i];
|
||||||
|
if (!IsValidACPISDTHeader(header))
|
||||||
|
continue;
|
||||||
|
if (memcmp(header->signature, "APIC", 4) == 0)
|
||||||
|
{
|
||||||
|
MADT* madt = (MADT*)header;
|
||||||
|
s_local_apic = madt->local_apic;
|
||||||
|
uint32_t entry_addr = (uint32_t)madt + sizeof(MADT);
|
||||||
|
while (entry_addr < (uint32_t)madt + madt->header.length)
|
||||||
|
{
|
||||||
|
MADTEntry* entry = (MADTEntry*)entry_addr;
|
||||||
|
|
||||||
|
switch (entry->type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
//s_processor_id = entry->lapic.processor_id;
|
||||||
|
kprintln("Processor {} ({})", entry->lapic.processor_id, entry->lapic.apic_id);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (s_io_apic == 0)
|
||||||
|
s_io_apic = entry->ioapic.ioapic_address;
|
||||||
|
kprintln("IOAPIC #{}", entry->ioapic.ioapic_id);
|
||||||
|
kprintln(" addr: {}", (void*)entry->ioapic.ioapic_address);
|
||||||
|
kprintln(" gsi base: {} ({})", entry->ioapic.gsi_base, (uint8_t)((ReadIOAPIC(0x01) >> 16) + 1));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
s_overrides[entry->interrupt_source_override.irq_source] = entry->interrupt_source_override.gsi;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry_addr += entry->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t ReadLocalAPIC(uint32_t offset)
|
||||||
|
{
|
||||||
|
return *(uint32_t*)(s_local_apic + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteLocalAPIC(uint32_t offset, uint32_t value)
|
||||||
|
{
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||||
|
*(uint32_t*)(s_local_apic + offset) = value;
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ReadIOAPIC(uint8_t reg)
|
||||||
|
{
|
||||||
|
volatile uint32_t* ioapic = (volatile uint32_t*)s_io_apic;
|
||||||
|
ioapic[0] = reg;
|
||||||
|
return ioapic[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteIOAPIC(uint8_t reg, uint32_t value)
|
||||||
|
{
|
||||||
|
volatile uint32_t* ioapic = (volatile uint32_t*)s_io_apic;
|
||||||
|
ioapic[0] = reg;
|
||||||
|
ioapic[4] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool InitializeAPIC()
|
||||||
|
{
|
||||||
|
if (!CPUID::IsAvailable())
|
||||||
|
{
|
||||||
|
kprintln("CPUID not available");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ecx, edx;
|
||||||
|
CPUID::GetFeatures(ecx, edx);
|
||||||
|
if (!(edx & CPUID::Features::EDX_APIC))
|
||||||
|
{
|
||||||
|
kprintln("Local APIC not available");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(edx & CPUID::Features::EDX_MSR))
|
||||||
|
{
|
||||||
|
kprintln("MSR not available");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RSDPDescriptor* rsdp = LocateRSDP();
|
||||||
|
if (rsdp == nullptr)
|
||||||
|
{
|
||||||
|
kprintln("Could not locate RSDP");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsdp->revision == 2)
|
||||||
|
{
|
||||||
|
GetAPIC<XSDT>((XSDT*)((RSDPDescriptor20*)rsdp)->xsdt_address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetAPIC<RSDT>((RSDT*)rsdp->rsdt_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_local_apic == 0 || s_io_apic == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Enable Local APIC
|
||||||
|
uint32_t sipi = ReadLocalAPIC(0xF0);
|
||||||
|
WriteIOAPIC(0xF0, sipi | 0x1FF);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0x00; i <= 0xFF; i++)
|
||||||
|
s_overrides[i] = i;
|
||||||
|
|
||||||
|
PIC::MaskAll();
|
||||||
|
PIC::Remap();
|
||||||
|
|
||||||
|
if (!InitializeAPIC())
|
||||||
|
{
|
||||||
|
kprintln("Could not initialize APIC. Using PIC as fallback");
|
||||||
|
s_using_fallback_pic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EOI()
|
||||||
|
{
|
||||||
|
if (s_using_fallback_pic)
|
||||||
|
return PIC::EOI(0);
|
||||||
|
WriteLocalAPIC(0xB0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetISR(uint32_t out[8])
|
||||||
|
{
|
||||||
|
if (s_using_fallback_pic)
|
||||||
|
{
|
||||||
|
memset(out, 0, sizeof(uint32_t) * 8);
|
||||||
|
uint32_t addr = (uint32_t)out + IRQ_VECTOR_BASE / 8;
|
||||||
|
*(uint16_t*)addr = PIC::GetISR();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 8; i++)
|
||||||
|
out[i] = ReadLocalAPIC(0x100 + i * 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnableIRQ(uint8_t irq)
|
||||||
|
{
|
||||||
|
if (s_using_fallback_pic)
|
||||||
|
return PIC::Unmask(irq);
|
||||||
|
|
||||||
|
uint32_t gsi = s_overrides[irq];
|
||||||
|
|
||||||
|
RedirectionEntry redir;
|
||||||
|
redir.lo_dword = ReadIOAPIC(0x10 + gsi * 2);
|
||||||
|
redir.hi_dword = ReadIOAPIC(0x10 + gsi * 2 + 1);
|
||||||
|
|
||||||
|
redir.vector = IRQ_VECTOR_BASE + irq;
|
||||||
|
redir.mask = 0;
|
||||||
|
redir.destination = ReadLocalAPIC(0x20);
|
||||||
|
|
||||||
|
kprintln("register irq {2} -> {2} @ apic {}", irq, gsi, redir.destination);
|
||||||
|
|
||||||
|
WriteIOAPIC(0x10 + gsi * 2, redir.lo_dword);
|
||||||
|
WriteIOAPIC(0x10 + gsi * 2 + 1, redir.hi_dword);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
|
#include <kernel/APIC.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/kmalloc.h>
|
#include <kernel/kmalloc.h>
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
#include <kernel/PIC.h>
|
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/Serial.h>
|
||||||
|
|
||||||
union GateDescriptor
|
union GateDescriptor
|
||||||
{
|
{
|
||||||
|
@ -33,12 +34,9 @@ struct IDTR
|
||||||
} __attribute((packed));
|
} __attribute((packed));
|
||||||
|
|
||||||
static IDTR s_idtr;
|
static IDTR s_idtr;
|
||||||
static GateDescriptor* s_idt;
|
static GateDescriptor s_idt[0x100];
|
||||||
|
|
||||||
static void (*s_irq_handlers[16])();
|
static void (*s_irq_handlers[0xFF])() { nullptr };
|
||||||
|
|
||||||
extern "C" void handle_irq();
|
|
||||||
extern "C" void handle_irq_common();
|
|
||||||
|
|
||||||
#define INTERRUPT_HANDLER(i, msg) \
|
#define INTERRUPT_HANDLER(i, msg) \
|
||||||
static void interrupt ## i () \
|
static void interrupt ## i () \
|
||||||
|
@ -119,21 +117,17 @@ namespace IDT
|
||||||
|
|
||||||
void register_irq_handler(uint8_t irq, void (*f)())
|
void register_irq_handler(uint8_t irq, void (*f)())
|
||||||
{
|
{
|
||||||
s_irq_handlers[irq] = f;
|
s_irq_handlers[IRQ_VECTOR_BASE + irq] = f;
|
||||||
register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common);
|
register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
constexpr size_t idt_size = 256;
|
|
||||||
|
|
||||||
s_idt = new GateDescriptor[idt_size];
|
|
||||||
|
|
||||||
s_idtr.offset = s_idt;
|
s_idtr.offset = s_idt;
|
||||||
s_idtr.size = idt_size * 8;
|
s_idtr.size = sizeof(s_idt);
|
||||||
|
|
||||||
for (uint8_t i = 0xff; i > 0x10; i--)
|
for (uint8_t i = 0xFF; i > IRQ_VECTOR_BASE; i--)
|
||||||
register_interrupt_handler(i, unimplemented_trap);
|
register_irq_handler(i, nullptr);
|
||||||
|
|
||||||
REGISTER_HANDLER(0x00);
|
REGISTER_HANDLER(0x00);
|
||||||
REGISTER_HANDLER(0x01);
|
REGISTER_HANDLER(0x01);
|
||||||
|
@ -145,16 +139,28 @@ namespace IDT
|
||||||
REGISTER_HANDLER(0x07);
|
REGISTER_HANDLER(0x07);
|
||||||
REGISTER_HANDLER(0x08);
|
REGISTER_HANDLER(0x08);
|
||||||
REGISTER_HANDLER(0x09);
|
REGISTER_HANDLER(0x09);
|
||||||
REGISTER_HANDLER(0x0a);
|
REGISTER_HANDLER(0x0A);
|
||||||
REGISTER_HANDLER(0x0b);
|
REGISTER_HANDLER(0x0B);
|
||||||
REGISTER_HANDLER(0x0c);
|
REGISTER_HANDLER(0x0C);
|
||||||
REGISTER_HANDLER(0x0d);
|
REGISTER_HANDLER(0x0D);
|
||||||
REGISTER_HANDLER(0x0e);
|
REGISTER_HANDLER(0x0E);
|
||||||
REGISTER_HANDLER(0x0f);
|
REGISTER_HANDLER(0x0F);
|
||||||
REGISTER_HANDLER(0x10);
|
REGISTER_HANDLER(0x10);
|
||||||
|
REGISTER_HANDLER(0x11);
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
REGISTER_HANDLER(0x12);
|
||||||
register_irq_handler(i, nullptr);
|
REGISTER_HANDLER(0x13);
|
||||||
|
REGISTER_HANDLER(0x14);
|
||||||
|
REGISTER_HANDLER(0x15);
|
||||||
|
REGISTER_HANDLER(0x16);
|
||||||
|
REGISTER_HANDLER(0x17);
|
||||||
|
REGISTER_HANDLER(0x18);
|
||||||
|
REGISTER_HANDLER(0x19);
|
||||||
|
REGISTER_HANDLER(0x1A);
|
||||||
|
REGISTER_HANDLER(0x1B);
|
||||||
|
REGISTER_HANDLER(0x1C);
|
||||||
|
REGISTER_HANDLER(0x1D);
|
||||||
|
REGISTER_HANDLER(0x1E);
|
||||||
|
REGISTER_HANDLER(0x1F);
|
||||||
|
|
||||||
flush_idt();
|
flush_idt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ KERNEL_ARCH_LDFLAGS=
|
||||||
KERNEL_ARCH_LIBS=
|
KERNEL_ARCH_LIBS=
|
||||||
|
|
||||||
KERNEL_ARCH_OBJS= \
|
KERNEL_ARCH_OBJS= \
|
||||||
|
$(ARCHDIR)/APIC.o \
|
||||||
$(ARCHDIR)/boot.o \
|
$(ARCHDIR)/boot.o \
|
||||||
$(ARCHDIR)/CPUID.o \
|
$(ARCHDIR)/CPUID.o \
|
||||||
$(ARCHDIR)/font.o \
|
$(ARCHDIR)/font.o \
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace APIC
|
||||||
|
{
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
void EOI();
|
||||||
|
void GetISR(uint32_t[8]);
|
||||||
|
void EnableIRQ(uint8_t irq);
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x50;
|
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||||
|
|
||||||
namespace IDT
|
namespace IDT
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
namespace PIC
|
namespace PIC
|
||||||
{
|
{
|
||||||
|
|
||||||
void initialize();
|
void Remap();
|
||||||
void eoi(uint8_t);
|
void MaskAll();
|
||||||
void unmask(uint8_t);
|
void EOI(uint8_t);
|
||||||
void mask(uint8_t);
|
void Unmask(uint8_t);
|
||||||
|
void Mask(uint8_t);
|
||||||
|
|
||||||
uint16_t get_isr();
|
uint16_t GetISR();
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
#include <BAN/Queue.h>
|
#include <BAN/Queue.h>
|
||||||
|
#include <kernel/APIC.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/Keyboard.h>
|
#include <kernel/Keyboard.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
#include <kernel/PIC.h>
|
|
||||||
#include <kernel/PIT.h>
|
#include <kernel/PIT.h>
|
||||||
#include <kernel/Serial.h>
|
#include <kernel/Serial.h>
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ namespace Keyboard
|
||||||
|
|
||||||
// Register callback and IRQ
|
// Register callback and IRQ
|
||||||
IDT::register_irq_handler(KEYBOARD_IRQ, keyboard_irq_handler);
|
IDT::register_irq_handler(KEYBOARD_IRQ, keyboard_irq_handler);
|
||||||
PIC::unmask(KEYBOARD_IRQ);
|
APIC::EnableIRQ(KEYBOARD_IRQ);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,11 @@
|
||||||
namespace PIC
|
namespace PIC
|
||||||
{
|
{
|
||||||
|
|
||||||
void initialize()
|
void Remap()
|
||||||
{
|
{
|
||||||
|
uint8_t a1 = IO::inb(PIC1_DATA);
|
||||||
|
uint8_t a2 = IO::inb(PIC2_DATA);
|
||||||
|
|
||||||
// Start the initialization sequence (in cascade mode)
|
// Start the initialization sequence (in cascade mode)
|
||||||
IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||||
IO::io_wait();
|
IO::io_wait();
|
||||||
|
@ -53,19 +56,25 @@ namespace PIC
|
||||||
IO::outb(PIC2_DATA, ICW4_8086);
|
IO::outb(PIC2_DATA, ICW4_8086);
|
||||||
IO::io_wait();
|
IO::io_wait();
|
||||||
|
|
||||||
// Mask everything
|
// Restore original masks
|
||||||
|
IO::outb(PIC1_DATA, a1);
|
||||||
|
IO::outb(PIC2_DATA, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaskAll()
|
||||||
|
{
|
||||||
IO::outb(PIC1_DATA, 0xff);
|
IO::outb(PIC1_DATA, 0xff);
|
||||||
IO::outb(PIC2_DATA, 0xff);
|
IO::outb(PIC2_DATA, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eoi(uint8_t irq)
|
void EOI(uint8_t irq)
|
||||||
{
|
{
|
||||||
if (irq >= 8)
|
if (irq >= 8)
|
||||||
IO::outb(PIC2_COMMAND, PIC_EOI);
|
IO::outb(PIC2_COMMAND, PIC_EOI);
|
||||||
IO::outb(PIC1_COMMAND, PIC_EOI);
|
IO::outb(PIC1_COMMAND, PIC_EOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mask(uint8_t irq) {
|
void Mask(uint8_t irq) {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
|
@ -79,7 +88,7 @@ namespace PIC
|
||||||
IO::outb(port, value);
|
IO::outb(port, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmask(uint8_t irq) {
|
void Unmask(uint8_t irq) {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
|
@ -93,7 +102,7 @@ namespace PIC
|
||||||
IO::outb(port, value);
|
IO::outb(port, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_isr()
|
uint16_t GetISR()
|
||||||
{
|
{
|
||||||
IO::outb(PIC1_COMMAND, 0x0b);
|
IO::outb(PIC1_COMMAND, 0x0b);
|
||||||
IO::outb(PIC2_COMMAND, 0x0b);
|
IO::outb(PIC2_COMMAND, 0x0b);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
#include <kernel/PIC.h>
|
#include <kernel/APIC.h>
|
||||||
|
|
||||||
#define IRQ_TIMER 0
|
#define IRQ_TIMER 0
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace PIT
|
||||||
|
|
||||||
void clock_handle()
|
void clock_handle()
|
||||||
{
|
{
|
||||||
PIT::s_system_time++;
|
s_system_time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ms_since_boot()
|
uint64_t ms_since_boot()
|
||||||
|
@ -47,7 +47,7 @@ namespace PIT
|
||||||
|
|
||||||
IDT::register_irq_handler(IRQ_TIMER, clock_handle);
|
IDT::register_irq_handler(IRQ_TIMER, clock_handle);
|
||||||
|
|
||||||
PIC::unmask(IRQ_TIMER);
|
APIC::EnableIRQ(IRQ_TIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <kernel/APIC.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
|
@ -40,11 +41,9 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||||
}
|
}
|
||||||
TTY::initialize();
|
TTY::initialize();
|
||||||
|
|
||||||
dprintln("{}", mbi->framebuffer.type);
|
|
||||||
|
|
||||||
kmalloc_initialize();
|
kmalloc_initialize();
|
||||||
|
|
||||||
PIC::initialize();
|
APIC::Initialize();
|
||||||
gdt_initialize();
|
gdt_initialize();
|
||||||
IDT::initialize();
|
IDT::initialize();
|
||||||
|
|
||||||
|
@ -52,11 +51,12 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||||
if (!Keyboard::initialize())
|
if (!Keyboard::initialize())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kprintln("Hello from the kernel!");
|
|
||||||
|
|
||||||
ENABLE_INTERRUPTS();
|
ENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
kprintln("Hello from the kernel!");
|
||||||
|
|
||||||
auto& shell = Kernel::Shell::Get();
|
auto& shell = Kernel::Shell::Get();
|
||||||
|
|
||||||
shell.Run();
|
shell.Run();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|
1
qemu.sh
1
qemu.sh
|
@ -4,6 +4,7 @@ set -e
|
||||||
|
|
||||||
qemu-system-$(./target-triplet-to-arch.sh $HOST) \
|
qemu-system-$(./target-triplet-to-arch.sh $HOST) \
|
||||||
-m 128 \
|
-m 128 \
|
||||||
|
-smp 2 \
|
||||||
-drive format=raw,media=cdrom,file=banan-os.iso \
|
-drive format=raw,media=cdrom,file=banan-os.iso \
|
||||||
-serial stdio \
|
-serial stdio \
|
||||||
|
|
Loading…
Reference in New Issue