136 lines
4.3 KiB
C
136 lines
4.3 KiB
C
// Kernel DDK-table provider implementation.
|
|
|
|
#include <stdint.h>
|
|
#include <ntlite/ddk/ddk.h>
|
|
#include <kernel/hal/hal_api.h>
|
|
#include <kernel/io_ddk.h>
|
|
#include <kernel/io_dma.h>
|
|
#include <kernel/ke_audio.h>
|
|
#include <kernel/ke_debug.h>
|
|
#include <kernel/ke_irq.h>
|
|
#include <kernel/ke_sched.h>
|
|
#include <kernel/mm_pte.h>
|
|
|
|
static const HAL_API* gIoDdkHal;
|
|
static uintptr_t gIoDdkPhysicalWindowBase;
|
|
|
|
// Returns the kernel direct-map alias for a physical address.
|
|
static void* IoDdkPhysToVirt(uint64_t physicalAddress) {
|
|
if (!gIoDdkPhysicalWindowBase || physicalAddress > UINTPTR_MAX - gIoDdkPhysicalWindowBase)
|
|
return (void*)0;
|
|
return (void*)(gIoDdkPhysicalWindowBase + (uintptr_t)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);
|
|
}
|
|
|
|
// Allocates one kernel IRQ slot for MSI delivery.
|
|
static KSTATUS IoDdkAllocateMsiVector(uint8_t* outIrq) {
|
|
return KeIrqAllocateMsiVector(outIrq);
|
|
}
|
|
|
|
|
|
// Composes one platform MSI message for an allocated nt-lite IRQ slot.
|
|
static KSTATUS IoDdkComposeMsiMessage(uint8_t irq, NTL_DDK_MSI_MESSAGE* messageOut) {
|
|
if (!gIoDdkHal || !messageOut || irq >= 24u)
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
|
|
HAL_MSI_MESSAGE message;
|
|
KSTATUS status = gIoDdkHal->InterruptController.ComposeMsi((uint8_t)(0x20u + irq), &message);
|
|
if (!KSUCCESS(status))
|
|
return status;
|
|
|
|
messageOut->Address = message.Address;
|
|
messageOut->Data = message.Data;
|
|
messageOut->Reserved = 0;
|
|
return NTLSTATUS_SUCCESS;
|
|
}
|
|
|
|
static const NTL_DDK_DEBUG gIoDdkDebug = {
|
|
.Print = DbgPrint,
|
|
.GetFlags = KeGetDebugFlags,
|
|
};
|
|
|
|
static const NTL_DDK_INTERRUPT gIoDdkInterrupt = {
|
|
.AllocateMsiVector = IoDdkAllocateMsiVector,
|
|
.ComposeMsiMessage = IoDdkComposeMsiMessage,
|
|
};
|
|
|
|
static const NTL_DDK_MEMORY gIoDdkMemory = {
|
|
.PhysToVirt = IoDdkPhysToVirt,
|
|
.MapPage = IoDdkMapPage,
|
|
};
|
|
|
|
static const NTL_DDK_PLATFORM gIoDdkPlatform = {
|
|
.PciRead32 = IoDdkPciRead32,
|
|
.PciWrite32 = IoDdkPciWrite32,
|
|
};
|
|
|
|
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,
|
|
.Audio = (const NTL_DDK_AUDIO*)0,
|
|
.Dma = (const NTL_DDK_DMA*)0,
|
|
.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, uintptr_t physicalWindowBase) {
|
|
gIoDdkHal = hal;
|
|
gIoDdkPhysicalWindowBase = physicalWindowBase;
|
|
gIoDdk.Audio = KeAudioGetDdk();
|
|
gIoDdk.Dma = IoGetDmaDdk();
|
|
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;
|
|
}
|