janwas
cded0936c5
. update moduleInit mechanism and move it out of lib.cpp. now has a thread-safe reference count and allows repeated init/shutdown (required for self-tests) . vfs now depends on h_mgr; h_mgr need therefore no longer explicitly be shutdown (e.g. in self-tests) . acpi: minor fixes . cpu: AtomicAdd and CAS now take volatile variable (safer) . mahaf: unload driver on shutdown (did this for DriverVerifier, but it's 'cleaner' in general) . wdbg_sym . wfilesystem: get rid of manual declarations of deprecated functions; implement them via trampoline instead This was SVN commit r5086.
89 lines
2.0 KiB
C++
89 lines
2.0 KiB
C++
/**
|
|
* =========================================================================
|
|
* File : hpet.cpp
|
|
* Project : 0 A.D.
|
|
* Description : HPET timer backend
|
|
* =========================================================================
|
|
*/
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include "hpet.h"
|
|
#include "acpi.h"
|
|
#include "win/mahaf.h"
|
|
#include "lib/bits.h"
|
|
#include "lib/module_init.h"
|
|
|
|
#pragma pack(1)
|
|
|
|
struct HpetDescriptionTable
|
|
{
|
|
AcpiTable header;
|
|
u32 eventTimerBlockId;
|
|
AcpiGenericAddress baseAddress;
|
|
u8 sequenceNumber;
|
|
u16 minimumPeriodicTicks;
|
|
u8 attributes;
|
|
};
|
|
|
|
struct HpetRegisters
|
|
{
|
|
u64 capabilities;
|
|
u64 reserved1;
|
|
u64 config;
|
|
u64 reserved2;
|
|
u64 interruptStatus;
|
|
u64 reserved3[25];
|
|
u64 counterValue;
|
|
u64 reserved4;
|
|
|
|
// .. followed by blocks for timers 0..31
|
|
};
|
|
|
|
static volatile HpetRegisters* hpetRegisters;
|
|
|
|
static const u64 CONFIG_ENABLE = BIT64(0);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static ModuleInitState initState;
|
|
|
|
bool hpetInit()
|
|
{
|
|
if(!ModuleShouldInitialize(&initState))
|
|
return true;
|
|
|
|
if(!acpiInit())
|
|
return false;
|
|
|
|
const HpetDescriptionTable* desc = (const HpetDescriptionTable*)acpiGetTable("HPET");
|
|
debug_assert(desc->baseAddress.addressSpaceId == ACPI_AS_MEMORY);
|
|
hpetRegisters = (volatile HpetRegisters*)MapPhysicalMemory(desc->baseAddress.address, sizeof(HpetRegisters));
|
|
if(!hpetRegisters)
|
|
return false;
|
|
|
|
const u32 timerPeriod_fs = bits64(hpetRegisters->capabilities, 32, 63);
|
|
const double freq = 1e15 / timerPeriod_fs;
|
|
|
|
hpetRegisters->config &= ~CONFIG_ENABLE;
|
|
hpetRegisters->counterValue = 0ull;
|
|
hpetRegisters->config |= CONFIG_ENABLE;
|
|
|
|
debug_printf("HPET freq=%f counter=%I64d\n", freq, hpetRegisters->counterValue);
|
|
return true;
|
|
}
|
|
|
|
|
|
void hpetShutdown()
|
|
{
|
|
if(!ModuleShouldShutdown(&initState))
|
|
return;
|
|
|
|
UnmapPhysicalMemory((void*)hpetRegisters);
|
|
|
|
acpiShutdown();
|
|
}
|