internal void CalibrateTimerWithHpet(Hpet hpet, ulong tsc_delay) { /* set up the hpet */ ulong init_hpet = 0x0; hpet.SetMainCounter(init_hpet); init_hpet = hpet.ReadMainCounter(); /* set up the lapic timer as masked, one shot, divisor of 1 */ uint lapic_val = 0xffffffff; //uint lapic_div = 11; /* bits 0, 1 and 3 set the divisor */ uint lapic_reg = 0x00010000; /* masked, one-shot, vector 0 */ WriteConfDword(LVT_timer_offset, lapic_reg); //WriteConfDword(Divide_Conf_offset, lapic_div); WriteConfDword(Initial_Count_offset, lapic_val); /* start the hpet */ hpet.EnableMainCounter(); /* perform a delay using the tsc */ ulong init_tsc = libsupcs.x86_64.Cpu.Tsc; ulong cur_tsc = init_tsc; while (cur_tsc < (init_tsc + tsc_delay)) { cur_tsc = libsupcs.x86_64.Cpu.Tsc; } /* get the final values of the timers */ ulong lapic_final_val = ReadConfDword(Current_Count_offset); hpet.DisableMainCounter(); ulong hpet_final_val = hpet.ReadMainCounter(); ulong delta_hpet = hpet_final_val - init_hpet; ulong delta_lapic = lapic_val - lapic_final_val; /* At this point: * * actual time delay = delta_hpet / hpet_frequency _or_ delta_hpet * hpet_cycle_length * bus_cycles = delta_lapic * lapic_divisor * * bus_frequency = bus_cycles / actual time delay */ double actual_time_delay = Convert.ToDouble((long)delta_hpet) * hpet.MainCounterCycleLength; ulong bus_cycles = delta_lapic * LApicTimerDivisor; double bus_frequency = Convert.ToDouble((long)bus_cycles) / actual_time_delay; double bus_frequency_mhz = bus_frequency * 0.000001; Program.arch.DebugOutput.Write("Bus frequency " + bus_frequency_mhz.ToString() + " Mhz\n"); Formatter.Write(" delta_tsc: ", Program.arch.DebugOutput); Formatter.Write(cur_tsc - init_tsc, "X", Program.arch.DebugOutput); Formatter.Write(" init_hpet: ", Program.arch.DebugOutput); Formatter.Write(init_hpet, "X", Program.arch.DebugOutput); Formatter.Write(" final_hpet: ", Program.arch.DebugOutput); Formatter.Write(hpet_final_val, "X", Program.arch.DebugOutput); Formatter.Write(" delta_hpet: ", Program.arch.DebugOutput); Formatter.Write(delta_hpet, "d", Program.arch.DebugOutput); Formatter.Write(" delta_lapic: ", Program.arch.DebugOutput); Formatter.Write(delta_lapic, "d", Program.arch.DebugOutput); Formatter.WriteLine(Program.arch.DebugOutput); lapic_base_freq = bus_frequency; calibrated = true; }
internal void CalibrateTimerWithHpet(Hpet hpet) { CalibrateTimerWithHpet(hpet, 0x1000000); }