replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.

This commit is contained in:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

+115 -108
View File
@@ -1,135 +1,142 @@
// 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;
static const HAL_API* gHal;
static uintptr_t gPhysicalWindowBase;
// 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);
void IoInitializeDdk(const HAL_API* hal, uintptr_t physicalWindowBase) {
gHal = hal;
gPhysicalWindowBase = physicalWindowBase;
}
// 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);
__declspec(dllexport) uint64_t KeQueryTicks(void) {
return gHal && gHal->Timer.QueryTicks ? gHal->Timer.QueryTicks() : 0;
}
// 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);
__declspec(dllexport) void KeStallExecution(uint32_t microseconds) {
if (gHal && gHal->Timer.Stall) gHal->Timer.Stall(microseconds);
}
// 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);
__declspec(dllexport) uint32_t KePciReadConfig32(uint16_t segment, uint8_t bus, uint8_t device, uint8_t function, uint16_t offset) {
return gHal && gHal->Pci.Read32 ? gHal->Pci.Read32(segment, bus, device, function, offset) : UINT32_MAX;
}
// Allocates one kernel IRQ slot for MSI delivery.
static KSTATUS IoDdkAllocateMsiVector(uint8_t* outIrq) {
return KeIrqAllocateMsiVector(outIrq);
__declspec(dllexport) void KePciWriteConfig32(uint16_t segment, uint8_t bus, uint8_t device, uint8_t function, uint16_t offset, uint32_t value) {
if (gHal && gHal->Pci.Write32) gHal->Pci.Write32(segment, bus, device, function, offset, value);
}
// 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)
__declspec(dllexport) KSTATUS KeIrqComposeMsiMessage(uint8_t irq, NTL_DDK_MSI_MESSAGE* out) {
if (!gHal || !out || irq >= 24u || !gHal->InterruptController.ComposeMsi)
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;
KSTATUS status = gHal->InterruptController.ComposeMsi((uint8_t)(0x20u + irq), &message);
if (!KSUCCESS(status)) return status;
out->Address = message.Address;
out->Data = message.Data;
out->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;
__declspec(dllexport) void* MmDdkPhysToVirt(uint64_t physicalAddress) {
if (!gPhysicalWindowBase || physicalAddress > UINTPTR_MAX - gPhysicalWindowBase)
return (void*)0;
return (void*)(gPhysicalWindowBase + (uintptr_t)physicalAddress);
}
// Returns the kernel-owned DDK table passed to driver entrypoints.
const NTL_DDK* IoGetDdk(void) {
return &gIoDdk;
__declspec(dllexport) KSTATUS MmDdkMapPage(uintptr_t virtualAddress, uint64_t physicalAddress, uint64_t flags, NTL_DDK_MAP_MODE mode) {
return MmPteMapPage(virtualAddress, physicalAddress, flags,
mode == NtlDdkMapReplaceExisting ? MmPteMapReplaceExisting : MmPteMapFailIfPresent);
}
__declspec(dllexport) KSTATUS IoDmaGetAdapter(struct DEVICE_OBJECT* device, const IO_DMA_REQUIREMENTS* requirements, IO_DMA_ADAPTER** outAdapter) {
return IoGetDmaDdk()->GetAdapter(device, requirements, outAdapter);
}
__declspec(dllexport) void IoDmaPutAdapter(IO_DMA_ADAPTER* adapter) {
IoGetDmaDdk()->PutAdapter(adapter);
}
__declspec(dllexport) KSTATUS IoDmaAllocateCommonBuffer(IO_DMA_ADAPTER* adapter, size_t size, size_t alignment, IO_DMA_BUFFER** outBuffer) {
return IoGetDmaDdk()->AllocateCommonBuffer(adapter, size, alignment, outBuffer);
}
__declspec(dllexport) void IoDmaFreeCommonBuffer(IO_DMA_BUFFER* buffer) {
IoGetDmaDdk()->FreeCommonBuffer(buffer);
}
__declspec(dllexport) void* IoDmaGetCommonBufferAddress(const IO_DMA_BUFFER* buffer) {
return IoGetDmaDdk()->GetCommonBufferAddress(buffer);
}
__declspec(dllexport) uint64_t IoDmaGetCommonBufferDeviceAddress(const IO_DMA_BUFFER* buffer) {
return IoGetDmaDdk()->GetCommonBufferDeviceAddress(buffer);
}
__declspec(dllexport) size_t IoDmaGetCommonBufferSize(const IO_DMA_BUFFER* buffer) {
return IoGetDmaDdk()->GetCommonBufferSize(buffer);
}
__declspec(dllexport) KSTATUS IoDmaPinKernelMemory(void* address, size_t size, IO_DMA_DIRECTION direction, MM_PINNED_MEMORY** outMemory) {
return IoGetDmaDdk()->PinKernelMemory(address, size, direction, outMemory);
}
__declspec(dllexport) KSTATUS IoDmaPinUserMemory(struct PROCESS* process, void* address, size_t size, IO_DMA_DIRECTION direction, MM_PINNED_MEMORY** outMemory) {
return IoGetDmaDdk()->PinUserMemory(process, address, size, direction, outMemory);
}
__declspec(dllexport) void IoDmaUnpinMemory(MM_PINNED_MEMORY* memory) {
IoGetDmaDdk()->UnpinMemory(memory);
}
__declspec(dllexport) KSTATUS IoDmaMapPinnedMemory(IO_DMA_ADAPTER* adapter, MM_PINNED_MEMORY* memory, size_t offset, size_t length, IO_DMA_DIRECTION direction, uint32_t flags, IO_DMA_MAPPING** outMapping) {
return IoGetDmaDdk()->MapPinnedMemory(adapter, memory, offset, length, direction, flags, outMapping);
}
__declspec(dllexport) void IoDmaUnmapMemory(IO_DMA_MAPPING* mapping) {
IoGetDmaDdk()->UnmapMemory(mapping);
}
__declspec(dllexport) KSTATUS IoDmaSynchronizeForDevice(IO_DMA_MAPPING* mapping) {
return IoGetDmaDdk()->SynchronizeForDevice(mapping);
}
__declspec(dllexport) KSTATUS IoDmaSynchronizeForCpu(IO_DMA_MAPPING* mapping) {
return IoGetDmaDdk()->SynchronizeForCpu(mapping);
}
__declspec(dllexport) uint32_t IoDmaGetSegmentCount(const IO_DMA_MAPPING* mapping) {
return IoGetDmaDdk()->GetSegmentCount(mapping);
}
__declspec(dllexport) const IO_DMA_SEGMENT* IoDmaGetSegments(const IO_DMA_MAPPING* mapping) {
return IoGetDmaDdk()->GetSegments(mapping);
}
__declspec(dllexport) void IoDmaQueryStats(IO_DMA_STATS* outStats) {
IoGetDmaDdk()->QueryStats(outStats);
}
__declspec(dllexport) KSTATUS IoAudioRegisterEndpoint(const IO_AUDIO_ENDPOINT_REGISTRATION* registration, IO_AUDIO_ENDPOINT** outEndpoint) {
return KeAudioGetDdk()->RegisterEndpoint(registration, outEndpoint);
}
__declspec(dllexport) void IoAudioUnregisterEndpoint(IO_AUDIO_ENDPOINT* endpoint, IO_AUDIO_REMOVAL_MODE mode) {
KeAudioGetDdk()->UnregisterEndpoint(endpoint, mode);
}
__declspec(dllexport) void IoAudioNotifyPeriod(IO_AUDIO_ENDPOINT* endpoint, uint32_t completedPeriodIndex, uint64_t presentedFrames, uint64_t hardwarePositionFrames, uint64_t interruptCount, uint64_t timestampTicks) {
KeAudioGetDdk()->NotifyPeriod(endpoint, completedPeriodIndex, presentedFrames, hardwarePositionFrames, interruptCount, timestampTicks);
}
__declspec(dllexport) void IoAudioSetEndpointAvailable(IO_AUDIO_ENDPOINT* endpoint, bool available) {
KeAudioGetDdk()->SetEndpointAvailable(endpoint, available);
}
__declspec(dllexport) void IoAudioReportEndpointFailure(IO_AUDIO_ENDPOINT* endpoint, KSTATUS status, uint32_t flags) {
KeAudioGetDdk()->ReportEndpointFailure(endpoint, status, flags);
}