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:
1 parent
c0ad63c27f
commit
d36f19509c
160 files changed
+6563
-7366
No files matched your search
+115
-108
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user