Files
nt-lite/code/kernel/io_ddk.c
T

120 lines
3.6 KiB
C

// Kernel DDK-table provider implementation.
#include <stdint.h>
#include <ntlite/ddk/ddk.h>
#include <ntlite/ddi/hal_api.h>
#include <kernel/hal/hal_apic.h>
#include <kernel/io_ddk.h>
#include <kernel/ke_irq.h>
#include <kernel/ke_sched.h>
static const HAL_API* gIoDdkHal;
// Returns the kernel direct-map alias for a physical address.
static void* IoDdkPhysToVirt(uint64_t physicalAddress) {
if (!gIoDdkHal || !gIoDdkHal->PhysToVirt)
return (void*)0;
return gIoDdkHal->PhysToVirt(physicalAddress);
}
// Maps one kernel page through the DDK memory surface.
static KSTATUS IoDdkMapPage(uintptr_t virtualAddress,
uint64_t physicalAddress,
uint64_t pageFlags,
NTL_DDK_MAP_MODE mode) {
MM_PTE_MAP_MODE kernelMode = MmPteMapFailIfPresent;
if (mode == NtlDdkMapReplaceExisting)
kernelMode = MmPteMapReplaceExisting;
return MmPteMapPage(virtualAddress, physicalAddress, pageFlags, kernelMode);
}
// Reads one aligned PCI configuration DWORD through the platform HAL.
static uint32_t IoDdkPciRead32(uint16_t segment,
uint8_t bus,
uint8_t device,
uint8_t function,
uint16_t offset) {
if (!gIoDdkHal || !gIoDdkHal->Pci.Read32)
return 0xFFFFFFFFu;
return gIoDdkHal->Pci.Read32(segment, bus, device, function, offset);
}
// Writes one aligned PCI configuration DWORD through the platform HAL.
static void IoDdkPciWrite32(uint16_t segment,
uint8_t bus,
uint8_t device,
uint8_t function,
uint16_t offset,
uint32_t value) {
if (!gIoDdkHal || !gIoDdkHal->Pci.Write32)
return;
gIoDdkHal->Pci.Write32(segment, bus, device, function, offset, value);
}
// Returns the BSP local APIC identifier.
static uint32_t IoDdkGetBspLapicId(void) {
return HalGetBspLapicId();
}
// Returns whether the platform interrupt controller is using x2APIC mode.
static uint8_t IoDdkIsX2ApicEnabled(void) {
return HalApicUsingX2Apic();
}
// Allocates one kernel IRQ slot for MSI delivery.
static KSTATUS IoDdkAllocateMsiVector(uint8_t* outIrq) {
return KeIrqAllocateMsiVector(outIrq);
}
static const NTL_DDK_DEBUG gIoDdkDebug = {
.Print = DbgPrint,
};
static const NTL_DDK_INTERRUPT gIoDdkInterrupt = {
.AllocateMsiVector = IoDdkAllocateMsiVector,
};
static const NTL_DDK_MEMORY gIoDdkMemory = {
.PhysToVirt = IoDdkPhysToVirt,
.MapPage = IoDdkMapPage,
};
static const NTL_DDK_PLATFORM gIoDdkPlatform = {
.PciRead32 = IoDdkPciRead32,
.PciWrite32 = IoDdkPciWrite32,
.GetBspLapicId = IoDdkGetBspLapicId,
.IsX2ApicEnabled = IoDdkIsX2ApicEnabled,
};
static const NTL_DDK_SCHEDULER gIoDdkScheduler = {
.DelayThread = KeDelayThread,
.Yield = KeYield,
};
static NTL_DDK_TIMER gIoDdkTimer = {
.QueryTicks = 0,
.Stall = 0,
};
static NTL_DDK gIoDdk = {
.Version = NTL_DDK_VERSION,
.Debug = &gIoDdkDebug,
.Interrupt = &gIoDdkInterrupt,
.Memory = &gIoDdkMemory,
.Platform = &gIoDdkPlatform,
.Scheduler = &gIoDdkScheduler,
.Timer = &gIoDdkTimer,
};
// Initializes the kernel-owned DDK table from platform services.
void IoInitializeDdk(const HAL_API* hal) {
gIoDdkHal = hal;
gIoDdkTimer.QueryTicks = hal ? hal->Timer.QueryTicks : 0;
gIoDdkTimer.Stall = hal ? hal->Timer.Stall : 0;
}
// Returns the kernel-owned DDK table passed to driver entrypoints.
const NTL_DDK* IoGetDdk(void) {
return &gIoDdk;
}