1#include <asm.h>
2#include <pit.h>
3#include <stdint.h>
4
5#define PIT_DEFAULT_MODE 0x34
6#define PIT_DEFAULT_COUNT 0x4AF2
7
8static uint16_t pit_read_count() {
9 outb(port: 0x43, value: 0x00);
10
11 uint8_t low = inb(port: 0x40);
12 uint8_t high = inb(port: 0x40);
13
14 return ((uint16_t) high << 8) | low;
15}
16
17static void pit_wait_until_zero() {
18 while (true) {
19 uint16_t count = pit_read_count();
20 if (count <= 1)
21 break;
22 cpu_relax();
23 }
24}
25
26uint64_t measure_tsc_freq_pit(void) {
27 outb(port: 0x43, value: 0x30);
28
29 uint16_t pit_count = 0xFFFF;
30 outb(port: 0x40, value: (uint8_t) (pit_count & 0xFF));
31 outb(port: 0x40, value: (uint8_t) (pit_count >> 8));
32
33 uint64_t start_tsc = rdtsc();
34
35 pit_wait_until_zero();
36
37 uint64_t end_tsc = rdtsc();
38
39 outb(port: 0x43, PIT_DEFAULT_MODE);
40 outb(port: 0x40, value: (uint8_t) (PIT_DEFAULT_COUNT & 0xFF));
41 outb(port: 0x40, value: (uint8_t) (PIT_DEFAULT_COUNT >> 8));
42
43 uint64_t tsc_frequency = (end_tsc - start_tsc) * PIT_FREQUENCY / pit_count;
44
45 return tsc_frequency;
46}
47