ACPI.Timer.Mod 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. (* Runtime support for high precision timer *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE Timer;
  4. IMPORT ACPI, SYSTEM;
  5. TYPE Counter* = LONGINT;
  6. VAR frequency: Counter;
  7. VAR counter {UNTRACED}: POINTER {UNSAFE} TO RECORD value: HUGEINT END;
  8. PROCEDURE - GetInstructionTimer(): HUGEINT;
  9. CODE
  10. RDTSC
  11. END GetInstructionTimer;
  12. PROCEDURE GetCounter- (): Counter;
  13. BEGIN {UNCOOPERATIVE, UNCHECKED}
  14. IF counter = NIL THEN RETURN SHORT(GetInstructionTimer() DIV (1024*1024)); (* return millions of instructions *) END;
  15. ASSERT (counter # NIL); RETURN SHORT (counter.value);
  16. END GetCounter;
  17. PROCEDURE GetFrequency- (): Counter;
  18. BEGIN {UNCOOPERATIVE, UNCHECKED}
  19. IF counter = NIL THEN RETURN 1024 (* giga instructions as a rough guess *) END;
  20. RETURN frequency;
  21. END GetFrequency;
  22. PROCEDURE Initialize-;
  23. CONST OverallEnable = 0;
  24. VAR hpet {UNTRACED}: POINTER {UNSAFE} TO ACPI.HPET; address: ADDRESS;
  25. VAR period {UNTRACED}: POINTER {UNSAFE} TO RECORD value: LONGINT END; configuration {UNTRACED}: POINTER {UNSAFE} TO RECORD value: SET END;
  26. BEGIN {UNCOOPERATIVE, UNCHECKED}
  27. ACPI.Initialize;
  28. IF ACPI.rdsp = NIL THEN RETURN END;
  29. hpet := ACPI.GetTable (ACPI.HPETSignature);
  30. IF hpet = NIL THEN RETURN END;
  31. address := ACPI.Convert (hpet.baseAddress.addressLow);
  32. period := address + SIZE OF CHAR * 004H;
  33. counter := address + SIZE OF CHAR * 0F0H;
  34. configuration := address + SIZE OF CHAR * 010H;
  35. frequency := SHORT (1000000000000000 DIV period.value);
  36. INCL (configuration.value, OverallEnable);
  37. END Initialize;
  38. END Timer.