replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
+161
-109
@@ -4,6 +4,8 @@
|
||||
#include <kernel/hal/hal_internal.h>
|
||||
#include <kernel/hal/hal_api.h>
|
||||
#include <kernel/hal/hal_timer.h>
|
||||
#include <kernel/hal/hal_processor.h>
|
||||
#include <kernel/ke_vectors.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <intrin.h>
|
||||
@@ -14,6 +16,9 @@ static volatile uint32_t* gLapic = (volatile uint32_t*)0;
|
||||
#define LAPIC_REG(off) (*(volatile uint32_t*)((uint8_t*)gLapic + (off)))
|
||||
#define LAPIC_ID 0x020
|
||||
#define LAPIC_EOI 0x0B0
|
||||
#define LAPIC_TPR 0x080
|
||||
#define LAPIC_ISR_BASE 0x100
|
||||
#define LAPIC_IRR_BASE 0x200
|
||||
#define LAPIC_SPURIOUS 0x0F0
|
||||
#define LAPIC_ICR_LO 0x300
|
||||
#define LAPIC_ICR_HI 0x310
|
||||
@@ -24,38 +29,70 @@ static volatile uint32_t* gLapic = (volatile uint32_t*)0;
|
||||
#define IA32_APIC_BASE_X2APIC (1ULL << 10)
|
||||
#define IA32_X2APIC_ID 0x00000802u
|
||||
#define IA32_X2APIC_EOI 0x0000080Bu
|
||||
#define IA32_X2APIC_TPR 0x00000808u
|
||||
#define IA32_X2APIC_ISR_BASE 0x00000810u
|
||||
#define IA32_X2APIC_IRR_BASE 0x00000820u
|
||||
#define IA32_X2APIC_SVR 0x0000080Fu
|
||||
#define IA32_X2APIC_ICR 0x00000830u
|
||||
|
||||
#define CPUID_FEATURE_ECX_X2APIC (1u << 21)
|
||||
|
||||
|
||||
// ---- I/O APIC ----.
|
||||
static volatile uint32_t* gIoapic = (volatile uint32_t*)0;
|
||||
static uint32_t gBspLapicId = 0;
|
||||
static uint8_t gX2ApicSupported = 0;
|
||||
static uint8_t gX2ApicEnabled = 0;
|
||||
static uint32_t gIoapicGsiBase = 0;
|
||||
static uint32_t gIoapicRedirectionCount = 0;
|
||||
// ---- I/O APIC interrupt domains ----.
|
||||
#define HAL_IOAPIC_MAX 8u
|
||||
#define IOAPIC_IDX 0x00u
|
||||
#define IOAPIC_DATA 0x10u
|
||||
|
||||
typedef struct HAL_IOAPIC {
|
||||
volatile uint32_t* Registers;
|
||||
uintptr_t Physical;
|
||||
uint32_t GsiBase;
|
||||
uint32_t Pins;
|
||||
volatile long RegisterLock;
|
||||
} HAL_IOAPIC;
|
||||
|
||||
static HAL_IOAPIC gIoapics[HAL_IOAPIC_MAX];
|
||||
static uint32_t gIoapicCount;
|
||||
static uint32_t gBspLapicId;
|
||||
static uint8_t gX2ApicSupported;
|
||||
static uint8_t gX2ApicEnabled;
|
||||
static uint32_t gIsaGsi[16];
|
||||
static uint16_t gIsaFlags[16];
|
||||
static uint16_t gSciIrq = UINT16_MAX;
|
||||
static bool gIsaOverridesInitialized = false;
|
||||
#define IOAPIC_IDX 0x00
|
||||
#define IOAPIC_DATA 0x10
|
||||
static bool gIsaOverridesInitialized;
|
||||
|
||||
// Implements the ioapic Read operation.
|
||||
static uint32_t IoapicRead(uint8_t reg) {
|
||||
*(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_IDX) = reg;
|
||||
return *(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_DATA);
|
||||
}
|
||||
// Implements the ioapic Write operation.
|
||||
static void IoapicWrite(uint8_t reg, uint32_t val) {
|
||||
*(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_IDX) = reg;
|
||||
*(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_DATA) = val;
|
||||
// I/O APIC register selectors are shared by every CPU accessing that APIC.
|
||||
static uint32_t IoapicRead(HAL_IOAPIC* apic, uint8_t reg) {
|
||||
uintptr_t interruptFlags = HalDisableInterrupts();
|
||||
while (_InterlockedCompareExchange(&apic->RegisterLock, 1, 0))
|
||||
_mm_pause();
|
||||
apic->Registers[IOAPIC_IDX / 4u] = reg;
|
||||
uint32_t value = apic->Registers[IOAPIC_DATA / 4u];
|
||||
_InterlockedExchange(&apic->RegisterLock, 0);
|
||||
HalRestoreInterrupts(interruptFlags);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void IoapicWrite(HAL_IOAPIC* apic, uint8_t reg, uint32_t value) {
|
||||
uintptr_t interruptFlags = HalDisableInterrupts();
|
||||
while (_InterlockedCompareExchange(&apic->RegisterLock, 1, 0))
|
||||
_mm_pause();
|
||||
apic->Registers[IOAPIC_IDX / 4u] = reg;
|
||||
apic->Registers[IOAPIC_DATA / 4u] = value;
|
||||
_InterlockedExchange(&apic->RegisterLock, 0);
|
||||
HalRestoreInterrupts(interruptFlags);
|
||||
}
|
||||
|
||||
static HAL_IOAPIC* HalApicFindGsi(uint32_t gsi, uint32_t* pinOut) {
|
||||
for (uint32_t i = 0; i < gIoapicCount; i++) {
|
||||
HAL_IOAPIC* apic = &gIoapics[i];
|
||||
if (gsi >= apic->GsiBase && gsi - apic->GsiBase < apic->Pins) {
|
||||
*pinOut = gsi - apic->GsiBase;
|
||||
return apic;
|
||||
}
|
||||
}
|
||||
return (HAL_IOAPIC*)0;
|
||||
}
|
||||
|
||||
// Implements the apic Detect Mode operation.
|
||||
static void HalApicDetectMode(void) {
|
||||
int regs[4] = {0, 0, 0, 0};
|
||||
__cpuid(regs, 1);
|
||||
@@ -70,7 +107,6 @@ static void HalApicStallUs(uint32_t us) {
|
||||
HalTimerStall(us);
|
||||
}
|
||||
|
||||
// Implements the apic Wait Icr Idle operation.
|
||||
static void HalApicWaitIcrIdle(void) {
|
||||
if (gX2ApicEnabled)
|
||||
return;
|
||||
@@ -82,7 +118,6 @@ static void HalApicWaitIcrIdle(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the apic Send Ipi operation.
|
||||
static void HalApicSendIpi(uint32_t lapicId, uint32_t low) {
|
||||
if (gX2ApicEnabled) {
|
||||
__writemsr(IA32_X2APIC_ICR, ((uint64_t)lapicId << 32) | low);
|
||||
@@ -98,8 +133,6 @@ static void HalApicSendIpi(uint32_t lapicId, uint32_t low) {
|
||||
// IRQ n -> redirection table at register 0x10 + 2*n (low), 0x11 + 2*n (high).
|
||||
#define IOREDTBL_LO(n) (0x10 + 2*(n))
|
||||
#define IOREDTBL_HI(n) (0x11 + 2*(n))
|
||||
// Interrupt vector base: IRQ 0 -> vector 0x20, IRQ 1 -> vector 0x21, ...
|
||||
#define IRQ_VECTOR_BASE 0x20
|
||||
|
||||
// Returns the local interrupt-controller hardware ID of the boot processor.
|
||||
uint32_t HalApicGetBootProcessorId(void) {
|
||||
@@ -126,12 +159,46 @@ void HalApicInitializeCurrentProcessor(void) {
|
||||
apicBase |= IA32_APIC_BASE_X2APIC;
|
||||
__writemsr(IA32_APIC_BASE, apicBase);
|
||||
__writemsr(IA32_X2APIC_SVR, LAPIC_ENABLE | 0xFFu);
|
||||
HalApicSetTaskPriority(0);
|
||||
return;
|
||||
}
|
||||
|
||||
__writemsr(IA32_APIC_BASE, apicBase);
|
||||
if (gLapic)
|
||||
LAPIC_REG(LAPIC_SPURIOUS) = LAPIC_ENABLE | 0xFF;
|
||||
HalApicSetTaskPriority(0);
|
||||
}
|
||||
|
||||
// Controls the current CPU's interrupt priority without changing its interrupt-enable flag.
|
||||
void HalApicSetTaskPriority(uint8_t priority) {
|
||||
if (gX2ApicEnabled) {
|
||||
__writemsr(IA32_X2APIC_TPR, priority);
|
||||
} else if (gLapic) {
|
||||
LAPIC_REG(LAPIC_TPR) = priority;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t HalApicQueryTaskPriority(void) {
|
||||
if (gX2ApicEnabled)
|
||||
return (uint8_t)__readmsr(IA32_X2APIC_TPR);
|
||||
return gLapic ? (uint8_t)LAPIC_REG(LAPIC_TPR) : 0u;
|
||||
}
|
||||
|
||||
// Reads the current processor's local delivery state after a source is masked.
|
||||
bool HalApicVectorPending(uint8_t vector) {
|
||||
const uint32_t index = (uint32_t)vector >> 5u;
|
||||
const uint32_t mask = 1u << (vector & 31u);
|
||||
uint32_t irr, isr;
|
||||
if (gX2ApicEnabled) {
|
||||
irr = (uint32_t)__readmsr(IA32_X2APIC_IRR_BASE + index);
|
||||
isr = (uint32_t)__readmsr(IA32_X2APIC_ISR_BASE + index);
|
||||
} else if (gLapic) {
|
||||
irr = LAPIC_REG(LAPIC_IRR_BASE + 0x10u * index);
|
||||
isr = LAPIC_REG(LAPIC_ISR_BASE + 0x10u * index);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return ((irr | isr) & mask) != 0u;
|
||||
}
|
||||
|
||||
// Broadcasts an NMI to every processor except the caller.
|
||||
@@ -182,102 +249,85 @@ KSTATUS HalApicStartProcessor(uint32_t hardwareId, uintptr_t startPhysical) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Composes an MSI message targeting the boot processor without exposing APIC mode.
|
||||
KSTATUS HalApicComposeMsi(uint8_t vector, HAL_MSI_MESSAGE* messageOut) {
|
||||
if (!messageOut || vector < 0x20u)
|
||||
// MSI destination encoding without interrupt remapping supports an 8-bit APIC ID.
|
||||
KSTATUS HalApicComposeMsi(uint32_t hardwareId, uint8_t vector, HAL_MSI_MESSAGE* out) {
|
||||
if (!out || vector < KE_VECTOR_DEVICE_FIRST || vector > KE_VECTOR_DEVICE_LAST)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (gBspLapicId >= 256u)
|
||||
if (hardwareId > 255u)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
messageOut->Address = 0xFEE00000ull | ((uint64_t)(gBspLapicId & 0xFFu) << 12);
|
||||
messageOut->Data = vector;
|
||||
messageOut->Reserved = 0;
|
||||
out->Address = 0xFEE00000ull | ((uint64_t)hardwareId << 12);
|
||||
out->Data = vector;
|
||||
out->Reserved = 0;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Initializes the identity ISA map before processing MADT source overrides.
|
||||
static void HalApicInitializeIsaMap(void) {
|
||||
if (gIsaOverridesInitialized) return;
|
||||
for (uint32_t irq = 0; irq < 16; ++irq) {
|
||||
for (uint32_t irq = 0; irq < 16; irq++) {
|
||||
gIsaGsi[irq] = irq;
|
||||
gIsaFlags[irq] = 0;
|
||||
}
|
||||
gIsaOverridesInitialized = true;
|
||||
}
|
||||
|
||||
// Records the global-system-interrupt base of the currently supported IOAPIC.
|
||||
void HalApicSetGsiBase(uint32_t gsiBase) { gIoapicGsiBase = gsiBase; }
|
||||
void HalApicAddIoapic(uintptr_t physical, uint32_t gsiBase) {
|
||||
if (!physical || gIoapicCount >= HAL_IOAPIC_MAX)
|
||||
return;
|
||||
for (uint32_t i = 0; i < gIoapicCount; i++)
|
||||
if (gIoapics[i].Physical == physical)
|
||||
return;
|
||||
HAL_IOAPIC* apic = &gIoapics[gIoapicCount++];
|
||||
apic->Physical = physical;
|
||||
apic->GsiBase = gsiBase;
|
||||
}
|
||||
|
||||
// Preserves MADT interrupt-source overrides for legacy ISA devices.
|
||||
void HalApicSetIsaOverride(uint8_t irq, uint32_t gsi, uint16_t flags) {
|
||||
if (irq >= 16) return;
|
||||
if (irq >= 16u) return;
|
||||
HalApicInitializeIsaMap();
|
||||
gIsaGsi[irq] = gsi;
|
||||
gIsaFlags[irq] = flags;
|
||||
}
|
||||
|
||||
// Marks the FADT SCI as a low-active, level-triggered interrupt by default.
|
||||
void HalApicSetSciIrq(uint16_t irq) { gSciIrq = irq; }
|
||||
|
||||
// Resolves one logical IRQ to a physical pin on the selected IOAPIC.
|
||||
static bool HalApicResolveIrq(uint8_t irq, uint32_t* pinOut, uint32_t* flagsOut) {
|
||||
KSTATUS HalApicResolveIsa(uint8_t irq, uint32_t* gsiOut, uint16_t* flagsOut) {
|
||||
if (irq >= 16u || !gsiOut || !flagsOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
HalApicInitializeIsaMap();
|
||||
uint32_t gsi = irq < 16 ? gIsaGsi[irq] : irq;
|
||||
if (gsi < gIoapicGsiBase || gsi - gIoapicGsiBase >= gIoapicRedirectionCount)
|
||||
return false;
|
||||
uint32_t flags = 0;
|
||||
if (irq == gSciIrq) flags = (1u << 13) | (1u << 15);
|
||||
if (irq < 16) {
|
||||
uint16_t override = gIsaFlags[irq];
|
||||
// MADT 00 is bus-conformant; 11 selects active low or level triggered.
|
||||
if ((override & 3u) == 3u) flags |= (1u << 13);
|
||||
else if ((override & 3u) == 1u) flags &= ~(1u << 13);
|
||||
if (((override >> 2) & 3u) == 3u) flags |= (1u << 15);
|
||||
else if (((override >> 2) & 3u) == 1u) flags &= ~(1u << 15);
|
||||
}
|
||||
*pinOut = gsi - gIoapicGsiBase;
|
||||
*flagsOut = flags;
|
||||
return true;
|
||||
uint32_t pin;
|
||||
if (!HalApicFindGsi(gIsaGsi[irq], &pin))
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
*gsiOut = gIsaGsi[irq];
|
||||
*flagsOut = gIsaFlags[irq];
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Reports whether a platform IRQ can be routed by the current IOAPIC.
|
||||
bool HalApicCanRouteIrq(uint8_t irq) {
|
||||
uint32_t pin, flags;
|
||||
return irq < 24 && HalApicResolveIrq(irq, &pin, &flags);
|
||||
// ACPI polarity bits 1:0 and trigger bits 3:2 encode bus-defined defaults.
|
||||
KSTATUS HalApicRouteGsi(uint32_t gsi, uint8_t vector, uint32_t hardwareId,
|
||||
uint16_t flags, bool masked) {
|
||||
if (vector < KE_VECTOR_DEVICE_FIRST || vector > KE_VECTOR_DEVICE_LAST || hardwareId > 255u)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
uint32_t pin;
|
||||
HAL_IOAPIC* apic = HalApicFindGsi(gsi, &pin);
|
||||
if (!apic) return NTLSTATUS_NOT_SUPPORTED;
|
||||
uint32_t mode = 0;
|
||||
if ((flags & 3u) == 3u) mode |= (1u << 13);
|
||||
if (((flags >> 2) & 3u) == 3u) mode |= (1u << 15);
|
||||
IoapicWrite(apic, IOREDTBL_LO(pin), (1u << 16) | vector | mode);
|
||||
IoapicWrite(apic, IOREDTBL_HI(pin), (hardwareId & 255u) << 24);
|
||||
if (!masked) IoapicWrite(apic, IOREDTBL_LO(pin), vector | mode);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the apic Route Irq operation.
|
||||
void HalApicRouteIrq(uint8_t irq) {
|
||||
// Full initial setup of the redirection entry.
|
||||
// Sets the vector and clears the mask bit in one write.
|
||||
uint32_t pin, flags;
|
||||
if (!HalApicResolveIrq(irq, &pin, &flags)) return;
|
||||
uint32_t vector = IRQ_VECTOR_BASE + irq;
|
||||
IoapicWrite(IOREDTBL_HI(pin), (gBspLapicId & 0xFFu) << 24);
|
||||
IoapicWrite(IOREDTBL_LO(pin), vector | flags);
|
||||
KSTATUS HalApicMaskGsi(uint32_t gsi, bool masked) {
|
||||
uint32_t pin;
|
||||
HAL_IOAPIC* apic = HalApicFindGsi(gsi, &pin);
|
||||
if (!apic) return NTLSTATUS_NOT_SUPPORTED;
|
||||
uint32_t lo = IoapicRead(apic, IOREDTBL_LO(pin));
|
||||
if (masked) lo |= 1u << 16;
|
||||
else lo &= ~(1u << 16);
|
||||
IoapicWrite(apic, IOREDTBL_LO(pin), lo);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the apic Mask Irq operation.
|
||||
void HalApicMaskIrq(uint8_t irq) {
|
||||
uint32_t pin, flags;
|
||||
if (!HalApicResolveIrq(irq, &pin, &flags)) return;
|
||||
uint32_t lo = IoapicRead(IOREDTBL_LO(pin));
|
||||
lo |= (1 << 16);
|
||||
IoapicWrite(IOREDTBL_LO(pin), lo);
|
||||
}
|
||||
|
||||
// Implements the apic Unmask Irq operation.
|
||||
void HalApicUnmaskIrq(uint8_t irq) {
|
||||
uint32_t pin, flags;
|
||||
if (!HalApicResolveIrq(irq, &pin, &flags)) return;
|
||||
uint32_t lo = IoapicRead(IOREDTBL_LO(pin));
|
||||
lo = (lo & ~(0xFFu | (1u << 16) | (1u << 13) | (1u << 15))) |
|
||||
(IRQ_VECTOR_BASE + irq) | flags;
|
||||
IoapicWrite(IOREDTBL_HI(pin), (gBspLapicId & 0xFFu) << 24);
|
||||
IoapicWrite(IOREDTBL_LO(pin), lo);
|
||||
}
|
||||
|
||||
// Implements the apic Send Eoi operation.
|
||||
void HalApicSendEoi(void) {
|
||||
if (gX2ApicEnabled) {
|
||||
__writemsr(IA32_X2APIC_EOI, 0);
|
||||
@@ -286,27 +336,29 @@ void HalApicSendEoi(void) {
|
||||
LAPIC_REG(LAPIC_EOI) = 0;
|
||||
}
|
||||
|
||||
// Implements the apic Initialize operation.
|
||||
void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys) {
|
||||
void HalApicInitialize(uintptr_t lapicPhys) {
|
||||
// The PIC remains masked: legacy input arrives through programmed I/O APICs.
|
||||
__outbyte(0x21, 0xFF);
|
||||
__outbyte(0xA1, 0xFF);
|
||||
HalApicDetectMode();
|
||||
|
||||
gLapic = (volatile uint32_t*)(HalPhysicalToVirtual(lapicPhys));
|
||||
gIoapic = (volatile uint32_t*)(HalPhysicalToVirtual(ioapicPhys));
|
||||
|
||||
// The BSP is the CPU executing HAL init. Keep all external/device IRQs
|
||||
// routed to this LAPIC; CPU-local IPIs use the local APIC directly.
|
||||
gLapic = (volatile uint32_t*)HalPhysicalToVirtual(lapicPhys);
|
||||
if (gX2ApicEnabled)
|
||||
gBspLapicId = (uint32_t)__readmsr(IA32_X2APIC_ID);
|
||||
else
|
||||
gBspLapicId = (LAPIC_REG(LAPIC_ID) >> 24) & 0xFF;
|
||||
|
||||
gBspLapicId = (LAPIC_REG(LAPIC_ID) >> 24) & 0xFFu;
|
||||
HalApicInitializeCurrentProcessor();
|
||||
if (gIoapicCount == 0)
|
||||
HalApicAddIoapic(0xFEC00000u, 0);
|
||||
|
||||
// Mask all IOAPIC lines initially.
|
||||
uint32_t maxRedir = (IoapicRead(1) >> 16) & 0xFF;
|
||||
gIoapicRedirectionCount = maxRedir + 1u;
|
||||
for (uint32_t i = 0; i <= maxRedir; i++) {
|
||||
IoapicWrite(IOREDTBL_LO(i), (1u << 16) | IRQ_VECTOR_BASE);
|
||||
IoapicWrite(IOREDTBL_HI(i), (gBspLapicId & 0xFFu) << 24);
|
||||
for (uint32_t index = 0; index < gIoapicCount; index++) {
|
||||
HAL_IOAPIC* apic = &gIoapics[index];
|
||||
apic->Registers = (volatile uint32_t*)HalPhysicalToVirtual(apic->Physical);
|
||||
uint32_t version = IoapicRead(apic, 1u);
|
||||
apic->Pins = ((version >> 16) & 0xFFu) + 1u;
|
||||
for (uint32_t pin = 0; pin < apic->Pins; pin++) {
|
||||
IoapicWrite(apic, IOREDTBL_LO(pin), (1u << 16) | KE_VECTOR_DEVICE_FIRST);
|
||||
IoapicWrite(apic, IOREDTBL_HI(pin), (gBspLapicId & 255u) << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-114
@@ -39,10 +39,13 @@ static HAL_API gApi = {
|
||||
.Start = HalApicStartProcessor,
|
||||
},
|
||||
.InterruptController = {
|
||||
.RouteIrq = HalApicRouteIrq,
|
||||
.MaskIrq = HalApicMaskIrq,
|
||||
.UnmaskIrq = HalApicUnmaskIrq,
|
||||
.RouteGsi = HalApicRouteGsi,
|
||||
.MaskGsi = HalApicMaskGsi,
|
||||
.ResolveIsa = HalApicResolveIsa,
|
||||
.SendEoi = HalApicSendEoi,
|
||||
.SetTaskPriority = HalApicSetTaskPriority,
|
||||
.QueryTaskPriority = HalApicQueryTaskPriority,
|
||||
.VectorPending = HalApicVectorPending,
|
||||
.InitializeCurrentProcessor = HalApicInitializeCurrentProcessor,
|
||||
.SendProcessorInterrupt = HalApicSendProcessorInterrupt,
|
||||
.SendProcessorNmi = HalApicSendProcessorNmi,
|
||||
@@ -122,12 +125,7 @@ typedef struct ACPI_FIXED_REGISTER {
|
||||
|
||||
static ACPI_FIXED_REGISTER gPm1aCnt;
|
||||
static ACPI_FIXED_REGISTER gPm1bCnt;
|
||||
static ACPI_FIXED_REGISTER gPm1aStatus;
|
||||
static ACPI_FIXED_REGISTER gPm1bStatus;
|
||||
static ACPI_FIXED_REGISTER gPm1aEnable;
|
||||
static ACPI_FIXED_REGISTER gPm1bEnable;
|
||||
static uint16_t gSciIrq = 0;
|
||||
static bool gFixedPowerButtonArmed = false;
|
||||
static ACPI_FIXED_REGISTER gSleepControl;
|
||||
static uint32_t gLegacyPm1aPort = 0;
|
||||
static uint32_t gLegacyPm1bPort = 0;
|
||||
@@ -179,13 +177,6 @@ void* HalPhysicalToVirtual(uint64_t phys) {
|
||||
// systems may put the real DSDT and PM1 control registers in the extended
|
||||
// X_* fields, so do not rely only on the legacy 32-bit fields.
|
||||
#define FADT_SCI_INT_OFFSET 46u
|
||||
#define FADT_PM1A_EVT_BLK_OFFSET 56u
|
||||
#define FADT_PM1B_EVT_BLK_OFFSET 60u
|
||||
#define FADT_PM1_EVT_LEN_OFFSET 88u
|
||||
#define FADT_X_PM1A_EVT_BLK_OFFSET 148u
|
||||
#define FADT_X_PM1B_EVT_BLK_OFFSET 160u
|
||||
#define FADT_FLAG_POWER_BUTTON (1u << 4)
|
||||
#define ACPI_PM1_POWER_BUTTON_BIT (1u << 8)
|
||||
#define FADT_DSDT_OFFSET 40u
|
||||
#define FADT_SMI_CMD_OFFSET 48u
|
||||
#define FADT_ACPI_ENABLE_OFFSET 52u
|
||||
@@ -217,7 +208,6 @@ typedef struct {
|
||||
static ACPI_FIXED_REGISTER gResetRegister;
|
||||
static uint8_t gResetValue;
|
||||
|
||||
// Implements the acpi Read U32 operation.
|
||||
static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) {
|
||||
uint32_t value = 0;
|
||||
if (off + sizeof(value) <= tableLen)
|
||||
@@ -225,7 +215,6 @@ static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off)
|
||||
return value;
|
||||
}
|
||||
|
||||
// Implements the acpi Read U64 operation.
|
||||
static uint64_t AcpiReadU64(const void* table, uint32_t tableLen, uint32_t off) {
|
||||
uint64_t value = 0;
|
||||
if (off + sizeof(value) <= tableLen)
|
||||
@@ -310,77 +299,6 @@ static void AcpiWriteFixedRegister(const ACPI_FIXED_REGISTER* reg, uint32_t valu
|
||||
else *(volatile uint32_t*)address = value;
|
||||
}
|
||||
|
||||
// Selects a PM1 event block as two adjacent equal-width status and enable registers.
|
||||
static void AcpiConfigurePm1EventBlock(const void* fadt, uint32_t len,
|
||||
uint32_t legacyOffset, uint32_t gasOffset,
|
||||
uint8_t halfLength, ACPI_FIXED_REGISTER* status,
|
||||
ACPI_FIXED_REGISTER* enable) {
|
||||
ACPI_FIXED_REGISTER block = {0};
|
||||
uint32_t legacy = AcpiReadU32(fadt, len, legacyOffset);
|
||||
if (legacy && legacy <= 0xFFFFu) {
|
||||
block.AddressSpaceId = 1;
|
||||
block.Address = legacy;
|
||||
}
|
||||
ACPI_FIXED_REGISTER extended = {0};
|
||||
if (AcpiReadGasRegister(fadt, len, gasOffset, &extended)) block = extended;
|
||||
if (!block.Address || (block.AddressSpaceId == 1 &&
|
||||
block.Address + halfLength * 2u - 1u > 0xFFFFu)) return;
|
||||
block.WidthBytes = halfLength;
|
||||
*status = block;
|
||||
block.Address += halfLength;
|
||||
*enable = block;
|
||||
}
|
||||
|
||||
// Reports the fixed-feature power-button interrupt supported by this HAL.
|
||||
static KSTATUS AcpiQueryFixedButtonIrq(uint8_t* irqOut) {
|
||||
if (!irqOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
// A FADT control-method power button requires AML evaluation, not PM1 polling.
|
||||
if (gHwReducedAcpi || (gFadtFlags & FADT_FLAG_POWER_BUTTON) ||
|
||||
!gSciIrq || gSciIrq >= 16u || !gPm1aStatus.Address || !gPm1aEnable.Address ||
|
||||
!HalApicCanRouteIrq((uint8_t)gSciIrq))
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
*irqOut = (uint8_t)gSciIrq;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Discards any stale press then enables the PM1 fixed power-button SCI.
|
||||
static KSTATUS AcpiArmFixedButton(void) {
|
||||
uint8_t irq;
|
||||
KSTATUS status = AcpiQueryFixedButtonIrq(&irq);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
// No SCI_EN means firmware still owns ACPI events. Never steal ownership
|
||||
// through SMI_CMD just to install a power-button handler during boot.
|
||||
if (!(AcpiReadFixedRegister(&gPm1aCnt) & 1u))
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT);
|
||||
if (gPm1bStatus.Address)
|
||||
AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT);
|
||||
uint32_t enabled = AcpiReadFixedRegister(&gPm1aEnable);
|
||||
AcpiWriteFixedRegister(&gPm1aEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT);
|
||||
if (gPm1bEnable.Address) {
|
||||
enabled = AcpiReadFixedRegister(&gPm1bEnable);
|
||||
AcpiWriteFixedRegister(&gPm1bEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT);
|
||||
}
|
||||
gFixedPowerButtonArmed = true;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Acknowledges the fixed-button source only; the SCI may carry unrelated events.
|
||||
static bool AcpiConsumeFixedButton(void) {
|
||||
if (!gFixedPowerButtonArmed) return false;
|
||||
bool pressed = false;
|
||||
if (AcpiReadFixedRegister(&gPm1aStatus) & ACPI_PM1_POWER_BUTTON_BIT) {
|
||||
AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT);
|
||||
pressed = true;
|
||||
}
|
||||
if (gPm1bStatus.Address &&
|
||||
(AcpiReadFixedRegister(&gPm1bStatus) & ACPI_PM1_POWER_BUTTON_BIT)) {
|
||||
AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT);
|
||||
pressed = true;
|
||||
}
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// Detects whether PM1 control is using the standard Intel PCH PMBASE layout.
|
||||
static void AcpiDetectIntelPchPmBase(void) {
|
||||
gIntelPchPmBase = 0;
|
||||
@@ -486,7 +404,6 @@ static const uint8_t* AmlParseNameString(const uint8_t* p, const uint8_t* end,
|
||||
return p;
|
||||
}
|
||||
|
||||
// Implements the aml Read Integer operation.
|
||||
static bool AmlReadInteger(const uint8_t** pp, const uint8_t* end, uint8_t* out) {
|
||||
const uint8_t* p = *pp;
|
||||
if (p >= end) return false;
|
||||
@@ -580,10 +497,6 @@ static void ParseFadt(const ACPISDTHeader* header) {
|
||||
|
||||
memset(&gPm1aCnt, 0, sizeof(gPm1aCnt));
|
||||
memset(&gPm1bCnt, 0, sizeof(gPm1bCnt));
|
||||
memset(&gPm1aStatus, 0, sizeof(gPm1aStatus));
|
||||
memset(&gPm1bStatus, 0, sizeof(gPm1bStatus));
|
||||
memset(&gPm1aEnable, 0, sizeof(gPm1aEnable));
|
||||
memset(&gPm1bEnable, 0, sizeof(gPm1bEnable));
|
||||
gSciIrq = 0;
|
||||
if (len >= FADT_SCI_INT_OFFSET + sizeof(gSciIrq))
|
||||
memcpy(&gSciIrq, (const uint8_t*)fadt + FADT_SCI_INT_OFFSET, sizeof(gSciIrq));
|
||||
@@ -628,16 +541,6 @@ static void ParseFadt(const ACPISDTHeader* header) {
|
||||
if (gHwReducedAcpi)
|
||||
(void)AcpiReadByteGasRegister(fadt, len, FADT_SLEEP_CONTROL_OFFSET, &gSleepControl);
|
||||
|
||||
uint8_t eventLength = FADT_PM1_EVT_LEN_OFFSET < len ?
|
||||
*((const uint8_t*)fadt + FADT_PM1_EVT_LEN_OFFSET) : 0u;
|
||||
if (!gHwReducedAcpi && (eventLength == 4u || eventLength == 8u)) {
|
||||
uint8_t half = eventLength / 2u;
|
||||
AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1A_EVT_BLK_OFFSET,
|
||||
FADT_X_PM1A_EVT_BLK_OFFSET, half, &gPm1aStatus, &gPm1aEnable);
|
||||
AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1B_EVT_BLK_OFFSET,
|
||||
FADT_X_PM1B_EVT_BLK_OFFSET, half, &gPm1bStatus, &gPm1bEnable);
|
||||
}
|
||||
|
||||
gSmiCommandPort = AcpiReadU32(fadt, len, FADT_SMI_CMD_OFFSET);
|
||||
gAcpiEnableValue = FADT_ACPI_ENABLE_OFFSET < len
|
||||
? *((const uint8_t*)fadt + FADT_ACPI_ENABLE_OFFSET)
|
||||
@@ -652,10 +555,12 @@ static void ParseFadt(const ACPISDTHeader* header) {
|
||||
centuryRegister = *((const uint8_t*)fadt + FADT_CENTURY_OFFSET);
|
||||
HalRtcSetCenturyRegister(centuryRegister);
|
||||
|
||||
HalDbgPrint("HAL: FADT flags=0x%08x hw_reduced=%u PM1a_CNT=%u:0x%016llx legacy=0x%04x "
|
||||
HalDbgPrint("HAL: FADT flags=0x%08x sci_irq=%u power_button=%s hw_reduced=%u PM1a_CNT=%u:0x%016llx legacy=0x%04x "
|
||||
"PM1b_CNT=%u:0x%016llx legacy=0x%04x SLEEP_CTL=%u:0x%016llx "
|
||||
"SMI=0x%08x DSDT=0x%016llx RTC_CENTURY=0x%02x\n",
|
||||
gFadtFlags, gHwReducedAcpi ? 1u : 0u,
|
||||
gFadtFlags, (unsigned)gSciIrq,
|
||||
(gFadtFlags & (1u << 4)) ? "control-method" : "fixed",
|
||||
gHwReducedAcpi ? 1u : 0u,
|
||||
gPm1aCnt.AddressSpaceId, gPm1aCnt.Address, gLegacyPm1aPort,
|
||||
gPm1bCnt.AddressSpaceId, gPm1bCnt.Address, gLegacyPm1bPort,
|
||||
gSleepControl.AddressSpaceId, gSleepControl.Address,
|
||||
@@ -674,7 +579,6 @@ static void ParseFadt(const ACPISDTHeader* header) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the add Cpu Record operation.
|
||||
static void HalAddCpuRecord(uint32_t uid, uint32_t lapicId, uint32_t flags) {
|
||||
if (gCpuTopology.Count >= HAL_MAX_PROCESSORS)
|
||||
return;
|
||||
@@ -711,7 +615,7 @@ static void ParseMadt(MADT* madt) {
|
||||
gIoapicPhys = *(uint32_t*)(p + 4);
|
||||
uint32_t base;
|
||||
memcpy(&base, p + 8, sizeof(base));
|
||||
HalApicSetGsiBase(base);
|
||||
HalApicAddIoapic(*(uint32_t*)(p + 4), base);
|
||||
} else if (type == 2 && len >= 10 && p[2] == 0) { // ISA source override
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
@@ -732,7 +636,6 @@ static void ParseMadt(MADT* madt) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the walk Acpi operation.
|
||||
static void WalkAcpi(uintptr_t rsdpPhys) {
|
||||
if (!rsdpPhys) return;
|
||||
|
||||
@@ -995,8 +898,7 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
HalDbgPrint("HAL: LAPIC=%016llx IOAPIC=%016llx HPET=%016llx\n",
|
||||
gLapicPhys, gIoapicPhys, gHpetPhys);
|
||||
|
||||
HalApicSetSciIrq(gSciIrq);
|
||||
HalApicInitialize(gLapicPhys, gIoapicPhys);
|
||||
HalApicInitialize(gLapicPhys);
|
||||
HalDbgPrint("HAL: local APIC mode=%s BSP_ID=%u\n",
|
||||
HalApicUsingX2Apic() ? "x2APIC" : "xAPIC",
|
||||
HalApicGetBootProcessorId());
|
||||
@@ -1008,9 +910,6 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
HalPciInitialize(&gApi.Pci);
|
||||
gApi.Power.Shutdown = HalShutdown;
|
||||
gApi.Power.Reset = HalReset;
|
||||
gApi.Power.QueryFixedButtonIrq = AcpiQueryFixedButtonIrq;
|
||||
gApi.Power.ArmFixedButton = AcpiArmFixedButton;
|
||||
gApi.Power.ConsumeFixedButton = AcpiConsumeFixedButton;
|
||||
|
||||
AcpiDetectIntelPchPmBase();
|
||||
gInitialised = 1;
|
||||
@@ -1026,7 +925,6 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
gApi.Timer.Stall(1); // Micro-stalls
|
||||
}
|
||||
|
||||
HalDbgPrint("HAL: initialisation complete.\n");
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ static void PciWrite32(uint16_t segment,
|
||||
__outdword(PCI_CONFIG_DATA, value);
|
||||
}
|
||||
|
||||
// Implements the pci Initialize operation.
|
||||
void HalPciInitialize(HAL_PCI* out) {
|
||||
out->Read32 = PciRead32;
|
||||
out->Write32 = PciWrite32;
|
||||
|
||||
@@ -23,23 +23,19 @@
|
||||
|
||||
static uint8_t gCenturyRegister;
|
||||
|
||||
// Implements the rtc Read operation.
|
||||
static uint8_t RtcRead(uint8_t reg) {
|
||||
__outbyte(CMOS_INDEX_PORT, (uint8_t)(reg | 0x80u)); // keep NMI masked while selecting.
|
||||
return __inbyte(CMOS_DATA_PORT);
|
||||
}
|
||||
|
||||
// Implements the rtc Update In Progress operation.
|
||||
static bool RtcUpdateInProgress(void) {
|
||||
return (RtcRead(RTC_REG_STATUS_A) & 0x80u) != 0;
|
||||
}
|
||||
|
||||
// Implements the rtc Bcd To Binary operation.
|
||||
static uint8_t RtcBcdToBinary(uint8_t value) {
|
||||
return (uint8_t)(((value >> 4) * 10u) + (value & 0x0Fu));
|
||||
}
|
||||
|
||||
// Implements the rtc Read Stable operation.
|
||||
static bool RtcReadStable(HAL_RTC_TIME* out) {
|
||||
if (!out) return false;
|
||||
|
||||
@@ -116,12 +112,10 @@ static bool RtcReadStable(HAL_RTC_TIME* out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Implements the rtc Leap Year operation.
|
||||
static bool RtcLeapYear(uint16_t year) {
|
||||
return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u);
|
||||
}
|
||||
|
||||
// Implements the rtc Days In Month operation.
|
||||
static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) {
|
||||
static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
if (month < 1u || month > 12u) return 0;
|
||||
@@ -129,7 +123,6 @@ static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) {
|
||||
return days[month - 1u];
|
||||
}
|
||||
|
||||
// Implements the rtc Valid operation.
|
||||
static bool RtcValid(const HAL_RTC_TIME* t) {
|
||||
if (!t) return false;
|
||||
if (t->Year < 1970u || t->Year > 9999u) return false;
|
||||
@@ -140,7 +133,6 @@ static bool RtcValid(const HAL_RTC_TIME* t) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Implements the rtc Query Time operation.
|
||||
static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) {
|
||||
if (!outTime) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
@@ -153,12 +145,10 @@ static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the rtc Set Century Register operation.
|
||||
void HalRtcSetCenturyRegister(uint8_t centuryRegister) {
|
||||
gCenturyRegister = centuryRegister;
|
||||
}
|
||||
|
||||
// Implements the rtc Initialize operation.
|
||||
void HalRtcInitialize(HAL_RTC* out) {
|
||||
if (!out) return;
|
||||
out->QueryTime = HalRtcQueryTime;
|
||||
|
||||
@@ -39,7 +39,6 @@ static inline void PutPixelRaw(int32_t x, int32_t y, uint32_t color) {
|
||||
gFb[y * gStride + x] = color;
|
||||
}
|
||||
|
||||
// Implements the screen Flush Rows operation.
|
||||
static void ScreenFlushRows(int startY, int rows) {
|
||||
if (!gBackbuffer || rows <= 0)
|
||||
return;
|
||||
@@ -73,12 +72,10 @@ static void ScreenClear(uint32_t color) {
|
||||
gCursorX = 0; gCursorY = 0;
|
||||
}
|
||||
|
||||
// Implements the screen Put Pixel operation.
|
||||
static void ScreenPutPixel(int32_t x, int32_t y, uint32_t color) {
|
||||
PutPixelRaw(x, y, color);
|
||||
}
|
||||
|
||||
// Implements the screen Blit operation.
|
||||
static void ScreenBlit(int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels) {
|
||||
// Calculate clipping bounds.
|
||||
int startX = (x < 0) ? 0 : x;
|
||||
@@ -111,10 +108,8 @@ static void ScreenBlit(int32_t x, int32_t y, int32_t w, int32_t h, const uint32_
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the screen Get Size operation.
|
||||
static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; }
|
||||
|
||||
// Implements the screen Get Framebuffer operation.
|
||||
static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) {
|
||||
if (!outInfo || !gFb || gWidth <= 0 || gHeight <= 0 || gStride <= 0)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -127,7 +122,6 @@ static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the screen Scroll operation.
|
||||
static void ScreenScroll(int32_t lines) {
|
||||
if (lines <= 0)
|
||||
return;
|
||||
@@ -153,7 +147,6 @@ static void ScreenScroll(int32_t lines) {
|
||||
ScreenFlushRows(0, gHeight);
|
||||
}
|
||||
|
||||
// Implements the screen Put Char operation.
|
||||
static void ScreenPutChar(char c, int32_t x, int32_t y, uint32_t fg, uint32_t bg) {
|
||||
const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16);
|
||||
for (int32_t row = 0; row < 16; row++) {
|
||||
@@ -165,7 +158,6 @@ static void ScreenPutChar(char c, int32_t x, int32_t y, uint32_t fg, uint32_t bg
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the screen Print Char operation.
|
||||
static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) {
|
||||
int cols = gWidth / FONT_W;
|
||||
int rows = gHeight / FONT_H;
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
#include <kernel/hal/hal_timer.h>
|
||||
#include <kernel/hal/hal_internal.h>
|
||||
#include <kernel/hal/hal_debug.h>
|
||||
#include <kernel/ke_vectors.h>
|
||||
|
||||
#define LAPIC_TIMER_LVT 0x320
|
||||
#define LAPIC_TIMER_INIT 0x380
|
||||
#define LAPIC_TIMER_CUR 0x390
|
||||
#define LAPIC_TIMER_DIV 0x3E0
|
||||
|
||||
#define TIMER_VECTOR 0x20 // vector 0x20 = IRQ 0 slot in IDT
|
||||
#define TIMER_VECTOR KE_VECTOR_CPU_TIMER
|
||||
#define TIMER_PERIODIC (1 << 17)
|
||||
#define TIMER_MASKED (1 << 16)
|
||||
#define TIMER_DIV16 0x3
|
||||
@@ -30,9 +31,7 @@ static volatile uint64_t* gHpet = NULL;
|
||||
|
||||
static volatile uint64_t gTicks = 0;
|
||||
|
||||
// Implements the outb operation.
|
||||
static inline void outb(uint16_t port, uint8_t val) { __outbyte(port, val); }
|
||||
// Implements the inb operation.
|
||||
static inline uint8_t inb(uint16_t port) { return __inbyte(port); }
|
||||
|
||||
// Records one local timer interrupt for HAL timekeeping fallback.
|
||||
@@ -87,7 +86,6 @@ static uint64_t QueryTickFrequency(void) {
|
||||
return 1000000ull;
|
||||
}
|
||||
|
||||
// Implements the stall operation.
|
||||
void HalTimerStall(uint32_t us) {
|
||||
// Priority 1: Use HPET (Highest Precision).
|
||||
if (gHpet && gHpetTicksPerUs > 0) {
|
||||
@@ -187,7 +185,6 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) {
|
||||
return elapsed / 10; // APIC ticks per ms
|
||||
}
|
||||
|
||||
// Implements the timer Configure Current Cpu operation.
|
||||
void HalTimerConfigureCurrentProcessor(void) {
|
||||
if (!gLapic || !gApicTicksPerQuantum) return;
|
||||
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
|
||||
@@ -195,14 +192,12 @@ void HalTimerConfigureCurrentProcessor(void) {
|
||||
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
|
||||
}
|
||||
|
||||
// Implements the timer Initialize operation.
|
||||
KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* out) {
|
||||
gLapic = (volatile uint32_t*)HalPhysicalToVirtual(lapicPhys);
|
||||
HalDbgPrint("HAL: lapicPhys=0x%016llX, lapicVirt=0x%016llX, hpetPhys=0x%016llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys);
|
||||
|
||||
uint32_t ticksPerMs = 0;
|
||||
if (hpetPhys) {
|
||||
HalDbgPrint("HAL: Attempting to calibrate APIC timer via HPET...\n");
|
||||
ticksPerMs = CalibrateApicTimerViaHpet(hpetPhys);
|
||||
}
|
||||
if (!ticksPerMs) {
|
||||
@@ -210,7 +205,7 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* o
|
||||
ticksPerMs = CalibrateApicTimerViaPit();
|
||||
}
|
||||
if (!ticksPerMs) {
|
||||
HalDbgPrint("HAL: APIC calibration failed. How?\n");
|
||||
HalDbgPrint("hal: APIC timer calibration failed\n");
|
||||
return NTLSTATUS_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
@@ -226,14 +221,13 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* o
|
||||
|
||||
HalDbgPrint("HAL: APIC timer: %u ticks/ms\n", ticksPerMs);
|
||||
|
||||
// Leave the BSP timer masked until the kernel registers its scheduler
|
||||
// callback and IRQ route. APs arm their local timer after per-CPU setup.
|
||||
// Leave the BSP timer masked until the kernel installs its timer handlers.
|
||||
// APs arm their local timer after per-CPU setup.
|
||||
|
||||
out->QueryTicks = HalTimerQueryTicks;
|
||||
out->QueryTickFrequency = QueryTickFrequency;
|
||||
out->Stall = HalTimerStall;
|
||||
out->HandleInterrupt = TimerInterrupt;
|
||||
out->ConfigureCurrentProcessor = HalTimerConfigureCurrentProcessor;
|
||||
out->IrqNumber = 0;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
!include $(BASEDIR)\makefile.def
|
||||
@@ -0,0 +1,11 @@
|
||||
TARGETNAME=hal
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=DYNLINK
|
||||
IMAGE_KIND=DLL
|
||||
FLAVOR=KERNEL
|
||||
EXTRA_CFLAGS=/DNTL_HAL_BUILD
|
||||
TARGETLIBS="$(BASEDIR)\bin\printf.lib" "$(BASEDIR)\bin\libc.lib"
|
||||
EXTRA_LFLAGS=/NOENTRY /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800010000000 /IGNORE:4216
|
||||
INCLUDES=$(BASEDIR)\code\kernel\include
|
||||
SOURCES=@/code/kernel/hal/hal_apic.c @/code/kernel/hal/hal_disk.c @/code/kernel/hal/hal_keyboard.c @/code/kernel/hal/hal_main.c @/code/kernel/hal/hal_mouse.c @/code/kernel/hal/hal_output.c \
|
||||
@/code/kernel/hal/hal_pci.c @/code/kernel/hal/hal_processor.c @/code/kernel/hal/hal_rtc.c @/code/kernel/hal/hal_screen.c @/code/kernel/hal/hal_serial.c @/code/kernel/hal/hal_timer.c
|
||||
Reference in new issue
Block a user