* Use macros to make the PIT programming more readable. Yes, I know that the PIT

timer code has such definitions too, but they're not quite as verbose. Will
  eventually make the latter use these too.
* Prepare for possibly using other PIT channels for the calibration. Right now
  everything's the same still.
* Add disabled print of the resulting factors.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41669 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-05-23 10:33:10 +00:00
parent 10919035c8
commit d620303480
1 changed files with 72 additions and 22 deletions

View File

@ -34,7 +34,39 @@ extern "C" uint64 rdtsc();
uint32 gTimeConversionFactor;
#define TIMER_CLKNUM_HZ (14318180/12)
// PIT definitions
#define TIMER_CLKNUM_HZ (14318180 / 12)
// PIT IO Ports
#define PIT_CHANNEL_PORT_BASE 0x40
#define PIT_CONTROL 0x43
// Channel selection
#define PIT_SELECT_CHANNEL_SHIFT 6
// Access mode
#define PIT_ACCESS_LATCH_COUNTER (0 << 4)
#define PIT_ACCESS_LOW_BYTE_ONLY (1 << 4)
#define PIT_ACCESS_HIGH_BYTE_ONLY (2 << 4)
#define PIT_ACCESS_LOW_THEN_HIGH_BYTE (3 << 4)
// Operating modes
#define PIT_MODE_INTERRUPT_ON_0 (0 << 1)
#define PIT_MODE_HARDWARE_COUNTDOWN (1 << 1)
#define PIT_MODE_RATE_GENERATOR (2 << 1)
#define PIT_MODE_SQUARE_WAVE_GENERATOR (3 << 1)
#define PIT_MODE_SOFTWARE_STROBE (4 << 1)
#define PIT_MODE_HARDWARE_STROBE (5 << 1)
// BCD/Binary mode
#define PIT_BINARY_MODE 0
#define PIT_BCD_MODE 1
// Channel 2 control (speaker)
#define PIT_CHANNEL_2_CONTROL 0x61
#define PIT_CHANNEL_2_GATE_HIGH 0x01
#define PIT_CHANNEL_2_SPEAKER_OFF_MASK ~0x02
#define CPUID_EFLAGS (1UL << 21)
#define RDTSC_FEATURE (1UL << 4)
@ -151,22 +183,39 @@ calculate_cpu_conversion_factor()
uint64 p1, p2, p3;
double r1, r2, r3;
out8(0x34, 0x43); /* program the timer to count down mode */
out8(0xff, 0x40); /* low and then high */
out8(0xff, 0x40);
uint8 channel = 0;
uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
uint8 control;
// When using channel 2, enable the input and disable the speaker.
if (channel == 2) {
control = in8(PIT_CHANNEL_2_CONTROL);
control &= PIT_CHANNEL_2_SPEAKER_OFF_MASK;
control |= PIT_CHANNEL_2_GATE_HIGH;
out8(control, PIT_CHANNEL_2_CONTROL);
}
uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
control = select | PIT_ACCESS_LOW_THEN_HIGH_BYTE | PIT_MODE_RATE_GENERATOR
| PIT_BINARY_MODE;
out8(control, PIT_CONTROL);
// Fill in count of 0xffff, low then high byte
out8(0xff, channelPort);
out8(0xff, channelPort);
/* quick sample */
quick_sample:
do {
out8(0x00, 0x43); /* latch counter value */
s_low = in8(0x40);
s_high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
s_low = in8(channelPort);
s_high = in8(channelPort);
} while (s_high != 255);
t1 = rdtsc();
do {
out8(0x00, 0x43); /* latch counter value */
low = in8(0x40);
high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
low = in8(channelPort);
high = in8(channelPort);
} while (high > 224);
t2 = rdtsc();
@ -176,15 +225,15 @@ quick_sample:
/* not so quick sample */
not_so_quick_sample:
do {
out8(0x00, 0x43); /* latch counter value */
s_low = in8(0x40);
s_high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
s_low = in8(channelPort);
s_high = in8(channelPort);
} while (s_high != 255);
t1 = rdtsc();
do {
out8(0x00, 0x43); /* latch counter value */
low = in8(0x40);
high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
low = in8(channelPort);
high = in8(channelPort);
} while (high > 192);
t2 = rdtsc();
p2 = t2-t1;
@ -200,15 +249,15 @@ not_so_quick_sample:
/* slow sample */
do {
out8(0x00, 0x43); /* latch counter value */
s_low = in8(0x40);
s_high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
s_low = in8(channelPort);
s_high = in8(channelPort);
} while (s_high != 255);
t1 = rdtsc();
do {
out8(0x00, 0x43); /* latch counter value */
low = in8(0x40);
high = in8(0x40);
out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
low = in8(channelPort);
high = in8(channelPort);
} while (high > 128);
t2 = rdtsc();
@ -238,6 +287,7 @@ not_so_quick_sample:
gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
gKernelArgs.arch_args.cpu_clock_speed = p3 / expired;
//dprintf("factors: %lu %llu\n", gTimeConversionFactor, p3 / expired);
}