replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
@@ -0,0 +1,157 @@
|
||||
// Optional firmware-event driver using the resident ACPICA namespace.
|
||||
#include <ntlite/ddk/module.h>
|
||||
#include <ntlite/atomic.h>
|
||||
#include <ntlite/ddk/platform.h>
|
||||
#include <ntlite/ddk/debug.h>
|
||||
#include <ntlite/ddk/power.h>
|
||||
#include "third_party/acpica/include/acpi.h"
|
||||
#include "third_party/acpica/include/aclocal.h"
|
||||
#include "third_party/acpica/include/acobject.h"
|
||||
#include "third_party/acpica/include/acglobal.h"
|
||||
#include "acpi_local.h"
|
||||
#include <ntlite/ddk/irql.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
// Firmware callbacks remain resident until the final ACPI S5 transition.
|
||||
static KSTATUS AcpiNtlPreparePower(void* context, uint32_t action) {
|
||||
(void)context;
|
||||
if (action != SYS_POWER_ACTION_SHUTDOWN) return NTLSTATUS_NOT_SUPPORTED;
|
||||
ACPI_STATUS status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
DbgPrint("acpi: S5 preparation failed status=0x%x\n", (unsigned)status);
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static KSTATUS AcpiNtlEnterPower(void* context, uint32_t action) {
|
||||
(void)context;
|
||||
if (action != SYS_POWER_ACTION_SHUTDOWN) return NTLSTATUS_NOT_SUPPORTED;
|
||||
// ACPICA requires interrupts disabled for the final sleep-control writes.
|
||||
uintptr_t flags = KeDisableInterrupts();
|
||||
ACPI_STATUS status = AcpiEnterSleepState(ACPI_STATE_S5);
|
||||
KeRestoreInterrupts(flags);
|
||||
DbgPrint("acpi: S5 transition returned status=0x%x\n", (unsigned)status);
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static volatile int32_t gFixedButtonPending;
|
||||
static uint32_t gFixedButtonEvents;
|
||||
static uint32_t gMethodButtonEvents;
|
||||
static uint32_t gMethodButtons;
|
||||
|
||||
static void AcpiNtlDeliverButton(void* context) {
|
||||
(void)context;
|
||||
KSTATUS result = KeNotifyPowerButton();
|
||||
if (!KSUCCESS(result)) DbgPrint("acpi: power button delivery failed status=0x%x\n", result);
|
||||
}
|
||||
|
||||
static void AcpiNtlDeliverFixedButton(void* context) {
|
||||
AcpiNtlDeliverButton(context);
|
||||
NtlAtomicExchange32(&gFixedButtonPending, 0);
|
||||
}
|
||||
|
||||
bool AcpiNtlFixedButtonHasDeferred(void) {
|
||||
return NtlAtomicLoad32(&gFixedButtonPending) == 2;
|
||||
}
|
||||
|
||||
void AcpiNtlFixedButtonDrainDeferred(void) {
|
||||
if (NtlAtomicCompareExchange32(&gFixedButtonPending, 1, 2) == 2)
|
||||
AcpiNtlDeliverFixedButton(NULL);
|
||||
}
|
||||
|
||||
// Fixed-event handlers run in the SCI and delegate delivery to passive work.
|
||||
static UINT32 AcpiNtlFixedButton(void* context) {
|
||||
(void)context;
|
||||
gFixedButtonEvents++;
|
||||
if (NtlAtomicCompareExchange32(&gFixedButtonPending, 1, 0) == 0 &&
|
||||
ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER, AcpiNtlDeliverFixedButton, NULL))) {
|
||||
NtlAtomicExchange32(&gFixedButtonPending, 2);
|
||||
AcpiNtlWakeExecutor();
|
||||
}
|
||||
return ACPI_INTERRUPT_HANDLED;
|
||||
}
|
||||
|
||||
// 0x80 is the normal S0 press event; 0x02 is a wake notification.
|
||||
static void AcpiNtlButtonNotify(ACPI_HANDLE handle, UINT32 event, void* context) {
|
||||
(void)handle; (void)context;
|
||||
if (event == 0x80u) {
|
||||
gMethodButtonEvents++;
|
||||
AcpiNtlDeliverButton(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static ACPI_STATUS AcpiNtlFindButton(ACPI_HANDLE handle, UINT32 depth,
|
||||
void* context, void** returnValue) {
|
||||
(void)depth; (void)context; (void)returnValue;
|
||||
ACPI_STATUS result = AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY,
|
||||
AcpiNtlButtonNotify, NULL);
|
||||
if (ACPI_SUCCESS(result)) gMethodButtons++;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static KSTATUS AcpiDriverInitialize(NTL_MODULE* module) {
|
||||
(void)module;
|
||||
uint64_t root = 0;
|
||||
KSTATUS status = KeFirmwareQueryAcpiRsdp(&root);
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("acpi: RSDP query failed status=0x%x\n", status);
|
||||
return status;
|
||||
}
|
||||
ACPI_STATUS result = AcpiInitializeSubsystem();
|
||||
if (ACPI_FAILURE(result)) goto fail;
|
||||
result = AcpiInitializeTables(NULL, 32, TRUE);
|
||||
if (ACPI_FAILURE(result)) goto fail;
|
||||
result = AcpiLoadTables();
|
||||
if (ACPI_FAILURE(result)) goto fail;
|
||||
AcpiNtlRestrictRuntimeMappings();
|
||||
status = AcpiNtlPrepareMmioRegisters();
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("acpi: MMIO register mappings unavailable st=0x%x\n", status);
|
||||
result = AE_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
status = AcpiNtlStartExecutor();
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("acpi: event worker unavailable st=0x%x\n", status);
|
||||
result = AE_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
result = AcpiEnableSubsystem(0);
|
||||
if (ACPI_FAILURE(result)) goto fail;
|
||||
ACPI_STATUS ecStatus = AcpiNtlEcInitialize();
|
||||
if (ACPI_FAILURE(ecStatus))
|
||||
DbgPrint("acpi: EC enumeration failed status=0x%x\n", (unsigned)ecStatus);
|
||||
result = AcpiInitializeObjects(0);
|
||||
if (ACPI_FAILURE(result)) goto fail;
|
||||
AcpiNtlEcActivate();
|
||||
|
||||
ACPI_STATUS fixedStatus = AE_SUPPORT;
|
||||
if (!(AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)) {
|
||||
fixedStatus = AcpiInstallFixedEventHandler(
|
||||
ACPI_EVENT_POWER_BUTTON, AcpiNtlFixedButton, NULL);
|
||||
}
|
||||
ACPI_STATUS methodStatus = AcpiGetDevices("PNP0C0C", AcpiNtlFindButton, NULL, NULL);
|
||||
DbgPrint("acpi: ready rsdp=0x%016llX fixed=0x%x method=0x%x buttons=%u ec=%u\n",
|
||||
(unsigned long long)root, (unsigned)fixedStatus,
|
||||
(unsigned)methodStatus, gMethodButtons, AcpiNtlEcCount());
|
||||
const NTL_FIRMWARE_POWER_PROVIDER provider = {
|
||||
.Size = sizeof(NTL_FIRMWARE_POWER_PROVIDER),
|
||||
.Context = NULL,
|
||||
.Prepare = AcpiNtlPreparePower,
|
||||
.Enter = AcpiNtlEnterPower,
|
||||
};
|
||||
status = KeRegisterFirmwarePowerProvider(&provider);
|
||||
if (!KSUCCESS(status)) DbgPrint("acpi: power provider registration failed status=0x%x\n", status);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
fail:
|
||||
DbgPrint("acpi: namespace initialization failed status=0x%x\n",
|
||||
(unsigned)result);
|
||||
AcpiNtlEcTerminate();
|
||||
(void)AcpiTerminate();
|
||||
AcpiNtlStopExecutor();
|
||||
AcpiNtlReleaseMmioRegisters();
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTL_DECLARE_MODULE(AcpiDriverInitialize);
|
||||
Reference in new issue
Block a user