* Put the calibration loop into a static inline function and replace the three
copies of it with a call to that. * Make the variable names more readable and spacing cleanup. No functional change intended. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41670 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d620303480
commit
34d3f13c64
@ -173,16 +173,46 @@ private:
|
||||
};
|
||||
|
||||
|
||||
static inline void
|
||||
calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta,
|
||||
double& conversionFactor, uint16& expired)
|
||||
{
|
||||
uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
|
||||
uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
|
||||
|
||||
// Wait for the PIT to arrive at our starting position (high byte == 0xff)
|
||||
uint8 startLow;
|
||||
uint8 startHigh;
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
startLow = in8(channelPort);
|
||||
startHigh = in8(channelPort);
|
||||
} while (startHigh != 255);
|
||||
|
||||
// Read in the first TSC value
|
||||
uint64 startTSC = rdtsc();
|
||||
|
||||
// Wait for the PIT to count down to our desired value
|
||||
uint8 endLow;
|
||||
uint8 endHigh;
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
endLow = in8(channelPort);
|
||||
endHigh = in8(channelPort);
|
||||
} while (endHigh > desiredHighByte);
|
||||
|
||||
// And read the second TSC value
|
||||
uint64 endTSC = rdtsc();
|
||||
|
||||
tscDelta = endTSC - startTSC;
|
||||
expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow);
|
||||
conversionFactor = (double)tscDelta / (double)expired;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_cpu_conversion_factor()
|
||||
{
|
||||
uint32 s_low, s_high;
|
||||
uint32 low, high;
|
||||
uint32 expired;
|
||||
uint64 t1, t2;
|
||||
uint64 p1, p2, p3;
|
||||
double r1, r2, r3;
|
||||
|
||||
uint8 channel = 0;
|
||||
uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
|
||||
uint8 control;
|
||||
@ -204,90 +234,54 @@ calculate_cpu_conversion_factor()
|
||||
out8(0xff, channelPort);
|
||||
out8(0xff, channelPort);
|
||||
|
||||
/* quick sample */
|
||||
uint64 tscDeltaQuick, tscDeltaSlower, tscDeltaSlow;
|
||||
double conversionFactorQuick, conversionFactorSlower, conversionFactorSlow;
|
||||
uint16 expired;
|
||||
|
||||
quick_sample:
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
s_low = in8(channelPort);
|
||||
s_high = in8(channelPort);
|
||||
} while (s_high != 255);
|
||||
t1 = rdtsc();
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
low = in8(channelPort);
|
||||
high = in8(channelPort);
|
||||
} while (high > 224);
|
||||
t2 = rdtsc();
|
||||
calibration_loop(224, channel, tscDeltaQuick, conversionFactorQuick,
|
||||
expired);
|
||||
|
||||
p1 = t2-t1;
|
||||
r1 = (double)(p1) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
||||
slower_sample:
|
||||
calibration_loop(192, channel, tscDeltaSlower, conversionFactorSlower,
|
||||
expired);
|
||||
|
||||
/* not so quick sample */
|
||||
not_so_quick_sample:
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
s_low = in8(channelPort);
|
||||
s_high = in8(channelPort);
|
||||
} while (s_high != 255);
|
||||
t1 = rdtsc();
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
low = in8(channelPort);
|
||||
high = in8(channelPort);
|
||||
} while (high > 192);
|
||||
t2 = rdtsc();
|
||||
p2 = t2-t1;
|
||||
r2 = (double)(p2) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
||||
if ((r1/r2) > 1.01) {
|
||||
//dprintf("Tuning loop(1)\n");
|
||||
goto quick_sample;
|
||||
}
|
||||
if ((r1/r2) < 0.99) {
|
||||
//dprintf("Tuning loop(1)\n");
|
||||
double deviation = conversionFactorQuick / conversionFactorSlower;
|
||||
if (deviation < 0.99 || deviation > 1.01) {
|
||||
// We might have been hit by a SMI or were otherwise stalled
|
||||
goto quick_sample;
|
||||
}
|
||||
|
||||
/* slow sample */
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
s_low = in8(channelPort);
|
||||
s_high = in8(channelPort);
|
||||
} while (s_high != 255);
|
||||
t1 = rdtsc();
|
||||
do {
|
||||
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
|
||||
low = in8(channelPort);
|
||||
high = in8(channelPort);
|
||||
} while (high > 128);
|
||||
t2 = rdtsc();
|
||||
// Slow sample
|
||||
calibration_loop(128, channel, tscDeltaSlow, conversionFactorSlow,
|
||||
expired);
|
||||
|
||||
p3 = t2-t1;
|
||||
r3 = (double)(p3) / (double)(((s_high << 8) | s_low) - ((high << 8) | low));
|
||||
if ((r2/r3) > 1.01) {
|
||||
TRACE(("Tuning loop(2)\n"));
|
||||
goto not_so_quick_sample;
|
||||
}
|
||||
if ((r2/r3) < 0.99) {
|
||||
TRACE(("Tuning loop(2)\n"));
|
||||
goto not_so_quick_sample;
|
||||
deviation = conversionFactorSlower / conversionFactorSlow;
|
||||
if (deviation < 0.99 || deviation > 1.01) {
|
||||
// We might have been hit by a SMI or were otherwise stalled
|
||||
goto slower_sample;
|
||||
}
|
||||
|
||||
expired = ((s_high << 8) | s_low) - ((high << 8) | low);
|
||||
p3 *= TIMER_CLKNUM_HZ;
|
||||
// Scale the TSC delta to timer units
|
||||
tscDeltaSlow *= TIMER_CLKNUM_HZ;
|
||||
|
||||
uint64 clockSpeed = tscDeltaSlow / expired;
|
||||
gTimeConversionFactor = ((uint128(expired) * uint32(1000000)) << 32)
|
||||
/ uint128(p3);
|
||||
/ uint128(tscDeltaSlow);
|
||||
|
||||
#ifdef TRACE_CPU
|
||||
if (p3 / expired / 1000000000LL)
|
||||
dprintf("CPU at %Ld.%03Ld GHz\n", p3/expired/1000000000LL, ((p3/expired)%1000000000LL)/1000000LL);
|
||||
else
|
||||
dprintf("CPU at %Ld.%03Ld MHz\n", p3/expired/1000000LL, ((p3/expired)%1000000LL)/1000LL);
|
||||
if (clockSpeed > 1000000000LL) {
|
||||
dprintf("CPU at %Ld.%03Ld GHz\n", clockSpeed / 1000000000LL,
|
||||
(clockSpeed % 1000000000LL) / 1000000LL);
|
||||
} else {
|
||||
dprintf("CPU at %Ld.%03Ld MHz\n", clockSpeed / 1000000LL,
|
||||
(clockSpeed % 1000000LL) / 1000LL);
|
||||
}
|
||||
#endif
|
||||
|
||||
gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
|
||||
gKernelArgs.arch_args.cpu_clock_speed = p3 / expired;
|
||||
//dprintf("factors: %lu %llu\n", gTimeConversionFactor, p3 / expired);
|
||||
gKernelArgs.arch_args.cpu_clock_speed = clockSpeed;
|
||||
//dprintf("factors: %lu %llu\n", gTimeConversionFactor, clockSpeed);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user