## diffname pc/i8253.c 1997/0327
## diff -e /dev/null /n/emeliedump/1997/0327/sys/src/brazil/pc/i8253.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
/*
* 8253 timer
*/
enum
{
T0cntr= 0x40, /* counter ports */
T1cntr= 0x41, /* ... */
T2cntr= 0x42, /* ... */
Tmode= 0x43, /* mode port */
/* commands */
Latch0= 0x00, /* latch counter 0's value */
Load0= 0x30, /* load counter 0 with 2 bytes */
/* modes */
Square= 0x36, /* periodic square wave */
Trigger= 0x30, /* interrupt on terminal count */
Freq= 1193182, /* Real clock frequency */
};
void
i8253init(int aalcycles)
{
int cpufreq, loops, incr, x, y;
static int initialised;
if(initialised == 0){
initialised = 1;
/*
* set clock for 1/HZ seconds
*/
outb(Tmode, Load0|Square);
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
}
/* find biggest loop that doesn't wrap */
incr = 16000000/(aalcycles*HZ*2);
x = 2000;
for(loops = incr; loops < 64*1024; loops += incr) {
/*
* measure time for the loop
*
* MOVL loops,CX
* aaml1: AAM
* LOOP aaml1
*
* the time for the loop should be independent of external
* cache and memory system since it fits in the execution
* prefetch buffer.
*
*/
outb(Tmode, Latch0);
x = inb(T0cntr);
x |= inb(T0cntr)<<8;
aamloop(loops);
outb(Tmode, Latch0);
y = inb(T0cntr);
y |= inb(T0cntr)<<8;
x -= y;
if(x < 0)
x += Freq/HZ;
if(x > Freq/(3*HZ))
break;
}
/*
* counter goes at twice the frequency, once per transition,
* i.e., twice per square wave
*/
x >>= 1;
/*
* figure out clock frequency and a loop multiplier for delay().
*/
cpufreq = loops*((aalcycles*Freq)/x);
m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */
/*
* add in possible 0.5% error and convert to MHz
*/
m->cpumhz = (cpufreq + cpufreq/200)/1000000;
}
void
i8253enable(void)
{
intrenable(VectorCLOCK, clockintr, 0, BUSUNKNOWN);
}
.
## diffname pc/i8253.c 1998/0710
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/i8253.c /n/emeliedump/1998/0710/sys/src/brazil/pc/i8253.c
100a
Lock i8253lock;
/*
* return time elapsed since clock start in
* 10ths of nanoseconds
*/
uvlong
i8253read(uvlong *hz)
{
if(hz)
*hz = HZ;
return m->ticks;
}
.
## diffname pc/i8253.c 1998/0819
## diff -e /n/emeliedump/1998/0710/sys/src/brazil/pc/i8253.c /n/emeliedump/1998/0819/sys/src/brazil/pc/i8253.c
102,103d
## diffname pc/i8253.c 1998/0903
## diff -e /n/emeliedump/1998/0819/sys/src/brazil/pc/i8253.c /n/emeliedump/1998/0903/sys/src/brazil/pc/i8253.c
42a
/*
* Introduce a little delay to make sure the count is
* latched and the timer is counting down; with a fast
* enough processor this may not be the case.
* The i8254 (which this probably is) has a read-back
* command which can be used to make sure the counting
* register has been written into the counting element.
*/
x = (Freq/HZ);
for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
outb(Tmode, Latch0);
x = inb(T0cntr);
x |= inb(T0cntr)<<8;
}
.
## diffname pc/i8253.c 1998/0910
## diff -e /n/emeliedump/1998/0903/sys/src/brazil/pc/i8253.c /n/emeliedump/1998/0910/sys/src/brazil/pc/i8253.c
114c
intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN);
.
## diffname pc/i8253.c 1999/0131
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/i8253.c /n/emeliedump/1999/0131/sys/src/brazil/pc/i8253.c
105,108c
if(havecycleclock){
/* counter goes up by 2*Freq */
b = (b-a)<<1;
b *= Freq;
b /= x;
/*
* round to the nearest megahz
*/
m->cpumhz = (b+500000)/1000000L;
m->cpuhz = b;
} else {
/*
* add in possible 0.5% error and convert to MHz
*/
m->cpumhz = (cpufreq + cpufreq/200)/1000000;
m->cpuhz = cpufreq;
}
.
102c
cpufreq = loops*((aalcycles*2*Freq)/x);
.
100a
* n.b. counter goes up by 2*Freq
.
94,99d
81a
if(havecycleclock)
rdmsr(0x10, &b);
.
77a
if(havecycleclock)
rdmsr(0x10, &a);
.
32a
vlong a, b;
.
30c
i8253init(int aalcycles, int havecycleclock)
.
## diffname pc/i8253.c 1999/0228
## diff -e /n/emeliedump/1999/0131/sys/src/brazil/pc/i8253.c /n/emeliedump/1999/0228/sys/src/brazil/pc/i8253.c
140,141c
*hz = HZ*100;
return m->ticks*100;
.
134c
* 100 times hz
.
## diffname pc/i8253.c 1999/0714
## diff -e /n/emeliedump/1999/0228/sys/src/brazil/pc/i8253.c /n/emeliedump/1999/0714/sys/src/brazil/pc/i8253.c
37a
ioalloc(T0cntr, 4, 0, "i8253");
.
## diffname pc/i8253.c 1999/0819
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/i8253.c /n/emeliedump/1999/0819/sys/src/brazil/pc/i8253.c
130c
intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN, "clock");
.
## diffname pc/i8253.c 2000/0621
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/i8253.c /n/emeliedump/2000/0621/sys/src/9/pc/i8253.c
130c
intrenable(IrqCLOCK, clockintr0, 0, BUSUNKNOWN, "clock");
.
126a
static void
clockintr0(Ureg* ureg, void *v)
{
loopbackintr();
clockintr(ureg, v);
}
.
## diffname pc/i8253.c 2000/0622
## diff -e /n/emeliedump/2000/0621/sys/src/9/pc/i8253.c /n/emeliedump/2000/0622/sys/src/9/pc/i8253.c
130c
loopbackintr(ureg);
.
126a
int
i8253readcnt(void)
{
ilock(&i8253lock);
iunlock(&i8253lock);
}
.
28a
static Lock i8253lock;
.
23,24c
Square= 0x6, /* periodic square wave */
Trigger= 0x0, /* interrupt on terminal count */
.
19a
Load0l= 0x10, /* load counter 0's lsb */
Load0m= 0x20, /* load counter 0's msb */
.
16c
Tmode= 0x43, /* mode port (control word register) */
.
## diffname pc/i8253.c 2000/0623
## diff -e /n/emeliedump/2000/0622/sys/src/9/pc/i8253.c /n/emeliedump/2000/0623/sys/src/9/pc/i8253.c
147a
i8253.when = fastticks(nil);
i8253.fastperiod = (m->cpuhz + HZ/2) / HZ;
i8253.fast2freq = (vlong)m->cpuhz * FreqMul / Freq;
.
141c
vlong now;
long set;
now = fastticks(nil);
while(i8253.when < now)
i8253.when += i8253.fastperiod;
set = (long)(i8253.when - now) * FreqMul / i8253.fast2freq;
set -= 3; /* three cycles for the count to take effect: outb, outb, wait */
lastfast = now;
outb(T0cntr, set); /* low byte */
outb(T0cntr, set>>8); /* high byte */
checkcycintr(ureg, v);
.
134,135c
int v;
ilock(&i8253.lock);
if(cntr == 2){
outb(Tmode, Rdback|Rd2cntr);
v = inb(T2cntr) << 16;
v |= inb(T2cntr);
v |= inb(T2cntr) << 8;
}else if(cntr == 0){
outb(Tmode, Rdback|Rd0cntr);
v = inb(T0cntr) << 16;
v |= inb(T0cntr);
v |= inb(T0cntr) << 8;
}else if(cntr == 3){
vlong nf = fastticks(nil);
long set;
set = (long)(nf - lastfast) * 100 / (long)((vlong)m->cpuhz * 100 / Freq);
set = (Freq/HZ) - set;
set -= 3 - 1; /* outb, outb, wait - outb(mode) */
outb(Tmode, Rdback|Rdnstat|Rd0cntr);
v = inb(T0cntr);
v |= inb(T0cntr) << 8;
v = set - v;
}else if(cntr == 4){
vlong nf = fastticks(nil);
long set;
set = (long)(nf - lastfast) * 16 / (long)((vlong)m->cpuhz * 16 / Freq);
set = (Freq/HZ) - set;
set -= 3 - 1; /* outb, outb, wait - outb(mode) */
outb(Tmode, Rdback|Rdnstat|Rd0cntr);
v = inb(T0cntr);
v |= inb(T0cntr) << 8;
v = set - v;
}else{
vlong nf = fastticks(nil);
long set;
set = (nf - lastfast) * Freq / m->cpuhz;
set = (Freq/HZ) - set;
set -= 3 - 1; /* outb, outb, wait - outb(mode) */
outb(Tmode, Rdback|Rdnstat|Rd0cntr);
v = inb(T0cntr);
v |= inb(T0cntr) << 8;
v = set - v;
}
iunlock(&i8253.lock);
return v;
.
132c
i8253readcnt(int cntr)
.
130a
static vlong lastfast;
.
128a
outb(Tmode, Load0|Trigger);
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
.
42a
ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
.
31c
static struct
{
Lock lock;
vlong when; /* next fastticks a clock interrupt should occur */
long fastperiod; /* fastticks/hz */
long fast2freq; /* fastticks*FreqMul/Freq */
}i8253;
.
28a
FreqMul=16, /* extra accuracy in fastticks/Freq calculation; ok up to ~8ghz */
.
27a
/* counter 2 controls */
C2gate= 0x1,
C2speak=0x2,
C2out= 0x10,
.
26c
Trigger=0x0, /* interrupt on terminal count */
Sstrobe=0x8, /* software triggered strobe */
.
24a
ModeMsk=0xe,
.
23a
/* 8254 read-back command: everything > pc-at has an 8254 */
Rdback= 0xc0, /* readback counters & status */
Rdnstat=0x10, /* don't read status */
Rdncnt= 0x20, /* don't read counter value */
Rd0cntr=0x02, /* read back for which counter */
Rd1cntr=0x04,
Rd2cntr=0x08,
.
22a
Latch2= 0x80, /* latch counter 2's value */
Load2l= 0x90, /* load counter 2's lsb */
Load2m= 0xa0, /* load counter 2's msb */
Load2= 0xb0, /* load counter 2 with 2 bytes */
.
16a
T2ctl= 0x61, /* counter 2 control port */
.
## diffname pc/i8253.c 2000/0624
## diff -e /n/emeliedump/2000/0623/sys/src/9/pc/i8253.c /n/emeliedump/2000/0624/sys/src/9/pc/i8253.c
234a
#endif
.
232d
223a
#ifdef SETNEXT
.
167,220d
165c
#ifdef SETNEXT
set up clock so it is reloaded every interrupt
outb(Tmode, Load0|Trigger);
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
#endif
.
159,162d
## diffname pc/i8253.c 2000/0627
## diff -e /n/emeliedump/2000/0624/sys/src/9/pc/i8253.c /n/emeliedump/2000/0627/sys/src/9/pc/i8253.c
184,185c
void
clockintrsched(void)
{
vlong next;
ilock(&i8253);
next = cycintrnext();
if(next != i8253.cycwhen)
clockintrsched0(next);
iunlock(&i8253);
}
static void
clockintr0(Ureg* ureg, void *v)
{
vlong now, when;
now = fastticks(nil);
when = i8253.when;
if(now >= i8253.when){
clockintr(ureg, v);
do
i8253.when += i8253.fastperiod;
while(i8253.when < now);
}
if(i8253.cycwhen || i8253.mode != Square)
clockintrsched0(checkcycintr(ureg, v));
.
176,182c
if(next || now < i8253.when - i8253.fastperiod || now > i8253.when - ((3*i8253.fastperiod)>>2)){
if(next > i8253.when)
next = i8253.when;
set = (long)(next - now) * FreqMul / i8253.fast2freq;
set -= 3; /* three cycles for the count to take effect: outb, outb, wait */
if(i8253.mode != Trigger){
outb(Tmode, Load0|Trigger);
i8253.mode = Trigger;
set--;
}
if(set < 3)
set = 5;
outb(T0cntr, set); /* low byte */
outb(T0cntr, set>>8); /* high byte */
}else if(i8253.mode != Square){
i8253.mode = Square;
outb(Tmode, Load0|Square);
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
}
}
.
174a
i8253.cycwhen = next;
if(i8253.mode == Square && next == 0)
return;
.
171d
169c
clockintrsched0(vlong next)
.
161,167c
/*
* schedule the next interrupt
* cycwhen is the next time for the cycle counter routines
*/
.
76a
i8253.mode = Square;
.
56a
vlong cycwhen; /* next fastticks a cycintr happens; 0 == infinity */
.
55c
Lock;
int mode;
.
## diffname pc/i8253.c 2000/0701
## diff -e /n/emeliedump/2000/0627/sys/src/9/pc/i8253.c /n/emeliedump/2000/0701/sys/src/9/pc/i8253.c
235a
i8253.enabled = 1;
.
207,209c
if(i8253.enabled){
next = cycintrnext();
if(next != i8253.cycwhen)
clockintrsched0(next);
}
.
200a
int
havecycintr(void)
{
return i8253.enabled;
}
.
55a
int enabled;
.
## diffname pc/i8253.c 2000/0706
## diff -e /n/emeliedump/2000/0701/sys/src/9/pc/i8253.c /n/emeliedump/2000/0706/sys/src/9/pc/i8253.c
190,191c
if(set < Minusec)
set = Minusec;
.
49a
Minusec=20, /* minimum cycles for a clock interrupt */
.
## diffname pc/i8253.c 2000/0713
## diff -e /n/emeliedump/2000/0706/sys/src/9/pc/i8253.c /n/emeliedump/2000/0713/sys/src/9/pc/i8253.c
227a
if(!i8253.havecyc){
clockintr(ureg, v);
return;
}
.
216c
if(i8253.enabled && i8253.havecyc){
.
207c
return i8253.havecyc && i8253.enabled;
.
74a
i8253.havecyc = havecycleclock;
.
57a
int havecyc;
.
## diffname pc/i8253.c 2001/0611
## diff -e /n/emeliedump/2000/0713/sys/src/9/pc/i8253.c /n/emeliedump/2001/0611/sys/src/9/pc/i8253.c
237a
/*
* If we suspend the machine and resume, the
* processor cycle counter gets reset. Detect this
* and deal with it.
*/
if(now < i8253.when && i8253.when-now > 3*i8253.fastperiod)
i8253.when = now;
.
## diffname pc/i8253.c 2001/1130
## diff -e /n/emeliedump/2001/0611/sys/src/9/pc/i8253.c /n/emeliedump/2001/1130/sys/src/9/pc/i8253.c
129c
rdtsc(&b);
.
123c
rdtsc(&a);
.
## diffname pc/i8253.c 2002/0221
## diff -e /n/emeliedump/2001/1130/sys/src/9/pc/i8253.c /n/emeliedump/2002/0221/sys/src/9/pc/i8253.c
262c
i8253.fast2freq = m->cpuhz * FreqMul / Freq;
.
## diffname pc/i8253.c 2002/0314
## diff -e /n/emeliedump/2002/0221/sys/src/9/pc/i8253.c /n/emeliedump/2002/0314/sys/src/9/pc/i8253.c
262c
i8253.fast2freq = (vlong)m->cpuhz * FreqMul / Freq;
.
## diffname pc/i8253.c 2002/0404
## diff -e /n/emeliedump/2002/0314/sys/src/9/pc/i8253.c /n/emeliedump/2002/0404/sys/src/9/pc/i8253.c
147d
140d
133c
.
127d
123a
outb(Tmode, Latch0);
.
121d
## diffname pc/i8253.c 2002/0405
## diff -e /n/emeliedump/2002/0404/sys/src/9/pc/i8253.c /n/emeliedump/2002/0405/sys/src/9/pc/i8253.c
272,273c
*hz = Freq<<8;
ilock(&i8253.lock1);
outb(Tmode, Latch1);
y = inb(T1cntr);
y |= inb(T1cntr)<<8;
if(y < i8253.last1)
x = i8253.last1 - y;
else
x = i8253.last1 + (0xfffe - y);
i8253.last1 = y;
i8253.ticks1 += x>>1;
ticks = i8253.ticks1;
iunlock(&i8253.lock1);
return ticks<<8;
}
/*
* return value and speed of timer set in arch->clockenable
*/
vlong
fastticks(uvlong *hz)
{
return (*arch->fastclock)(hz);
.
270a
ushort y, x;
uvlong ticks;
.
265,266c
* return the total ticks of counter 1. We shift by
* 8 to give timesync more wriggle room for interpretation
* of the frequency
.
257,259c
uvlong hz;
i8253.when = fastticks(&hz);
i8253.fastperiod = (hz + HZ/2) / HZ;
i8253.fast2freq = (hz * FreqMul) / Freq;
.
250,251c
if(i8253.timerwhen || i8253.mode != Square)
clockintrsched0(checktimer(ureg, v));
.
236,243d
228,231c
nclockintr0++;
/* goes with syncing in squidboy */
if(m->havetsc)
rdtsc(&m->lasttsc);
.
222a
int nclockintr0;
.
215,217c
if(i8253.enabled){
next = timernext();
if(next != i8253.timerwhen)
.
206c
return i8253.enabled;
.
204c
havetimer(void)
.
176c
i8253.timerwhen = next;
.
168c
* timerwhen is the time of the next interrupt
.
146a
if(m->havetsc){
.
145d
138a
.
132c
.
127c
outb(Tmode, Latch0);
if(m->havetsc)
.
123a
if(m->havetsc)
rdtsc(&a);
.
121,122d
103a
void
guesscpuhz(int aalcycles)
{
int cpufreq, loops, incr, x, y;
vlong a, b;
.
102a
}
.
88,101c
/*
* set time clock
*/
outb(Tmode, Load1|Square);
i8253.mode = Square;
outb(T1cntr, 0xfe); /* low byte */
outb(T1cntr, 0xff); /* high byte */
/*
* Introduce a little delay to make sure the count is
* latched and the timer is counting down; with a fast
* enough processor this may not be the case.
* The i8254 (which this probably is) has a read-back
* command which can be used to make sure the counting
* register has been written into the counting element.
*/
x = (Freq/HZ);
for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
outb(Tmode, Latch0);
x = inb(T0cntr);
x |= inb(T0cntr)<<8;
.
80,86c
/*
* set interrupting clock for 1/HZ seconds
*/
outb(Tmode, Load0|Square);
i8253.mode = Square;
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
.
74,78c
ioalloc(T0cntr, 4, 0, "i8253");
ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
.
70,72c
int loops, x;
.
68c
i8253init(void)
.
64a
Lock lock1; /* mutex for the following */
ushort last1; /* last value of clock 1 */
uvlong ticks1; /* cumulative ticks of counter 1 */
.
62c
vlong timerwhen; /* next fastticks a cycintr happens; 0 == infinity */
.
58d
23a
Latch1= 0x40, /* latch counter 1's value */
Load1l= 0x50, /* load counter 1's lsb */
Load1m= 0x60, /* load counter 1's msb */
Load1= 0x70, /* load counter 1 with 2 bytes */
.
## diffname pc/i8253.c 2002/0406
## diff -e /n/emeliedump/2002/0405/sys/src/9/pc/i8253.c /n/emeliedump/2002/0406/sys/src/9/pc/i8253.c
256a
if(i8253.last1 == 0 || i8253.last1 >= 0xffe0)
i8253ding[1]++;
else
i8253ding[0]++;
.
250d
244c
ulong i8253ding[2];
.
## diffname pc/i8253.c 2002/0409
## diff -e /n/emeliedump/2002/0406/sys/src/9/pc/i8253.c /n/emeliedump/2002/0409/sys/src/9/pc/i8253.c
314c
return ticks<<Tickshift;
.
308,312c
x = i8253.last + (0x1000 - y);
i8253.last = y;
i8253.ticks += x>>1;
ticks = i8253.ticks;
iunlock(&i8253);
.
305,306c
if(y < i8253.last)
x = i8253.last - y;
.
300,303c
ilock(&i8253);
outb(Tmode, Latch2);
y = inb(T2cntr);
y |= inb(T2cntr)<<8;
.
298c
*hz = Freq<<Tickshift;
.
258,263d
244,245d
95,98c
outb(Tmode, Load2|Square);
outb(T2cntr, 0); /* low byte */
outb(T2cntr, 0); /* high byte */
x = inb(T2ctl);
x |= T2gate;
outb(T2ctl, x);
.
93c
* enable a longer period counter to use as a clock
.
71,73c
ushort last; /* last value of clock 1 */
uvlong ticks; /* cumulative ticks of counter 1 */
.
54a
Tickshift= 8, /* increase tick wriggle room */
.
53a
/* T2ctl bits */
T2gate= (1<<0), /* enable T2 counting */
T2spkr= (1<<1), /* connect T2 out to speaker */
T2out= (1<<5), /* output of T2 */
.
## diffname pc/i8253.c 2002/0410
## diff -e /n/emeliedump/2002/0409/sys/src/9/pc/i8253.c /n/emeliedump/2002/0410/sys/src/9/pc/i8253.c
322c
millisecs *= m->loopconst;
if(millisecs <= 0)
millisecs = 1;
aamloop(millisecs);
}
void
microdelay(int microsecs)
{
microsecs *= m->loopconst;
microsecs /= 1000;
if(microsecs <= 0)
microsecs = 1;
aamloop(microsecs);
}
ulong
TK2MS(ulong ticks)
{
uvlong t, hz;
t = ticks;
hz = HZ;
t *= 1000L;
t = t/hz;
ticks = t;
return ticks;
.
316,320c
void
delay(int millisecs)
.
307c
x = i8253.last + (0x10000 - y);
.
297c
*hz = i8253.hz;
.
282c
i8253.period = Freq/HZ;
intrenable(IrqCLOCK, i8253clock, 0, BUSUNKNOWN, "clock");
.
276,280d
254,270c
timerintr(ureg, 0);
.
252c
i8253clock(Ureg* ureg, void*)
.
248d
237,246c
/* remember period */
i8253.period = period;
i8253periodset++;
iunlock(&i8253);
.
231,235c
/* histeresis */
if(i8253.period != period){
ilock(&i8253);
/* load new value */
outb(Tmode, Load0|Square);
outb(T0cntr, period); /* low byte */
outb(T0cntr, period>>8); /* high byte */
.
229d
208,227c
period = MaxPeriod;
if(next != 0){
period = want - now;
if(period < MinPeriod)
period = MinPeriod;
else if(period > (4*MaxPeriod)/5) /* strong attraction to MaxPeriod */
period = MaxPeriod;
.
204,206c
want = next>>Tickshift;
now = i8253.ticks; /* assuming whomever called us just did fastticks() */
.
201,202c
ulong period;
ulong want;
ulong now;
.
194,199c
ulong i8253periodset;
void
i8253timerset(uvlong next)
.
191a
i8253.hz = Freq<<Tickshift;
.
106c
.
102a
i8253.period = Freq/HZ;
.
95a
i8253.period = Freq/HZ;
.
93d
90c
* enable a 1/HZ interrupt for providing scheduling interrupts
.
80a
.
71,75c
uvlong hz;
.
69a
ulong period; /* current clock period */
.
60,64c
Tickshift=8, /* extra accuracy */
MaxPeriod=Freq/HZ,
MinPeriod=Freq/(100*HZ),
.
49,53d
## diffname pc/i8253.c 2002/0415
## diff -e /n/emeliedump/2002/0410/sys/src/9/pc/i8253.c /n/emeliedump/2002/0415/sys/src/9/pc/i8253.c
119c
uvlong a, b;
.
## diffname pc/i8253.c 2002/0609
## diff -e /n/emeliedump/2002/0415/sys/src/9/pc/i8253.c /n/emeliedump/2002/0609/sys/src/9/pc/i8253.c
235a
}
static long
i8253timerread(Chan*, void *a, long n, vlong offset)
{
if(n < 16)
error("need more room");
if(offset)
return 0;
return snprint(a, n, "timerset %s", i8253dotimerset ? "on" : "off");
}
static long
i8253timerwrite(Chan*, void *a, long n, vlong)
{
if(n==3 && memcmp(a, "off", 3) == 0){
i8253dotimerset = 0;
outb(Tmode, Load0|Square);
outb(T0cntr, (Freq/HZ));
outb(T0cntr, (Freq/HZ)>>8);
return n;
}
if(n==2 && memcmp(a, "on", 2) == 0){
i8253dotimerset = 1;
return n;
}
error("invalid control message");
return -1;
}
void
i8253link(void)
{
addarchfile("i8253timerset", 0664, i8253timerread, i8253timerwrite);
.
196a
if(i8253dotimerset == 0)
return;
.
188a
int i8253dotimerset = 1;
.
## diffname pc/i8253.c 2002/0703
## diff -e /n/emeliedump/2002/0609/sys/src/9/pc/i8253.c /n/emeliedump/2002/0703/sys/src/9/pc/i8253.c
213c
/* hysteresis */
.
## diffname pc/i8253.c 2002/0710
## diff -e /n/emeliedump/2002/0703/sys/src/9/pc/i8253.c /n/emeliedump/2002/0710/sys/src/9/pc/i8253.c
325,337d
## diffname pc/i8253.c 2002/0822
## diff -e /n/emeliedump/2002/0710/sys/src/9/pc/i8253.c /n/emeliedump/2002/0822/sys/src/9/pc/i8253.c
324a
/*
* performance measurement ticks. must be low overhead.
* doesn't have to count over a second.
*/
ulong
perfticks(void)
{
uvlong x;
if(!m->havetsc)
return m->ticks;
rdtsc(&x);
return x;
}
.
## diffname pc/i8253.c 2002/1218
## diff -e /n/emeliedump/2002/0822/sys/src/9/pc/i8253.c /n/emeliedump/2002/1218/sys/src/9/pc/i8253.c
219c
outb(T0cntr, period>>8); /* high byte */
.
214a
memmove(&phist[0], &phist[1], sizeof(phist)-sizeof(ulong));
phist[nelem(phist)-1] = period;
.
190a
ulong phist[128];
.
## diffname pc/i8253.c 2002/1219
## diff -e /n/emeliedump/2002/1218/sys/src/9/pc/i8253.c /n/emeliedump/2002/1219/sys/src/9/pc/i8253.c
223c
outb(T0cntr, period >> 8); /* high byte */
.
196c
long period;
.
94d
86d
79a
i8253.period = Freq/HZ;
.
## diffname pc/i8253.c 2003/0326
## diff -e /n/emeliedump/2002/1219/sys/src/9/pc/i8253.c /n/emeliedump/2003/0326/sys/src/9/pc/i8253.c
277d
246,273d
|