/shark/trunk/oslib/kl/time.c |
---|
49,18 → 49,17 |
extern BYTE frc; |
extern int activeEvent; |
extern unsigned char use_tsc; |
FILE(Time); |
TIME ll_gettime(int mode, struct timespec *tsres) |
{ |
#ifndef __TSC__ |
DWORD res, tc; |
BYTE isr; |
struct timespec tmp; |
if (!use_tsc) { |
#if 1 |
if (activeEvent) { |
if (tsres != NULL) { |
138,68 → 137,22 |
} |
return 0; |
} else { |
#else |
#if 1 |
if (activeEvent) { |
if (tsres != NULL) { |
ll_read_timespec(tsres); |
} else { |
struct timespec tmp; |
ll_read_timespec(&tmp); |
return TIMESPEC2USEC(&tmp); |
} |
return TIMESPEC2USEC(tsres); |
} |
#endif |
if (mode == TIME_PTICK) { |
if (timermode != LL_PERIODIC) { |
return 0; |
} |
if(tsres != NULL) { |
ll_read_timespec(tsres); |
} else { |
struct timespec tmp; |
ll_read_timespec(&tmp); |
return TIMESPEC2USEC(&tmp); |
} |
return TIMESPEC2USEC(tsres); |
} |
if (mode == TIME_NEW) { |
if (tsres != NULL) { |
ll_read_timespec(tsres); |
return TIMESPEC2USEC(tsres); |
} else { |
struct timespec tmp; |
ll_read_timespec(&tmp); |
return TIMESPEC2USEC(&tmp); |
} |
} |
if (mode == TIME_EXACT) { |
if (timermode == LL_PERIODIC) { |
if (tsres != NULL) { |
ll_read_timespec(tsres); |
} else { |
struct timespec tmp; |
ll_read_timespec(&tmp); |
return TIMESPEC2USEC(&tmp); |
} |
return TIMESPEC2USEC(tsres); |
} else { |
return 0; |
} |
} |
return 0; |
#endif |
} |
} |
/shark/trunk/oslib/kl/event.c |
---|
36,6 → 36,7 |
#include <ll/i386/pit.h> |
#include <ll/i386/apic.h> |
#include <ll/i386/advtimer.h> |
#include <ll/i386/64bit.h> |
#include <ll/sys/ll/ll-data.h> |
#include <ll/sys/ll/ll-instr.h> |
72,9 → 73,7 |
extern void (*evt_prol) (void); |
extern void (*evt_epil) (void); |
extern unsigned char use_tsc; |
extern unsigned char use_apic; |
extern signed long long apic_clk_per_msec; |
extern unsigned int apic_clk_per_msec; |
void event_setlasthandler(void *p) |
{ |
167,13 → 166,15 |
void periodic_wake_up(void) |
{ /* CHANGE the NAME, please... */ |
struct event *p, *pp; |
#ifndef __TSC__ |
WORD tmp; |
#endif |
if(!use_tsc) { |
#ifndef __TSC__ |
tmp = pit_read(frc); |
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter); |
lastTime = tmp; |
} |
#endif |
activeInt++; |
if (activeInt == 1 && evt_prol != NULL) { |
180,11 → 181,11 |
evt_prol(); |
} |
if (!use_tsc) { |
#ifndef __TSC__ |
ADDNANO2TIMESPEC(nts, &actTime); |
} else { |
#else |
ll_read_timespec(&actTime); |
} |
#endif |
for (p = firstevent; p != NULL; p = pp) { |
/* |
217,25 → 218,30 |
int i; |
BYTE mask; |
TIME t; |
#ifdef __APIC__ |
DWORD apic_clk; |
#endif |
if (use_tsc) ll_init_advtimer(); |
#ifdef __TSC__ |
ll_init_advtimer(); |
#endif |
if (!use_apic) |
#ifndef __APIC__ |
IDT_place(0x40,ll_timer); |
else |
#else |
IDT_place(0x39,ll_apic_timer); |
#endif |
if (l->mode != LL_PERIODIC) { |
message("One-shot mode\n"); |
t = 0; |
if (!use_apic) { |
#ifndef __APIC__ |
/* Mode: Binary/Mode 4/16 bit Time_const/Counter 0 */ |
pit_init(0, TMR_MD4, 0xFFFF); /* Timer 0, Mode 4, constant 0xFFFF */ |
} else { |
#else |
set_APIC_timer(0xFFFFFFFF); |
enable_APIC_timer(); |
} |
#endif |
} else { |
t = l->tick; |
248,9 → 254,9 |
/* If T-C == 0 -> T-C = 65536 (Max available) */ |
ticksize = t; |
if (!use_apic) { |
#ifndef __APIC__ |
t = (signed long long)(t) * 1193182 / 1000000; |
mul32div32to32(t,1197,1000,t); |
/* Only for security! This should cause timer overrun */ |
/* While 0 would set maximum period on timer */ |
260,17 → 266,17 |
/* Mode: Binary/Mode 2/16 bit Time_const/Counter 0 */ |
pit_init(0, TMR_MD2, t); /* Timer 0, Mode 2, Time constant t */ |
} else { |
#else |
apic_clk = (signed long long)(t) * apic_clk_per_msec / 1000; |
mul32div32to32(t,apic_clk_per_msec,1000,apic_clk); |
set_APIC_timer(apic_clk); |
enable_APIC_timer(); |
#endif |
} |
} |
timermode = l->mode; |
if (!use_apic) { |
#ifndef __APIC__ |
if (ll_arch.x86.cpu > 4) { |
/* Timer1: mode 0, time const 0... */ |
pit_init(1, TMR_MD0, 0); |
280,7 → 286,7 |
pit_init(2, TMR_MD0, 0); |
outp(0x61, 3); |
} |
} |
#endif |
mask = ll_in(0x21); |
mask &= 0xFE; /* 0xFE = ~0x01 */ |
316,6 → 322,8 |
} |
/* Last but not least... */ |
if (!use_apic) irq_unmask(0); |
#ifndef __APIC__ |
irq_unmask(0); |
#endif |
} |
/shark/trunk/oslib/kl/event1.c |
---|
34,6 → 34,7 |
#include <ll/i386/apic.h> |
#include <ll/i386/advtimer.h> |
#include <ll/i386/error.h> |
#include <ll/i386/64bit.h> |
#include <ll/sys/ll/ll-data.h> |
#include <ll/sys/ll/ll-func.h> |
57,12 → 58,8 |
extern void (*evt_prol) (void); |
extern void (*evt_epil) (void); |
extern unsigned char use_tsc; |
extern unsigned char use_apic; |
extern unsigned long long apic_clk_per_msec; |
extern unsigned int apic_clk_per_msec; |
#define barrier() __asm__ __volatile__("" ::: "memory"); |
/* Switched to timespec */ |
int oneshot_event_post(struct timespec time, void (*handler) (void *p), |
void *par) |
105,7 → 102,11 |
} else { |
firstevent = p; |
if (!activeEvent) { |
#ifndef __TSC__ |
ll_gettime(TIME_NEW, &now); |
#else |
ll_read_timespec(&now); |
#endif |
if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) { |
NULL_TIMESPEC(&tmp); |
} else { |
112,15 → 113,15 |
SUBTIMESPEC(&(firstevent->time), &now, &tmp); |
} |
tnext = TIMESPEC2USEC(&tmp); |
if (!use_apic) { |
tnext = (signed long long)(tnext) * 1193182 / 1000000; |
#ifndef __APIC__ |
mul32div32to32(tnext,1197,1000,tnext); |
pit_setconstant(0, tnext); |
} else { |
tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000; |
#else |
mul32div32to32(tnext,apic_clk_per_msec,1000,tnext); |
set_APIC_timer(tnext); |
#endif |
} |
} |
} |
p->next = p1; |
return p->index; |
132,10 → 133,12 |
{ /* CHANGE the NAME, please... */ |
struct event *p = NULL, *pp; |
struct timespec now, ttmp; |
#ifndef __TSC__ |
WORD tmp; |
#endif |
DWORD tnext; |
if (!use_tsc) { |
#ifndef __TSC__ |
tmp = pit_read(frc); |
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter); |
143,11 → 146,11 |
PITSPEC2TIMESPEC(&globalCounter, &now); |
} else { |
#else |
ll_read_timespec(&now); |
} |
#endif |
if (firstevent != NULL) { |
activeEvent = 1; |
176,10 → 179,8 |
activeInt--; |
} |
barrier(); |
#ifndef __TSC__ |
if (!use_tsc) { |
tmp = pit_read(frc); |
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter); |
lastTime = tmp; |
186,11 → 187,11 |
PITSPEC2TIMESPEC(&globalCounter, &now); |
} else { |
#else |
ll_read_timespec(&now); |
} |
#endif |
if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) { |
200,21 → 201,21 |
} |
/* SUBTIMESPEC(&(firstevent->time), &now, &ttmp); */ |
tnext = TIMESPEC2USEC(&ttmp); |
if (!use_apic) { |
tnext = (signed long long)(tnext) * 1193182 / 1000000; |
#ifndef __APIC__ |
mul32div32to32(tnext,1197,1000,tnext); |
pit_setconstant(0, tnext); |
} else { |
tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000; |
#else |
mul32div32to32(tnext,apic_clk_per_msec,1000,tnext); |
set_APIC_timer(tnext); |
} |
#endif |
activeEvent = 0; |
} else { |
if (!use_apic) { |
#ifndef __APIC__ |
pit_setconstant(0, 0xFFFF); |
} else { |
#else |
set_APIC_timer(0xFFFFFFFF); |
#endif |
} |
} |
} |
247,14 → 248,18 |
if (!activeEvent) { |
if (firstevent == NULL) { |
if (!use_apic) { |
#ifndef __APIC__ |
pit_setconstant(0, 0xFFFF); |
} else { |
#else |
set_APIC_timer(0xFFFFFFFF); |
} |
#endif |
} else { |
if (firstdeleted) { |
#ifndef __TSC__ |
ll_gettime(TIME_NEW, &now); |
#else |
ll_read_timespec(&now); |
#endif |
if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) { |
NULL_TIMESPEC(&tmp); |
} else { |
262,15 → 267,15 |
} |
/*SUBTIMESPEC(&now, &(firstevent->time), &tmp); */ |
tnext = TIMESPEC2USEC(&tmp); |
if (!use_apic) { |
tnext = (signed long long)(tnext) * 1193182 / 1000000; |
#ifndef __APIC__ |
mul32div32to32(tnext,1197,1000,tnext); |
pit_setconstant(0, tnext); |
} else { |
tnext = (signed long long)(tnext) * apic_clk_per_msec / 1000; |
#else |
mul32div32to32(tnext,apic_clk_per_msec,1000,tnext); |
set_APIC_timer(tnext); |
#endif |
} |
} |
} |
} |
return 1; |
} |
/shark/trunk/oslib/kl/timeint.s |
---|
58,14 → 58,16 |
pushw %fs |
pushw %gs |
cli |
/* Send ACK to APIC */ |
movl $0xFEE000B0,%ebx |
movl $0,(%ebx) |
movw $(X_FLATDATA_SEL),%ax |
movw %ax,%ds |
movw %ax,%es |
/* Send EOI to APIC */ |
movl $0xFEE000B0,%ebx |
movl $0,(%ebx) |
/* Call wake_up(actual_context) */ |
movl SYMBOL_NAME(ll_clock),%eax |
131,6 → 133,9 |
movl SYMBOL_NAME(last_handler), %ebx |
call *%ebx |
apic_nohandler: |
sti |
popw %gs |
popw %fs |
popw %es |
153,16 → 158,17 |
pushw %fs |
pushw %gs |
movw $(X_FLATDATA_SEL),%ax |
movw %ax,%ds |
movw %ax,%es |
cli |
/* Send EOI to master PIC */ |
/* to perform later the overrun test */ |
/* Send ACK to master PIC */ |
movb $0x20,%al |
movl $0x20,%edx |
outb %al,%dx |
movw $(X_FLATDATA_SEL),%ax |
movw %ax,%ds |
movw %ax,%es |
/* Call wake_up(actual_context) */ |
movl SYMBOL_NAME(ll_clock),%eax |
243,6 → 249,9 |
movl SYMBOL_NAME(last_handler), %ebx |
call *%ebx |
nohandler: |
sti |
popw %gs |
popw %fs |
popw %es |
/shark/trunk/oslib/kl/advtimer.c |
---|
25,145 → 25,30 |
#include <ll/i386/stdlib.h> |
#include <ll/i386/error.h> |
#include <ll/i386/advtimer.h> |
#include <ll/sys/ll/ll-data.h> |
#include <ll/sys/ll/ll-func.h> |
#include <ll/i386/pic.h> |
#include <ll/i386/apic.h> |
#include <ll/i386/64bit.h> |
#include <ll/sys/ll/event.h> |
#include <ll/sys/ll/time.h> |
#include <ll/i386/advtimer.h> |
#define CALIBRATE_USING_CMOS |
unsigned char use_tsc = 1; //Enable the TSC counter mode |
unsigned char use_cmos = 0; //Enable the RTC correction |
unsigned char use_apic = 0; //Enable the APIC for P6 only |
unsigned long long init_tsc; |
unsigned long long * ptr_init_tsc = &init_tsc; |
//Max single delta_clk_per_msec increment = clk_per_msec / MAX_DIV_INK; |
#define MAX_DIV_INK 30000 |
unsigned long long init_nsec; //Wraparound 292 years |
unsigned long long * ptr_init_nsec = &init_nsec; |
signed long long init_tsc; |
signed long long * ptr_init_tsc = &init_tsc; |
unsigned int clk_per_msec = 0; |
unsigned int apic_clk_per_msec = 0; |
unsigned int apic_set_limit = 0; |
signed long long init_nsec; //Wraparound 292 years |
signed long long * ptr_init_nsec = &init_nsec; |
signed long long clk_per_msec; |
signed long long * ptr_clk_per_msec = &clk_per_msec; |
signed long long apic_clk_per_msec; |
unsigned int apic_set_limit; |
signed long last_delta_clk_per_msec; |
signed long total_delta_clk_per_msec; |
unsigned char save_CMOS_regA; |
unsigned char save_CMOS_regB; |
//#define IRQ8_DEBUG |
void HandlerIRQ8(void *p) |
{ |
unsigned char set; |
static unsigned long Mconst = 1000000; |
static unsigned long init_step = 0; |
signed long max_dcms = clk_per_msec / MAX_DIV_INK; |
static signed long long dn; |
static signed long long * ptr_dn = &dn; |
signed long delta_clk_per_msec; |
cli(); |
#ifdef IRQ8_DEBUG |
message("(IRQ8"); |
#endif |
CMOS_READ(0x0C,set); |
__asm__("xorl %%eax,%%eax\n\t" |
"cpuid\n\t" |
"rdtsc\n\t" |
"pushl %%eax\n\t" |
"pushl %%edx\n\t" |
"pushl %%eax\n\t" |
"pushl %%edx\n\t" |
"xorl %%eax,%%eax\n\t" |
"cpuid\n\t" |
"popl %%edx\n\t" |
"popl %%eax\n\t" |
"subl (%%edi),%%eax\n\t" |
"sbbl 4(%%edi),%%edx\n\t" |
"popl 4(%%edi)\n\t" |
"popl (%%edi)\n\t" |
"movl %%edx,%%ecx\n\t" |
"mull %4\n\t" |
"pushl %%eax\n\t" |
"movl %%ecx,%%eax\n\t" |
"movl %%edx,%%ecx\n\t" |
"mull %4\n\t" |
"addl %%ecx,%%eax\n\t" |
"adcl $0,%%edx\n\t" |
"movl %7,%%ebx\n\t" |
"divl (%%ebx)\n\t" |
"movl %%eax,4(%%esi)\n\t" |
"popl %%eax\n\t" |
"divl (%%ebx)\n\t" |
"movl %%eax,(%%esi)\n\t" |
: |
: "D" (ptr_init_tsc), "S" (ptr_dn), "b" (0), |
"c" (0), "m" (Mconst), "a" (0), "d" (0), "m" (ptr_clk_per_msec)); |
//Offset |
init_nsec += dn; |
if (init_step < 5) { |
init_step++; |
#ifdef IRQ8_DEBUG |
message(")"); |
#endif |
sti(); |
return; |
} |
dn = dn % 1000000000 - 500000000; |
//Delta clk/msec |
delta_clk_per_msec = dn * clk_per_msec / (500000000 - dn); |
//clk_per_msec adjustment |
if (delta_clk_per_msec < 0) { |
if (delta_clk_per_msec > -max_dcms) |
clk_per_msec += delta_clk_per_msec; |
else |
clk_per_msec -= max_dcms; |
} else { |
if (delta_clk_per_msec < max_dcms) |
clk_per_msec += delta_clk_per_msec; |
else |
clk_per_msec += max_dcms; |
} |
last_delta_clk_per_msec = delta_clk_per_msec; |
total_delta_clk_per_msec += delta_clk_per_msec; |
#ifdef IRQ8_DEBUG |
message(")"); |
#endif |
sti(); |
} |
#ifdef CONFIG_MELAN |
# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ |
#else |
178,11 → 63,11 |
void ll_calibrate_tsc(void) |
{ |
signed long long start; |
signed long long end; |
signed long long dtsc; |
unsigned long long start; |
unsigned long long end; |
unsigned long long dtsc; |
signed long start_8253, end_8253, delta_8253; |
unsigned int start_8253, end_8253, delta_8253; |
cli(); |
231,13 → 116,13 |
ll_abort(10); |
} |
message("Delta TSC = %10ld\n",(long)dtsc); |
message("Delta TSC = %10d\n",(int)dtsc); |
message("Delta PIT = %10ld\n",(long)delta_8253); |
message("Delta PIT = %10d\n",delta_8253); |
clk_per_msec = dtsc * CLOCK_TICK_RATE / delta_8253 / 1000; |
message("Calibrated Clk_per_msec = %10ld\n",(long)clk_per_msec); |
message("Calibrated Clk_per_msec = %10d\n",clk_per_msec); |
sti(); |
249,8 → 134,8 |
#define CMOS_END 3 |
int cmos_calibrate_status = CMOS_INIT; |
signed long long irq8_start; |
signed long long irq8_end; |
unsigned long long irq8_start; |
unsigned long long irq8_end; |
void calibrate_tsc_IRQ8(void *p) |
{ |
286,7 → 171,7 |
void ll_calibrate_tsc_cmos(void) |
{ |
signed long long dtsc; |
unsigned long long dtsc; |
cli(); |
310,7 → 195,7 |
clk_per_msec = dtsc / 500; |
message("Calibrated CPU Clk/msec = %10ld\n",(long)clk_per_msec); |
message("Calibrated CPU Clk/msec = %10d\n",clk_per_msec); |
cli(); |
323,53 → 208,6 |
} |
//Low level time read function |
void ll_read_timespec(struct timespec *tspec) |
{ |
static unsigned long Gconst = 1000000000; |
static unsigned long Mconst = 1000000; |
if (clk_per_msec <= 0) { |
NULL_TIMESPEC(tspec); |
return; |
} |
__asm__("xorl %%eax,%%eax\n\t" |
"cpuid\n\t" |
"rdtsc\n\t" |
"pushl %%eax\n\t" |
"pushl %%edx\n\t" |
"xorl %%eax,%%eax\n\t" |
"cpuid\n\t" |
"popl %%edx\n\t" |
"popl %%eax\n\t" |
"subl (%%edi),%%eax\n\t" |
"sbbl 4(%%edi),%%edx\n\t" |
"movl %%edx,%%ecx\n\t" |
"mull %6\n\t" |
"pushl %%eax\n\t" |
"movl %%ecx,%%eax\n\t" |
"movl %%edx,%%ecx\n\t" |
"mull %6\n\t" |
"addl %%ecx,%%eax\n\t" |
"adcl $0,%%edx\n\t" |
"movl %8,%%ebx\n\t" |
"divl (%%ebx)\n\t" |
"movl %%eax,%%ecx\n\t" |
"popl %%eax\n\t" |
"divl (%%ebx)\n\t" |
"movl %%ecx,%%edx\n\t" |
"addl (%%esi),%%eax\n\t" |
"adcl 4(%%esi),%%edx\n\t" |
"divl %7\n\t" |
: "=a" (tspec->tv_sec), "=d" (tspec->tv_nsec) |
: "D" (ptr_init_tsc), "S" (ptr_init_nsec), "b" (0), |
"c" (0), "m" (Mconst), "m" (Gconst), "m" (ptr_clk_per_msec)); |
} |
int apic_get_maxlvt(void) |
{ |
unsigned int v, ver, maxlvt; |
523,7 → 361,7 |
{ |
unsigned int apic_start = 0, apic_end = 0, dapic; |
signed long long tsc_start = 0, tsc_end = 0, dtsc; |
unsigned long long tsc_start = 0, tsc_end = 0, dtsc; |
unsigned int tmp_value; |
cli(); |
557,17 → 395,20 |
dtsc = tsc_end - tsc_start; |
dapic = apic_start - apic_end; |
apic_clk_per_msec = clk_per_msec * (signed long long)(dapic) / dtsc; |
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 = %10ld\n",(long)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 |
if (use_tsc) { |
#ifdef __TSC__ |
#ifdef CALIBRATE_USING_CMOS |
ll_calibrate_tsc_cmos(); |
575,14 → 416,10 |
ll_calibrate_tsc(); |
#endif |
last_delta_clk_per_msec = 0; |
total_delta_clk_per_msec = 0; |
rdtscll(init_tsc); // Read start TSC |
init_nsec = 0; |
if (use_apic) { |
unsigned long msr_low_orig, tmp; |
#ifdef __APIC__ |
rdmsr(APIC_BASE_MSR, msr_low_orig, tmp); |
wrmsr(APIC_BASE_MSR, msr_low_orig|(1<<11), 0); |
595,52 → 432,16 |
setup_APIC_timer(); |
} |
#endif |
if (use_cmos) { |
#endif |
message("CMOS adjustement enabled\n"); |
cli(); |
irq_bind(8, HandlerIRQ8, 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 |
irq_unmask(8); |
sti(); |
} |
} else { |
use_cmos = 0; |
} |
} |
void ll_restore_adv() |
{ |
/* Restore CMOS setting */ |
if (use_cmos) { |
cli(); |
irq_mask(8); |
CMOS_WRITE(0x0A,save_CMOS_regA); |
CMOS_WRITE(0x0B,save_CMOS_regB); |
sti(); |
} |
/* Disable APIC */ |
if (use_apic) { |
#ifdef __APIC__ |
unsigned int msr_low_orig, tmp; |
cli(); |
652,6 → 453,6 |
sti(); |
} |
#endif |
} |