File: pmt.cpp

package info (click to toggle)
0ad 0.0.23.1-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 78,412 kB
  • sloc: cpp: 245,162; ansic: 200,249; javascript: 19,244; python: 13,754; sh: 6,104; perl: 4,620; makefile: 977; xml: 810; java: 533; ruby: 229; erlang: 46; pascal: 30; sql: 21; tcl: 4
file content (115 lines) | stat: -rw-r--r-- 3,199 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* Copyright (C) 2010 Wildfire Games.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Timer implementation using ACPI PM timer
 */

#include "precompiled.h"
#include "lib/sysdep/os/win/whrt/pmt.h"

#include "lib/sysdep/os/win/whrt/counter.h"

#include "lib/sysdep/os/win/win.h"
#include "lib/sysdep/acpi.h"
#include "lib/sysdep/os/win/mahaf.h"
#include "lib/bits.h"

static const u32 TMR_VAL_EXT = Bit<u32>(8);	// FADT flags

//-----------------------------------------------------------------------------


class CounterPMT : public ICounter
{
public:
	CounterPMT()
		: m_portAddress(0xFFFF)
	{
	}

	virtual const char* Name() const
	{
		return "PMT";
	}

	Status Activate()
	{
		// mahaf is needed for port I/O.
		RETURN_STATUS_IF_ERR(mahaf_Init());	// (fails without Administrator privileges)
		// (note: it's called FADT, but the signature is "FACP")
		const FADT* fadt = (const FADT*)acpi_GetTable("FACP");
		if(!fadt)
			return ERR::NOT_SUPPORTED;	// NOWARN (ACPI tables might not be available)
		m_portAddress = u16_from_larger(fadt->pmTimerPortAddress);

		return INFO::OK;
	}

	void Shutdown()
	{
	}

	bool IsSafe() const
	{
		// the PMT has one issue: "Performance counter value may unexpectedly
		// leap forward" (Q274323). This happens on some buggy Pentium-era
		// systems under heavy PCI bus load. We are clever and observe that
		// the TSC implementation would be used on such systems (because it
		// has higher precedence and is safe on P5 CPUs), so the PMT is fine
		// in general.
		return true;
	}

	u64 Counter() const
	{
		return mahaf_ReadPort32(m_portAddress);
	}

	size_t CounterBits() const
	{
		// (see previous acpi_GetTable call)
		const FADT* fadt = (const FADT*)acpi_GetTable("FACP");
		ENSURE(fadt);	// Activate made sure FADT is available
		const size_t counterBits = (fadt->flags & TMR_VAL_EXT)? 32 : 24;
		return counterBits;
	}

	double NominalFrequency() const
	{
		return (double)PMT_FREQ;
	}

	double Resolution() const
	{
		return 1.0 / PMT_FREQ;
	}

private:
	u16 m_portAddress;
};

ICounter* CreateCounterPMT(void* address, size_t size)
{
	ENSURE(sizeof(CounterPMT) <= size);
	return new(address) CounterPMT();
}