120 lines
3.6 KiB
C
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;
|
|
}
|