1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- (* Runtime support for high precision timer *)
- (* Copyright (C) Florian Negele *)
- MODULE Timer;
- IMPORT ACPI, SYSTEM;
- TYPE Counter* = LONGINT;
- VAR frequency: Counter;
- VAR counter {UNTRACED}: POINTER {UNSAFE} TO RECORD value: HUGEINT END;
- PROCEDURE - GetInstructionTimer(): HUGEINT;
- CODE
- RDTSC
- END GetInstructionTimer;
- PROCEDURE GetCounter- (): Counter;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- IF counter = NIL THEN RETURN SHORT(GetInstructionTimer() DIV (1024*1024)); (* return millions of instructions *) END;
- ASSERT (counter # NIL); RETURN SHORT (counter.value);
- END GetCounter;
- PROCEDURE GetFrequency- (): Counter;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- IF counter = NIL THEN RETURN 1024 (* giga instructions as a rough guess *) END;
- RETURN frequency;
- END GetFrequency;
- PROCEDURE Initialize-;
- CONST OverallEnable = 0;
- VAR hpet {UNTRACED}: POINTER {UNSAFE} TO ACPI.HPET; address: ADDRESS;
- VAR period {UNTRACED}: POINTER {UNSAFE} TO RECORD value: LONGINT END; configuration {UNTRACED}: POINTER {UNSAFE} TO RECORD value: SET END;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- ACPI.Initialize;
- IF ACPI.rdsp = NIL THEN RETURN END;
- hpet := ACPI.GetTable (ACPI.HPETSignature);
- IF hpet = NIL THEN RETURN END;
- address := ACPI.Convert (hpet.baseAddress.addressLow);
- period := address + SIZE OF CHAR * 004H;
- counter := address + SIZE OF CHAR * 0F0H;
- configuration := address + SIZE OF CHAR * 010H;
- frequency := SHORT (1000000000000000 DIV period.value);
- INCL (configuration.value, OverallEnable);
- END Initialize;
- END Timer.
|