Files
2026-05-03 13:05:55 +04:00

73 lines
2.1 KiB
C

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKSor
#include <Arch/GIC.h>
#include <Arch/Exceptions.h>
#include <Arch/Timer.h>
#include <OS/Log.h>
static volatile UInt32* GICD = nullptr;
static volatile UInt32* GICC = nullptr;
void GICInitialize(Pointer gicdVirtBase, Pointer giccVirtBase) {
GICD = (volatile UInt32*)gicdVirtBase;
GICC = (volatile UInt32*)giccVirtBase;
GICD[kGICDCTLR / 4] = 0; // disable Distributor (gicd)
UInt32 typer = GICD[kGICDTYPER / 4]; // how many interrupts are supported
UInt32 maxIRQS = 32 * ((typer & 0x1F) + 1); // total number of interrupts
OSLog("GIC: maxIRQS: %d\n", maxIRQS);
for (UInt32 i = 0; i < maxIRQS / 32; i++) {
GICD[kGICDICENABLER / 4 + i] = 0xFFFFFFFF; // clear enable
GICD[kGICDICPENDR / 4 + i] = 0xFFFFFFFF; // clear pending
}
for (UInt32 i = 0; i < maxIRQS / 4; i++) {
GICD[kGICDIPRIORITYR / 4 + i] = 0xA0A0A0A0; // set priority 0xA0 for all interrupts
}
for (UInt32 i = 8; i < maxIRQS / 4; i++) {
GICD[kGICDITARGETSR / 4 + i] = 0x01010101; // set interrupts id >= 32 for CPU 0
}
GICD[kGICDCTLR / 4] = 1; // enable Distributor (gicd)
GICC[kGICCCTLR / 4] = 0; // disable cpu interface
GICC[kGICCPMR / 4] = 0xFF; // set lowest priority (accept all interrupts)
GICC[kGICCCTLR / 4] = 1; // enable CPU interface (gicc)
OSLog("GICv2 initialized.\n");
}
void GICEnableInterrupt(UInt32 irqID) {
UInt32 regOffset = irqID / 32;
UInt32 bitMask = 1 << (irqID % 32);
GICD[kGICDISENABLER / 4 + regOffset] = bitMask;
}
UInt32 GICCReadIAR(void) {
return GICC[kGICCIAR / 4];
}
void GICCWriteEOIR(UInt32 irqID) {
GICC[kGICCEOIR / 4] = irqID;
}
Address GICDispatch(ExceptionsContext* frame, ExceptionsType type) {
if (type != ExceptionsIRQEl1h && type != ExceptionsIRQEl064) return (Address)frame;
UInt32 irqID = GICCReadIAR() & 0x3FF;
if (irqID == 1023) return (Address)frame; // spurious interrupt
Address newStackPointer = (Address)frame;
if (irqID == kTimerIRQ) {
newStackPointer = TimerHandler(frame);
}
GICCWriteEOIR(irqID);
return newStackPointer;
}