#include <cpu.h>

.globl TimerCalibrate
.func TimerCalibrate
TimerCalibrate:
    movq    lapic, %rsi

// configure LAPIC timer
    xorl    %eax, %eax
    movl    %eax, LAPIC_TICR * 16(%rsi)
    movl    $33, %eax
    movl    %eax, LAPIC_TIMER * 16(%rsi)

    movl    $3, %eax
    movl    %eax, LAPIC_TDCR * 16(%rsi)

// configure PIT channel 2 for 10 ms delay in one-shot mode
    inb     $0x61, %al
    andb    $0xFD, %al
    orb     $1, %al
    outb    %al, $0x61

    movb    $0xB0, %al
    outb    %al, $0x43
    movw    $11931, %ax // 100 Hz
    outb    %al, $0x42
    inb     $0x60, %al
    movb    %ah, %al
    outb    %al, $0x42

// and enable APIC timer
    xorl    %eax, %eax
    decl    %eax
    movl    %eax, LAPIC_TICR * 16(%rsi)
1:  inb     $0x61, %al
    testb   $0x20, %al
    jz      1b

// 10 ms reached, now take number of LAPIC timer ticks and disable it
    movl    LAPIC_TCCR * 16(%rsi), %ecx

    movl    $1 << 16, %eax
    movl    %eax, LAPIC_TIMER * 16(%rsi)

// invert and multiply by 1600 to get FSB frequency
    xorq    %rax, %rax
    decl    %eax
    subl    %ecx, %eax
    decl    %eax
    movl    $1600, %ecx
    mull    %ecx

    retq
.endfunc
.size TimerCalibrate, . - TimerCalibrate
