0ad/source/lib/sysdep/hpet.cpp
janwas cded0936c5 # housekeeping
. 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.
2007-05-21 23:24:56 +00:00

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();
}