Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 41 → Rev 120

/shark/trunk/oslib/kl/time.c
21,6 → 21,13
 
/* Time management code: ll_getttime() */
 
/* Added Advanced Timer Code
*
* Date: 8.4.2003
* Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
*
*/
 
#include <ll/i386/pit.h>
#include <ll/i386/stdlib.h>
#include <ll/i386/error.h>
41,6 → 48,8
extern BYTE frc;
extern int activeEvent;
 
extern unsigned char use_tsc;
 
FILE(Time);
 
TIME ll_gettime(int mode, struct timespec *tsres)
49,6 → 58,8
BYTE isr;
struct timespec tmp;
 
if (!use_tsc) {
 
#if 1
if (activeEvent) {
if (tsres != NULL) {
125,4 → 136,69
}
}
return 0;
 
} else {
 
#if 1
if (activeEvent) {
if (tsres != NULL) {
read_timespec(tsres);
} else {
struct timespec tmp;
 
read_timespec(&tmp);
return TIMESPEC2USEC(&tmp);
}
return TIMESPEC2USEC(tsres);
}
#endif
 
if (mode == TIME_PTICK) {
if (timermode != LL_PERIODIC) {
return 0;
}
if(tsres != NULL) {
read_timespec(tsres);
} else {
struct timespec tmp;
 
read_timespec(&tmp);
return TIMESPEC2USEC(&tmp);
}
return TIMESPEC2USEC(tsres);
}
 
if (mode == TIME_NEW) {
if (tsres != NULL) {
read_timespec(tsres);
return TIMESPEC2USEC(tsres);
} else {
struct timespec tmp;
 
read_timespec(&tmp);
return TIMESPEC2USEC(&tmp);
}
}
 
if (mode == TIME_EXACT) {
if (timermode == LL_PERIODIC) {
if (tsres != NULL) {
read_timespec(tsres);
} else {
struct timespec tmp;
 
read_timespec(&tmp);
return TIMESPEC2USEC(&tmp);
}
return TIMESPEC2USEC(tsres);
} else {
return 0;
}
}
 
return 0;
 
}
}
/shark/trunk/oslib/kl/event.c
19,6 → 19,13
* For legalese, check out the included GPL license.
*/
 
/* Added Advanced Timer Code
*
* Date: 8.4.2003
* Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
*
*/
 
/* Time Event routines */
 
#include <ll/i386/stdlib.h>
61,6 → 68,8
extern void (*evt_prol) (void);
extern void (*evt_epil) (void);
 
extern unsigned char use_tsc;
 
void event_setlasthandler(void *p)
{
last_handler = p;
152,17 → 161,23
struct event *p, *pp;
WORD tmp;
 
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
 
if(!use_tsc) {
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
}
activeInt++;
if (activeInt == 1 && evt_prol != NULL) {
evt_prol();
}
 
ADDNANO2TIMESPEC(nts, &actTime);
 
if (!use_tsc) {
ADDNANO2TIMESPEC(nts, &actTime);
} else {
read_timespec(&actTime);
}
for (p = firstevent; p != NULL; p = pp) {
/*
SUBTIMESPEC(&(p->time), &actTime, &tmp);
197,7 → 212,7
IDT_place(0x40,ll_timer);
 
if (l->mode != LL_PERIODIC) {
error("Trying one-shot!!!");
message("One-shot mode\n");
t = 0;
/* Mode: Binary/Mode 4/16 bit Time_const/Counter 0 */
pit_init(0, TMR_MD4, 0xFFFF); /* Timer 0, Mode 4, constant 0xFFFF */
256,6 → 271,8
/* Initialization of the time variables for periodic mode */
nts = ticksize * 1000;
NULL_TIMESPEC(&actTime);
if (use_tsc) ll_init_advtimer();
 
/* Initialization of the general time variables */
NULLPITSPEC(&globalCounter);
/shark/trunk/oslib/kl/event1.c
19,6 → 19,13
* For legalese, check out the included GPL license.
*/
 
/* Added Advanced Timer Code
*
* Date: 8.4.2003
* Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
*
*/
 
/* Time Event routines (one shot mode) */
 
#include <ll/i386/stdlib.h>
45,6 → 52,8
extern void (*evt_prol) (void);
extern void (*evt_epil) (void);
 
extern unsigned char use_tsc;
 
/* TODO: oneshot_event_delete & oneshot_event_init... */
 
/* Switched to timespec */
112,12 → 121,20
WORD tmp;
DWORD tnext;
 
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
if (!use_tsc) {
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
 
PITSPEC2TIMESPEC(&globalCounter, &now);
PITSPEC2TIMESPEC(&globalCounter, &now);
 
} else {
 
read_timespec(&now);
 
}
 
if (firstevent != NULL) {
activeEvent = 1;
if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
144,13 → 161,22
}
activeInt--;
}
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
 
PITSPEC2TIMESPEC(&globalCounter, &now);
if (!use_tsc) {
tmp = pit_read(frc);
ADDPITSPEC((WORD) (lastTime - tmp), &globalCounter);
lastTime = tmp;
 
PITSPEC2TIMESPEC(&globalCounter, &now);
 
} else {
 
read_timespec(&now);
 
}
 
 
if (TIMESPEC_A_GT_B(&now, &(firstevent->time))) {
NULL_TIMESPEC(&ttmp);
} else {
/shark/trunk/oslib/kl/init.c
183,7 → 183,8
void abort_tail(int code)
{
message("ABORT %d !!!",code);
l1_end();
restore_CMOS();
l1_end();
sti();
l1_exit(1);
}
190,6 → 191,7
 
void ll_end(void)
{
restore_CMOS();
l1_end();
}
 
/shark/trunk/oslib/kl/advtimer.c
0,0 → 1,267
/* Project: OSLib
* Description: The OS Construction Kit
* Date: 1.6.2000
* Idea by: Luca Abeni & Gerardo Lamastra
*
* OSLib is an SO project aimed at developing a common, easy-to-use
* low-level infrastructure for developing OS kernels and Embedded
* Applications; it partially derives from the HARTIK project but it
* currently is independently developed.
*
* OSLib is distributed under GPL License, and some of its code has
* been derived from the Linux kernel source; also some important
* ideas come from studying the DJGPP go32 extender.
*
* We acknowledge the Linux Community, Free Software Foundation,
* D.J. Delorie and all the other developers who believe in the
* freedom of software and ideas.
*
* For legalese, check out the included GPL license.
*/
 
/* Advanced Timer Managment
* Author: Giacomo Guidi <giacomo@gandalf.sssup.it>
*/
 
#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/sys/ll/event.h>
#include <ll/sys/ll/time.h>
 
unsigned char use_tsc = 0; //Enable the TSC counter mode
unsigned char use_cmos = 0; //Enable the RTC correction
 
//Max single delta_clk_per_msec increment
#define MAX_DELTA_INK 10
 
//Max delta_clk_per_msec before declare lost
//the CMOS sync
#define MAX_DELTA_TOT 100
 
signed long long init_tsc;
signed long long init_nsec; //Warp around 292 years !!
signed long long clk_per_msec;
 
signed long last_delta_clk_per_msec;
signed long total_delta_clk_per_msec;
 
unsigned char save_CMOS_regA;
unsigned char save_CMOS_regB;
 
void HandlerIRQ8(void *p)
{
 
unsigned char set;
static unsigned long init_step = 0;
signed long long actual_tsc;
signed long long dt,dn;
signed long delta_clk_per_msec;
 
cli();
CMOS_READ(0x0C,set);
rdtscll(actual_tsc);
//Delta TSC
dt = actual_tsc - init_tsc;
 
init_tsc = actual_tsc;
UNSIGNED_TSC2NSEC(dt,&dn);
//Offset
init_nsec += dn;
if (init_step < 5) {
init_step++;
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_DELTA_INK)
clk_per_msec += delta_clk_per_msec;
else
clk_per_msec -= MAX_DELTA_INK;
} else {
if (delta_clk_per_msec < MAX_DELTA_INK)
clk_per_msec += delta_clk_per_msec;
else
clk_per_msec += MAX_DELTA_INK;
}
if (delta_clk_per_msec > MAX_DELTA_TOT || delta_clk_per_msec < -MAX_DELTA_TOT) {
message("Error: Delta_clk_per_msec |%ld| > %ld\n",\
(long)delta_clk_per_msec,(long)MAX_DELTA_TOT);
ll_abort(10);
}
last_delta_clk_per_msec = delta_clk_per_msec;
total_delta_clk_per_msec += delta_clk_per_msec;
sti();
}
 
#define HZ 100
 
#ifdef CONFIG_MELAN
# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
#else
# define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#endif
 
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)
 
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
 
//TSC Calibration (idea from the linux kernel code)
void ll_calibrate_tsc(void)
{
 
signed long long start;
signed long long end;
signed long long dtsc;
signed long start_8253, end_8253, delta_8253;
 
cli();
/* Set the Gate high, disable speaker */
outp(0x61, (inp(0x61) & ~0x02) | 0x01);
 
outp(0x43,0xB0); /* binary, mode 0, LSB/MSB, Ch 2 */
outp(0x42,CALIBRATE_LATCH & 0xff); /* LSB of count */
outp(0x42,CALIBRATE_LATCH >> 8); /* MSB of count */
 
rdtscll(start);
outp(0x43,0x00);
start_8253 = inp(0x42);
start_8253 |= inp(0x42) << 8;
 
do {
outp(0x43,0x00);
end_8253 = inp(0x42);
end_8253 |= inp(0x42) << 8;
 
} while (end_8253 > 10);
rdtscll(end);
outp(0x43,0x00);
end_8253 = inp(0x42);
end_8253 |= inp(0x42) << 8;
 
//Delta TSC
dtsc = end - start;
 
//Delta PIT
delta_8253 = start_8253 - end_8253 + 1;
 
if (delta_8253 > 0xFFFF) {
message("Error calculating Delta PIT\n");
ll_abort(10);
}
 
message("Delta TSC = %10ld\n",(long)dtsc);
 
message("Delta PIT = %10ld\n",(long)delta_8253);
 
clk_per_msec = dtsc * CALIBRATE_LATCH * 1000 / delta_8253 / CALIBRATE_TIME;
message("Calibrated Clk_per_msec = %10ld\n",(long)clk_per_msec);
 
sti();
}
 
//Low level time read function
void read_timespec(struct timespec *tspec)
{
 
signed long long actual_tsc;
signed long long dt,dn;
 
rdtscll(actual_tsc);
 
tspec->tsc = actual_tsc;
dt = actual_tsc - init_tsc;
UNSIGNED_TSC2NSEC(dt,&dn);
tspec->tv_sec = (init_nsec + dn) / 1000000000;
tspec->tv_nsec = (init_nsec + dn) % 1000000000;
}
 
void ll_init_advtimer()
{
 
if (use_tsc) {
ll_calibrate_tsc();
last_delta_clk_per_msec = 0;
total_delta_clk_per_msec = 0;
rdtscll(init_tsc); // Read start TSC
init_nsec = 0;
 
if (use_cmos) {
 
message("CMOS adjustment 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 restore_CMOS()
{
if (use_cmos) {
cli();
irq_mask(8);
CMOS_WRITE(0x0A,save_CMOS_regA);
CMOS_WRITE(0x0B,save_CMOS_regB);
sti();
}
}
/shark/trunk/oslib/kl/makefile
24,7 → 24,8
aspace.o \
intevt.o \
event.o \
event1.o
event1.o \
advtimer.o
 
KL_OBJ = $(KL_C_OBJ) abort.o timeint.o