Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 618 → Rev 619

/shark/trunk/oslib/kl/advtimer.c
58,6 → 58,11
unsigned char save_CMOS_regA;
unsigned char save_CMOS_regB;
 
unsigned char X86_tsc = 0;
unsigned char X86_apic = 0;
unsigned char use_tsc = 0;
unsigned char use_apic = 0;
 
#ifdef CONFIG_MELAN
# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
#else
84,36 → 89,34
outp(0x42,0xFF); /* LSB of count */
outp(0x42,0xFF); /* MSB of count */
barrier();
rdtscll(start);
barrier();
outp(0x43,0x00);
barrier();
rdtscll(start);
barrier();
outp(0x43,0x00);
start_8253 = inp(0x42);
start_8253 |= inp(0x42) << 8;
barrier();
rdtscll(start);
barrier();
barrier();
rdtscll(start);
barrier();
do {
outp(0x43,0x00);
end_8253 = inp(0x42);
end_8253 |= inp(0x42) << 8;
 
} while (end_8253 > COUNTER_END);
 
barrier();
rdtscll(end);
barrier();
barrier();
rdtscll(end);
barrier();
outp(0x43,0x00);
end_8253 = inp(0x42);
end_8253 |= inp(0x42) << 8;
barrier();
rdtscll(end);
barrier();
barrier();
rdtscll(end);
barrier();
 
//Delta TSC
dtsc = end - start;
dtsc = end - start;
 
//Delta PIT
delta_8253 = start_8253 - end_8253;
130,7 → 133,6
clk_per_msec = dtsc * CLOCK_TICK_RATE / delta_8253 / 1000;
message("Calibrated Clk_per_msec = %10d\n",clk_per_msec);
 
}
 
#define CMOS_INIT 0
144,98 → 146,94
 
void calibrate_tsc_IRQ8(void *p)
{
unsigned char set;
 
unsigned char set;
CMOS_READ(0x0C,set);
 
CMOS_READ(0x0C,set);
barrier();
rdtscll(irq8_end);
barrier();
 
barrier();
rdtscll(irq8_end);
barrier();
if (cmos_calibrate_status == CMOS_START) {
cmos_calibrate_status = CMOS_END;
}
 
if (cmos_calibrate_status == CMOS_START) {
cmos_calibrate_status = CMOS_END;
}
if (cmos_calibrate_status == CMOS_BEGIN) {
irq8_start = irq8_end;
cmos_calibrate_status = CMOS_START;
}
 
if (cmos_calibrate_status == CMOS_BEGIN) {
irq8_start = irq8_end;
cmos_calibrate_status = CMOS_START;
}
 
if (cmos_calibrate_status == CMOS_INIT) {
cmos_calibrate_status = CMOS_BEGIN;
}
if (cmos_calibrate_status == CMOS_INIT) {
cmos_calibrate_status = CMOS_BEGIN;
}
}
 
//TSC Calibration using RTC
void ll_calibrate_tsc_cmos(void)
{
unsigned long long dtsc;
 
unsigned long long dtsc;
irq_bind(8, calibrate_tsc_IRQ8, INT_FORCE);
 
irq_bind(8, calibrate_tsc_IRQ8, INT_FORCE);
CMOS_READ(0x0A,save_CMOS_regA);
CMOS_READ(0x0B,save_CMOS_regB);
CMOS_WRITE(0x0A,0x2F); // Set 2 Hz Periodic Interrupt
CMOS_WRITE(0x0B,0x42); // Enable Interrupt
 
CMOS_READ(0x0A,save_CMOS_regA);
CMOS_READ(0x0B,save_CMOS_regB);
CMOS_WRITE(0x0A,0x2F); // Set 2 Hz Periodic Interrupt
CMOS_WRITE(0x0B,0x42); // Enable Interrupt
 
irq_unmask(8);
irq_unmask(8);
sti();
sti();
 
while (cmos_calibrate_status != CMOS_END) {
barrier();
}
while (cmos_calibrate_status != CMOS_END) {
barrier();
}
cli();
cli();
 
dtsc = irq8_end - irq8_start;
dtsc = irq8_end - irq8_start;
 
clk_per_msec = dtsc / 500;
clk_opt_0 = (unsigned int)(dtsc);
clk_opt_1 = (unsigned int)((unsigned long long)(dtsc << 1));
clk_opt_2 = (unsigned int)((unsigned long long)(dtsc << 33) / 1000000000L);
clk_opt_3 = (unsigned int)((unsigned long long)(dtsc << 32) / 1000000000L);
clk_opt_4 = (unsigned int)((unsigned long long)(dtsc << 31) / 1000000000L);
clk_opt_5 = (unsigned int)((unsigned long long)(dtsc << 30) / 1000000000L);
clk_per_msec = dtsc / 500;
clk_opt_0 = (unsigned int)(dtsc);
clk_opt_1 = (unsigned int)((unsigned long long)(dtsc << 1));
clk_opt_2 = (unsigned int)((unsigned long long)(dtsc << 33) / 1000000000L);
clk_opt_3 = (unsigned int)((unsigned long long)(dtsc << 32) / 1000000000L);
clk_opt_4 = (unsigned int)((unsigned long long)(dtsc << 31) / 1000000000L);
clk_opt_5 = (unsigned int)((unsigned long long)(dtsc << 30) / 1000000000L);
 
message("Calibrated CPU Clk/msec = %10u\n",clk_per_msec);
message("Calibrated CPU Clk/msec = %10u\n",clk_per_msec);
 
#ifdef __O1000__
if (clk_per_msec < 1000000) {
message("Timer Optimization CPU < 1 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
#ifdef __O1000__
if (clk_per_msec < 1000000) {
message("Timer Optimization CPU < 1 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
 
#ifdef __O2000__
if (clk_per_msec < 2000000 && clk_per_msec >= 1000000) {
message("Timer Optimization 1 GHz < CPU < 2 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
#ifdef __O2000__
if (clk_per_msec < 2000000 && clk_per_msec >= 1000000) {
message("Timer Optimization 1 GHz < CPU < 2 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
 
#ifdef __O4000__
if (clk_per_msec < 4000000 && clk_per_msec >= 2000000) {
message("Timer Optimization 2 GHz < CPU < 4 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
#ifdef __O4000__
if (clk_per_msec < 4000000 && clk_per_msec >= 2000000) {
message("Timer Optimization 2 GHz < CPU < 4 GHz\n");
} else {
message("Bad Timer Optimization\n");
ll_abort(66);
}
#endif
 
irq_mask(8);
irq_mask(8);
 
CMOS_WRITE(0x0A,save_CMOS_regA);
CMOS_WRITE(0x0B,save_CMOS_regB);
 
CMOS_WRITE(0x0A,save_CMOS_regA);
CMOS_WRITE(0x0B,save_CMOS_regB);
}
 
int apic_get_maxlvt(void)
323,41 → 321,38
unsigned long value;
 
/* Pound the ESR really hard over the head with a big hammer - mbligh */
 
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
 
value = APIC_SPIV_FOCUS_DISABLED | APIC_SPIV_APIC_ENABLED | SPURIOUS_APIC_VECTOR;
apic_write_around(APIC_SPIV, value);
 
value = APIC_DM_EXTINT | APIC_LVT_LEVEL_TRIGGER;
apic_write_around(APIC_LVT0, value);
value = APIC_DM_EXTINT | APIC_LVT_LEVEL_TRIGGER;
apic_write_around(APIC_LVT0, value);
 
value = APIC_DM_NMI;
apic_write_around(APIC_LVT1, value);
value = APIC_DM_NMI;
apic_write_around(APIC_LVT1, value);
 
apic_write(APIC_ESR, 0);
 
apic_write(APIC_ESR, 0);
}
 
void disable_APIC_timer(void)
{
unsigned long v;
unsigned long v;
v = apic_read(APIC_LVTT);
apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
v = apic_read(APIC_LVTT);
apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
}
void enable_APIC_timer(void)
{
unsigned long v;
unsigned long v;
v = apic_read(APIC_LVTT);
apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
v = apic_read(APIC_LVTT);
apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
}
 
#define LOCAL_TIMER_VECTOR 0x39
365,20 → 360,20
/* Set APIC Timer... from Linux kernel */
void setup_APIC_timer()
{
unsigned int lvtt1_value;
lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
apic_write_around(APIC_LVTT, lvtt1_value);
/*
* Divide PICLK by 1
*/
apic_write_around(APIC_TDCR, APIC_TDR_DIV_1);
unsigned int lvtt1_value;
 
apic_write_around(APIC_TMICT, MAX_DWORD);
lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
apic_write_around(APIC_LVTT, lvtt1_value);
 
disable_APIC_timer();
/*
* Divide PICLK by 1
*/
apic_write_around(APIC_TDCR, APIC_TDR_DIV_1);
 
apic_write_around(APIC_TMICT, MAX_DWORD);
 
disable_APIC_timer();
}
 
#define APIC_LIMIT 0xFF000000
386,89 → 381,89
 
void ll_calibrate_apic(void)
{
unsigned int apic_start = 0, apic_end = 0, dapic;
unsigned long long tsc_start = 0, tsc_end = 0, dtsc;
unsigned int tmp_value;
 
unsigned int apic_start = 0, apic_end = 0, dapic;
unsigned long long tsc_start = 0, tsc_end = 0, dtsc;
unsigned int tmp_value;
tmp_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | LOCAL_TIMER_VECTOR;
apic_write_around(APIC_LVTT, tmp_value);
 
tmp_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | LOCAL_TIMER_VECTOR;
apic_write_around(APIC_LVTT, tmp_value);
apic_write_around(APIC_TDCR, APIC_TDR_DIV_1);
 
apic_write_around(APIC_TDCR, APIC_TDR_DIV_1);
apic_write(APIC_TMICT, MAX_DWORD);
 
apic_write(APIC_TMICT, MAX_DWORD);
enable_APIC_timer();
 
enable_APIC_timer();
barrier();
rdtscll(tsc_start);
barrier();
apic_start = apic_read(APIC_TMCCT);
barrier();
 
barrier();
rdtscll(tsc_start);
barrier();
apic_start = apic_read(APIC_TMCCT);
barrier();
while (apic_read(APIC_TMCCT) > APIC_LIMIT) {
barrier();
rdtscll(tsc_end);
}
while (apic_read(APIC_TMCCT) > APIC_LIMIT) {
barrier();
rdtscll(tsc_end);
}
 
barrier();
rdtscll(tsc_end);
barrier();
apic_end = apic_read(APIC_TMCCT);
barrier();
barrier();
rdtscll(tsc_end);
barrier();
apic_end = apic_read(APIC_TMCCT);
barrier();
 
disable_APIC_timer();
disable_APIC_timer();
 
dtsc = tsc_end - tsc_start;
dapic = apic_start - apic_end;
dtsc = tsc_end - tsc_start;
dapic = apic_start - apic_end;
apic_clk_per_msec = (unsigned long long)(clk_per_msec) * (unsigned long long)(dapic) / dtsc;
apic_set_limit = ((apic_clk_per_msec / 100) != 0) ? (apic_clk_per_msec/100) : APIC_SET_LIMIT;
 
apic_clk_per_msec = (unsigned long long)(clk_per_msec) * (unsigned long long)(dapic) / dtsc;
apic_set_limit = ((apic_clk_per_msec / 100) != 0) ? (apic_clk_per_msec/100) : APIC_SET_LIMIT;
message("Calibrated APIC Clk/msec = %10d\n",apic_clk_per_msec);
message("Calibrated APIC Clk/msec = %10d\n",apic_clk_per_msec);
}
 
void ll_init_advtimer()
{
#ifdef __APIC__
unsigned long msr_low_orig, tmp;
#endif
unsigned long msr_low_orig, tmp;
 
#ifdef __TSC__
#ifdef __APIC__
use_apic = X86_apic;
#endif
 
#ifdef __TSC__
use_tsc = X86_tsc;
#endif
 
if (use_tsc) {
#ifdef CALIBRATE_USING_CMOS
ll_calibrate_tsc_cmos();
#else
ll_calibrate_tsc();
#endif
#ifdef CALIBRATE_USING_CMOS
ll_calibrate_tsc_cmos();
#else
ll_calibrate_tsc();
#endif
 
rdtscll(init_tsc); // Read start TSC
init_nsec = 0;
rdtscll(init_tsc); // Read start TSC
init_nsec = 0;
 
#ifdef __APIC__
if (use_apic) {
rdmsr(APIC_BASE_MSR, msr_low_orig, tmp);
wrmsr(APIC_BASE_MSR, msr_low_orig|(1<<11), 0);
 
rdmsr(APIC_BASE_MSR, msr_low_orig, tmp);
wrmsr(APIC_BASE_MSR, msr_low_orig|(1<<11), 0);
clear_local_APIC();
 
clear_local_APIC();
ll_calibrate_apic();
 
ll_calibrate_apic();
 
setup_local_APIC();
setup_local_APIC();
setup_APIC_timer();
 
#endif
 
#endif
 
setup_APIC_timer();
}
}
}
 
void ll_restore_adv()
{
/* Disable APIC */
#ifdef __APIC__
if (use_apic) {
unsigned int msr_low_orig, tmp;
 
cli();
479,7 → 474,5
wrmsr(APIC_BASE_MSR, msr_low_orig&~(1<<11), 0);
 
sti();
 
#endif
}
}