M alphapc/cycintr.c => alphapc/cycintr.c +3 -3
@@ 6,18 6,18 @@
#include "io.h"
int
-havecycintr(void)
+havetimer(void)
{
return 0;
}
void
-cycintradd(Cycintr *)
+timeradd(Timer *)
{
}
void
-cycintrdel(Cycintr *)
+timerdel(Timer *)
{
}
M alphapc/dat.h => alphapc/dat.h +4 -4
@@ 1,5 1,5 @@
typedef struct Conf Conf;
-typedef struct Cycintr Cycintr;
+typedef struct Timer Timer;
typedef struct FPsave FPsave;
typedef struct ISAConf ISAConf;
typedef struct Label Label;
@@ 252,10 252,10 @@ struct DevConf
/*
* fasttick timer interrupts (Dummy for now)
*/
-struct Cycintr
+struct Timer
{
vlong when; /* fastticks when f should be called */
- void (*f)(Ureg*, Cycintr*);
+ void (*f)(Ureg*, Timer*);
void *a;
- Cycintr *next;
+ Timer *next;
};
M alphapc/fns.h => alphapc/fns.h +3 -3
@@ 13,8 13,8 @@ int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void cpuidprint(void);
void cserve(ulong, ulong);
-void cycintradd(Cycintr *);
-void cycintrdel(Cycintr *);
+void timeradd(Timer *);
+void timerdel(Timer *);
int dmacount(int);
int dmadone(int);
void dmaend(int);
@@ 35,7 35,7 @@ char *getconf(char*);
ulong getfcr(void);
ulong getstatus(void);
void gotopc(ulong);
-int havecycintr(void);
+int havetimer(void);
int i8042auxcmd(int);
void i8042auxenable(void (*)(int, int));
void i8042reset(void);
M bitsy/clock.c => bitsy/clock.c +28 -5
@@ 21,6 21,12 @@ static int clockinited;
static void clockintr(Ureg*, void*);
+enum
+{
+ Minfreq = ClockFreq/HZ, /* At least one interrupt per HZ (10 ms) */
+ Maxfreq = ClockFreq/10000, /* At most one interrupt every 100 µs */
+};
+
void
clockpower(int on)
{
@@ 61,6 67,8 @@ clockinit(void)
/* post interrupt 1/HZ secs from now */
timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
+ timersinit();
+
clockinited = 1;
}
@@ 84,17 92,32 @@ fastticks(uvlong *hz)
return high+x;
}
+void
+timerset(vlong v)
+{
+ ulong when; /* Must be unsigned! */
+
+ if (v == 0LL)
+ when = timerregs->oscr + Minfreq;
+ else {
+ when = v;
+
+ /* post next interrupt: calculate # of tics from now */
+ when = when - timerregs->oscr - Maxfreq;
+ if (when - timerregs->oscr > Minfreq)
+ when = timerregs->oscr + Maxfreq;
+ }
+ timerregs->osmr[0] = when;
+}
+
static void
clockintr(Ureg *ureg, void*)
{
+
/* reset previous interrupt */
timerregs->ossr |= 1<<0;
- /* post interrupt 1/HZ secs from now */
- timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
-
- drawactive(0); /* screen saver */
- portclock(ureg);
+ timerset(timerintr(ureg, nil));
}
void
M bitsy/dat.h => bitsy/dat.h +13 -12
@@ 1,6 1,5 @@
typedef struct Cisdat Cisdat;
typedef struct Conf Conf;
-typedef struct Cycintr Cycintr;
typedef struct FPU FPU;
typedef struct FPenv FPenv;
typedef struct FPsave FPsave;
@@ 17,6 16,7 @@ typedef struct PCMconftab PCMconftab;
typedef struct PhysUart PhysUart;
typedef struct PMMU PMMU;
typedef struct Proc Proc;
+typedef struct Timer Timer;
typedef struct Uart Uart;
typedef struct Ureg Ureg;
typedef struct Vctl Vctl;
@@ 155,17 155,6 @@ struct Mach
};
/*
- * fasttick timer interrupts
- */
-struct Cycintr
-{
- vlong when; /* fastticks when f should be called */
- void (*f)(Ureg*, Cycintr*);
- void *a;
- Cycintr *next;
-};
-
-/*
* Fake kmap since we direct map dram
*/
typedef void KMap;
@@ 273,3 262,15 @@ struct DevConf
ulong interrupt; /* interrupt number */
char *type; /* card type, mallocated */
};
+
+/*
+ * Timer interrupts
+ */
+struct Timer
+{
+ vlong when; /* fastticks when f should be called */
+ vlong period; /* non-zero for recurring periodic timers */
+ void (*f)(Ureg*, Timer*); /* function to call */
+ void *a; /* User parameter */
+ Timer *next;
+};
M bitsy/fns.h => bitsy/fns.h +8 -4
@@ 1,5 1,6 @@
#include "../port/portfns.h"
+void addclock0link(void (*)(void));
void audiopower(int);
void audioamppower(int);
void audioicpower(int);
@@ 7,16 8,14 @@ void cacheflush(void);
void cachewb(void);
void cachewbaddr(void*);
void cachewbregion(ulong, int);
+void clockintrsched(void); /* to be deleted */
void coma(ulong);
void dcacheinvalidate(void);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void clockinit(void);
void clockpower(int);
-void clockintrsched(void);
#define coherence()
-void cycintradd(Cycintr *);
-void cycintrdel(Cycintr *);
#define dcflush(a, b)
void delay(int);
void µdelay(ulong);
@@ 43,7 42,7 @@ void* getlink(void);
ulong getsp(void);
void gpiointrenable(ulong, int, void (*)(Ureg*, void*), void*, char*);
void h3650uartsetup(void);
-int havecycintr(void);
+int havetimer(void);
void icacheinvalidate(void);
void idle(void);
void idlehands(void);
@@ 101,6 100,11 @@ int screenprint(char*, ...); /* debugging */
void serialµcputs(uchar *str, int n);
void setr13(int, ulong*);
uchar* tarlookup(uchar*, char*, int*);
+void timersinit(void);
+void timeradd(Timer*);
+void timerdel(Timer*);
+vlong timerintr(Ureg *, void*);
+void timerset(vlong);
void touser(void*);
void trapdump(char *tag);
void trapinit(void);
M ip/tcp.c => ip/tcp.c +34 -34
@@ 16,9 16,9 @@ enum
TCP_HDRSIZE = 20,
TCP_TCBPHDRSZ = 40,
TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE,
- TimerOFF = 0,
- TimerON = 1,
- TimerDONE = 2,
+ TcptimerOFF = 0,
+ TcptimerON = 1,
+ TcptimerDONE = 2,
MAX_TIME = (1<<20), /* Forever */
TCP_ACK = 200, /* Timed ack sequence in ms */
@@ 73,12 73,12 @@ char *tcpstates[] =
"Closing", "Last_ack", "Time_wait"
};
-typedef struct Timer Timer;
-struct Timer
+typedef struct Tcptimer Tcptimer;
+struct Tcptimer
{
- Timer *next;
- Timer *prev;
- Timer *readynext;
+ Tcptimer *next;
+ Tcptimer *prev;
+ Tcptimer *readynext;
int state;
int start;
int count;
@@ 177,10 177,10 @@ struct Tcpctl
int backedoff; /* ms we've backed off for rexmits */
uchar flags; /* State flags */
Reseq *reseq; /* Resequencing queue */
- Timer timer; /* Activity timer */
- Timer acktimer; /* Acknowledge timer */
- Timer rtt_timer; /* Round trip timer */
- Timer katimer; /* keep alive timer */
+ Tcptimer timer; /* Activity timer */
+ Tcptimer acktimer; /* Acknowledge timer */
+ Tcptimer rtt_timer; /* Round trip timer */
+ Tcptimer katimer; /* keep alive timer */
ulong rttseq; /* Round trip sequence */
int srtt; /* Shortened round trip */
int mdev; /* Mean deviation of round trip */
@@ 241,7 241,7 @@ static char *statnames[] =
typedef struct Tcppriv Tcppriv;
struct Tcppriv
{
- Timer *timers; /* List of active timers */
+ Tcptimer *timers; /* List of active timers */
QLock tl; /* Protect timer list */
Rendez tcpr; /* used by tcpackproc */
@@ 493,10 493,10 @@ tcpcreate(Conv *c)
}
static void
-timerstate(Tcppriv *priv, Timer *t, int newstate)
+timerstate(Tcppriv *priv, Tcptimer *t, int newstate)
{
- if(newstate != TimerON){
- if(t->state == TimerON){
+ if(newstate != TcptimerON){
+ if(t->state == TcptimerON){
// unchain
if(priv->timers == t){
priv->timers = t->next;
@@ 510,7 510,7 @@ timerstate(Tcppriv *priv, Timer *t, int newstate)
t->next = t->prev = nil;
}
} else {
- if(t->state != TimerON){
+ if(t->state != TcptimerON){
// chain
if(t->prev != nil || t->next != nil)
panic("timerstate2");
@@ 527,7 527,7 @@ timerstate(Tcppriv *priv, Timer *t, int newstate)
void
tcpackproc(void *a)
{
- Timer *t, *tp, *timeo;
+ Tcptimer *t, *tp, *timeo;
Proto *tcp;
Tcppriv *priv;
int loop;
@@ 545,10 545,10 @@ tcpackproc(void *a)
if(loop++ > 10000)
panic("tcpackproc1");
tp = t->next;
- if(t->state == TimerON) {
+ if(t->state == TcptimerON) {
t->count--;
if(t->count == 0) {
- timerstate(priv, t, TimerDONE);
+ timerstate(priv, t, TcptimerDONE);
t->readynext = timeo;
timeo = t;
}
@@ 560,7 560,7 @@ tcpackproc(void *a)
for(t = timeo; t != nil; t = t->readynext) {
if(loop++ > 10000)
panic("tcpackproc2");
- if(t->state == TimerDONE && t->func != nil && !waserror()){
+ if(t->state == TcptimerDONE && t->func != nil && !waserror()){
(*t->func)(t->arg);
poperror();
}
@@ 569,25 569,25 @@ tcpackproc(void *a)
}
void
-tcpgo(Tcppriv *priv, Timer *t)
+tcpgo(Tcppriv *priv, Tcptimer *t)
{
if(t == nil || t->start == 0)
return;
qlock(&priv->tl);
t->count = t->start;
- timerstate(priv, t, TimerON);
+ timerstate(priv, t, TcptimerON);
qunlock(&priv->tl);
}
void
-tcphalt(Tcppriv *priv, Timer *t)
+tcphalt(Tcppriv *priv, Tcptimer *t)
{
if(t == nil)
return;
qlock(&priv->tl);
- timerstate(priv, t, TimerOFF);
+ timerstate(priv, t, TcptimerOFF);
qunlock(&priv->tl);
}
@@ 1002,13 1002,13 @@ tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst)
tcb = (Tcpctl*)new->ptcl;
tcb->flags &= ~CLONE;
tcb->timer.arg = new;
- tcb->timer.state = TimerOFF;
+ tcb->timer.state = TcptimerOFF;
tcb->acktimer.arg = new;
- tcb->acktimer.state = TimerOFF;
+ tcb->acktimer.state = TcptimerOFF;
tcb->katimer.arg = new;
- tcb->katimer.state = TimerOFF;
+ tcb->katimer.state = TcptimerOFF;
tcb->rtt_timer.arg = new;
- tcb->rtt_timer.state = TimerOFF;
+ tcb->rtt_timer.state = TcptimerOFF;
h = &tcb->protohdr;
memset(h, 0, sizeof(*h));
@@ 1186,7 1186,7 @@ update(Conv *s, Tcp *seg)
}
/* Adjust the timers according to the round trip time */
- if(tcb->rtt_timer.state == TimerON && seq_ge(seg->ack, tcb->rttseq)) {
+ if(tcb->rtt_timer.state == TcptimerON && seq_ge(seg->ack, tcb->rttseq)) {
tcphalt(tpriv, &tcb->rtt_timer);
if((tcb->flags&RETRAN) == 0) {
tcb->backoff = 0;
@@ 1491,7 1491,7 @@ reset:
}
case Time_wait:
tcb->flags |= FORCE;
- if(tcb->timer.state != TimerON)
+ if(tcb->timer.state != TcptimerON)
tcpgo(tpriv, &tcb->timer);
}
@@ 1548,7 1548,7 @@ reset:
* turn on the acktimer if there's something
* to ack
*/
- if(tcb->acktimer.state != TimerON)
+ if(tcb->acktimer.state != TcptimerON)
tcpgo(tpriv, &tcb->acktimer);
break;
@@ 1792,14 1792,14 @@ tcpoutput(Conv *s)
* expect acknowledges
*/
if(ssize != 0){
- if(tcb->timer.state != TimerON)
+ if(tcb->timer.state != TcptimerON)
tcpgo(tpriv, &tcb->timer);
/* If round trip timer isn't running, start it.
* measure the longest packet only in case the
* transmission time dominates RTT
*/
- if(tcb->rtt_timer.state != TimerON)
+ if(tcb->rtt_timer.state != TcptimerON)
if(ssize == tcb->mss) {
tcpgo(tpriv, &tcb->rtt_timer);
tcb->rttseq = tcb->snd.ptr;
M mtx/cycintr.c => mtx/cycintr.c +3 -3
@@ 6,18 6,18 @@
#include "io.h"
int
-havecycintr(void)
+havetimer(void)
{
return 0;
}
void
-cycintradd(Cycintr *)
+timeradd(Timer *)
{
}
void
-cycintrdel(Cycintr *)
+timerdel(Timer *)
{
}
M mtx/dat.h => mtx/dat.h +4 -4
@@ 1,5 1,5 @@
typedef struct Conf Conf;
-typedef struct Cycintr Cycintr;
+typedef struct Timer Timer;
typedef struct FPsave FPsave;
typedef struct ISAConf ISAConf;
typedef struct Label Label;
@@ 195,12 195,12 @@ struct ISAConf {
/*
* fasttick timer interrupts (Dummy for now)
*/
-struct Cycintr
+struct Timer
{
vlong when; /* fastticks when f should be called */
- void (*f)(Ureg*, Cycintr*);
+ void (*f)(Ureg*, Timer*);
void *a;
- Cycintr *next;
+ Timer *next;
};
#define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG))
M mtx/fns.h => mtx/fns.h +3 -3
@@ 8,8 8,8 @@ void clockinit(void);
void clockintr(Ureg*);
void clockintrsched(void);
#define coherence() eieio()
-void cycintradd(Cycintr *);
-void cycintrdel(Cycintr *);
+void timeradd(Timer *);
+void timerdel(Timer *);
void cpuidentify(void);
void cpuidprint(void);
void dcflush(void*, ulong);
@@ 36,7 36,7 @@ ulong getpvr(void);
ulong gettbl(void);
ulong gettbu(void);
void gotopc(ulong);
-int havecycintr(void);
+int havetimer(void);
void hwintrinit(void);
void i8250console(void);
void i8259init(void);
M pc/archmp.c => pc/archmp.c +1 -0
@@ 102,4 102,5 @@ PCArch archmp = {
0, /* intrdisable */
0, /* clockenable */
+ i8253read, /* fastclock */
};
M pc/clock.c => pc/clock.c +7 -2
@@ 6,11 6,16 @@
#include "io.h"
#include "ureg.h"
+/*
+ * this is called both by the mp's clock interrupt and
+ * by the clockintr0 for the i8253
+ */
+int nclockintr;
void
clockintr(Ureg* ureg, void*)
{
- // this needs to be here for synchronizing mp clocks
- // see pc/mp.c's squidboy()
+nclockintr++;
+ /* this has to get called every tick or the 8253 timer will overflow */
fastticks(nil);
if(m->flushmmu){
M pc/cycintr.c => pc/cycintr.c +27 -27
@@ 9,56 9,56 @@
static struct
{
Lock;
- Cycintr *ci;
-}cycintrs;
+ Timer *ci;
+}timers;
/*
* called by clockintrsched()
*/
vlong
-cycintrnext(void)
+timernext(void)
{
- Cycintr *ci;
+ Timer *ci;
vlong when;
- ilock(&cycintrs);
+ ilock(&timers);
when = 0;
- ci = cycintrs.ci;
+ ci = timers.ci;
if(ci != nil)
when = ci->when;
- iunlock(&cycintrs);
+ iunlock(&timers);
return when;
}
vlong
-checkcycintr(Ureg *u, void*)
+checktimer(Ureg *u, void*)
{
- Cycintr *ci;
+ Timer *ci;
vlong when;
- ilock(&cycintrs);
- while(ci = cycintrs.ci){
+ ilock(&timers);
+ while(ci = timers.ci){
when = ci->when;
if(when > fastticks(nil)){
- iunlock(&cycintrs);
+ iunlock(&timers);
return when;
}
- cycintrs.ci = ci->next;
- iunlock(&cycintrs);
+ timers.ci = ci->next;
+ iunlock(&timers);
(*ci->f)(u, ci);
- ilock(&cycintrs);
+ ilock(&timers);
}
- iunlock(&cycintrs);
+ iunlock(&timers);
return 0;
}
void
-cycintradd(Cycintr *nci)
+timeradd(Timer *nci)
{
- Cycintr *ci, **last;
+ Timer *ci, **last;
- ilock(&cycintrs);
- last = &cycintrs.ci;
+ ilock(&timers);
+ last = &timers.ci;
while(ci = *last){
if(ci == nci){
*last = ci->next;
@@ 67,7 67,7 @@ cycintradd(Cycintr *nci)
last = &ci->next;
}
- last = &cycintrs.ci;
+ last = &timers.ci;
while(ci = *last){
if(ci->when > nci->when)
break;
@@ 75,16 75,16 @@ cycintradd(Cycintr *nci)
}
nci->next = *last;
*last = nci;
- iunlock(&cycintrs);
+ iunlock(&timers);
}
void
-cycintrdel(Cycintr *dci)
+timerdel(Timer *dci)
{
- Cycintr *ci, **last;
+ Timer *ci, **last;
- ilock(&cycintrs);
- last = &cycintrs.ci;
+ ilock(&timers);
+ last = &timers.ci;
while(ci = *last){
if(ci == dci){
*last = ci->next;
@@ 92,5 92,5 @@ cycintrdel(Cycintr *dci)
}
last = &ci->next;
}
- iunlock(&cycintrs);
+ iunlock(&timers);
}
M pc/dat.h => pc/dat.h +6 -5
@@ 1,5 1,5 @@
typedef struct Conf Conf;
-typedef struct Cycintr Cycintr;
+typedef struct Timer Timer;
typedef struct FPsave FPsave;
typedef struct ISAConf ISAConf;
typedef struct Label Label;
@@ 176,7 176,6 @@ struct Mach
int syscall;
int load;
int intr;
- vlong fastclock; /* last sampled value */
vlong intrts; /* time stamp of last interrupt */
int flushmmu; /* make current proc flush it's mmu state */
@@ 191,6 190,8 @@ struct Mach
int cpuiddx;
char cpuidid[16];
char* cpuidtype;
+ int havetsc;
+ vlong lasttsc; /* last sampled value */
vlong mtrrcap;
vlong mtrrdef;
@@ 203,12 204,12 @@ struct Mach
/*
* fasttick timer interrupts
*/
-struct Cycintr
+struct Timer
{
vlong when; /* fastticks when f should be called */
- void (*f)(Ureg*, Cycintr*);
+ void (*f)(Ureg*, Timer*);
void *a;
- Cycintr *next;
+ Timer *next;
};
/*
M pc/devarch.c => pc/devarch.c +27 -37
@@ 489,8 489,6 @@ nop(void)
}
void (*coherence)(void) = nop;
-void cycletimerinit(void);
-uvlong cycletimer(uvlong*);
PCArch* arch;
extern PCArch* knownarch[];
@@ 594,7 592,6 @@ static X86type x86winchip[] =
};
-static uvlong fasthz;
static X86type *cputype;
void
@@ 611,6 608,15 @@ cpuidprint(void)
print(buf);
}
+/*
+ * figure out:
+ * - cpu type
+ * - whether or not we have a TSC (cycle counter)
+ * - whether or not is supports page size extensions
+ * (if so turn it on)
+ * - whether or not is supports machine check exceptions
+ * (if so turn it on)
+ */
int
cpuidentify(void)
{
@@ 637,7 643,18 @@ cpuidentify(void)
t++;
}
m->cpuidtype = t->name;
- i8253init(t->aalcycles, t->family >= 5);
+
+ /*
+ * if there is one, set tsc to a known value
+ */
+ m->havetsc = t->family >= 5;
+ if(m->havetsc)
+ wrmsr(0x10, 0);
+
+ /*
+ * use i8253 to guess our cpu speed
+ */
+ guesscpuhz(t->aalcycles);
/*
* If machine check exception or page size extensions are supported
@@ 703,17 720,12 @@ archinit(void)
arch->serialpower = archgeneric.serialpower;
if(arch->modempower == 0)
arch->modempower = archgeneric.modempower;
-
if(arch->intrinit == 0)
arch->intrinit = archgeneric.intrinit;
if(arch->intrenable == 0)
arch->intrenable = archgeneric.intrenable;
- }
-
- /* pick the better timer */
- if(X86FAMILY(m->cpuidax) >= 5){
- cycletimerinit();
- arch->fastclock = cycletimer;
+ if(arch->intrenable == 0)
+ arch->intrenable = archgeneric.intrenable;
}
/*
@@ 728,40 740,18 @@ archinit(void)
addarchfile("cputype", 0444, cputyperead, nil);
}
-void
-cycletimerinit(void)
-{
- wrmsr(0x10, 0);
- fasthz = m->cpuhz;
-}
-
/*
- * return the most precise clock we have
+ * call either the pcmcia or pccard device setup
*/
-uvlong
-cycletimer(uvlong *hz)
-{
- uvlong tsc;
-
- if(hz != nil)
- *hz = fasthz;
- rdtsc((vlong*)&tsc);
- m->fastclock = tsc;
- return tsc;
-}
-
-vlong
-fastticks(uvlong *hz)
-{
- return (*arch->fastclock)(hz);
-}
-
int
pcmspecial(char *idstr, ISAConf *isa)
{
return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
}
+/*
+ * call either the pcmcia or pccard device teardown
+ */
void
pcmspecialclose(int a)
{
M pc/etherelnk3.c => pc/etherelnk3.c +3 -3
@@ 181,7 181,7 @@ enum { /* Window 1 - operating set */
Fifo = 0x0000,
RxError = 0x0004, /* 3C59[0257] only */
RxStatus = 0x0008,
- Timer = 0x000A,
+ Timerx = 0x000A,
TxStatus = 0x000B,
TxFree = 0x000C,
/* RxError bits */
@@ 999,7 999,7 @@ interrupt(Ureg*, void* arg)
if(ctlr->busmaster == 2)
ctlr->timer[0] += inb(port+Timer905) & 0xFF;
else
- ctlr->timer[0] += inb(port+Timer) & 0xFF;
+ ctlr->timer[0] += inb(port+Timerx) & 0xFF;
do{
if(status & hostError){
@@ 1167,7 1167,7 @@ interrupt(Ureg*, void* arg)
if(ctlr->busmaster == 2)
ctlr->timer[1] += inb(port+Timer905) & 0xFF;
else
- ctlr->timer[1] += inb(port+Timer) & 0xFF;
+ ctlr->timer[1] += inb(port+Timerx) & 0xFF;
COMMAND(port, SelectRegisterWindow, w);
iunlock(&ctlr->wlock);
M pc/fns.h => pc/fns.h +8 -6
@@ 6,7 6,7 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,v
void apicclkenable(void);
void archinit(void);
void bootargs(ulong);
-vlong checkcycintr(Ureg*, void*);
+vlong checktimer(Ureg*, void*);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
#define clearmmucache() /* x86 doesn't have one */
@@ 16,9 16,10 @@ void (*coherence)(void);
void cpuid(char*, int*, int*);
int cpuidentify(void);
void cpuidprint(void);
-void cycintradd(Cycintr*);
-void cycintrdel(Cycintr*);
-vlong cycintrnext(void);
+void timeradd(Timer*);
+void timerdel(Timer*);
+void timerset(vlong);
+vlong timernext(void);
void delay(int);
int dmacount(int);
int dmadone(int);
@@ 37,14 38,15 @@ ulong getcr2(void);
ulong getcr3(void);
ulong getcr4(void);
char* getconf(char*);
+void guesscpuhz(int);
void halt(void);
-int havecycintr(void);
+int havetimer(void);
int i8042auxcmd(int);
void i8042auxenable(void (*)(int, int));
void i8042reset(void);
void i8250console(void);
void* i8250alloc(int, int, int);
-void i8253init(int, int);
+void i8253init(void);
void i8253enable(void);
uvlong i8253read(uvlong*);
void i8259init(void);
M pc/i8253.c => pc/i8253.c +109 -65
@@ 21,6 21,12 @@ enum
Load0l= 0x10, /* load counter 0's lsb */
Load0m= 0x20, /* load counter 0's msb */
Load0= 0x30, /* load counter 0 with 2 bytes */
+
+ 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 */
+
Latch2= 0x80, /* latch counter 2's value */
Load2l= 0x90, /* load counter 2's lsb */
Load2m= 0xa0, /* load counter 2's msb */
@@ 55,51 61,63 @@ enum
static struct
{
Lock;
- int havecyc;
int enabled;
int mode;
vlong when; /* next fastticks a clock interrupt should occur */
- vlong cycwhen; /* next fastticks a cycintr happens; 0 == infinity */
+ vlong timerwhen; /* next fastticks a cycintr happens; 0 == infinity */
long fastperiod; /* fastticks/hz */
long fast2freq; /* fastticks*FreqMul/Freq */
+
+ Lock lock1; /* mutex for the following */
+ ushort last1; /* last value of clock 1 */
+ uvlong ticks1; /* cumulative ticks of counter 1 */
}i8253;
void
-i8253init(int aalcycles, int havecycleclock)
+i8253init(void)
{
- int cpufreq, loops, incr, x, y;
- vlong a, b;
- static int initialised;
+ int loops, x;
- if(initialised == 0){
- initialised = 1;
- i8253.havecyc = havecycleclock;
- ioalloc(T0cntr, 4, 0, "i8253");
- ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
+ ioalloc(T0cntr, 4, 0, "i8253");
+ ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl");
- /*
- * set 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 */
+ /*
+ * 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 */
- /*
- * 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;
- }
+ /*
+ * 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;
}
+}
+
+void
+guesscpuhz(int aalcycles)
+{
+ int cpufreq, loops, incr, x, y;
+ vlong a, b;
/* find biggest loop that doesn't wrap */
incr = 16000000/(aalcycles*HZ*2);
@@ 118,31 136,34 @@ i8253init(int aalcycles, int havecycleclock)
* prefetch buffer.
*
*/
- if(havecycleclock)
- rdtsc(&a);
outb(Tmode, Latch0);
+ if(m->havetsc)
+ rdtsc(&a);
x = inb(T0cntr);
x |= inb(T0cntr)<<8;
aamloop(loops);
- if(havecycleclock)
+ outb(Tmode, Latch0);
+ if(m->havetsc)
rdtsc(&b);
y = inb(T0cntr);
y |= inb(T0cntr)<<8;
x -= y;
-
+
if(x < 0)
x += Freq/HZ;
if(x > Freq/(3*HZ))
break;
}
+
/*
* figure out clock frequency and a loop multiplier for delay().
* n.b. counter goes up by 2*Freq
*/
cpufreq = loops*((aalcycles*2*Freq)/x);
m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */
- if(havecycleclock){
+
+ if(m->havetsc){
/* counter goes up by 2*Freq */
b = (b-a)<<1;
@@ 165,7 186,7 @@ i8253init(int aalcycles, int havecycleclock)
/*
* schedule the next interrupt
- * cycwhen is the next time for the cycle counter routines
+ * timerwhen is the time of the next interrupt
*/
static void
clockintrsched0(vlong next)
@@ 173,7 194,7 @@ clockintrsched0(vlong next)
vlong now;
long set;
- i8253.cycwhen = next;
+ i8253.timerwhen = next;
if(i8253.mode == Square && next == 0)
return;
@@ 201,9 222,9 @@ clockintrsched0(vlong next)
}
int
-havecycintr(void)
+havetimer(void)
{
- return i8253.havecyc && i8253.enabled;
+ return i8253.enabled;
}
void
@@ 212,63 233,86 @@ clockintrsched(void)
vlong next;
ilock(&i8253);
- if(i8253.enabled && i8253.havecyc){
- next = cycintrnext();
- if(next != i8253.cycwhen)
+ if(i8253.enabled){
+ next = timernext();
+ if(next != i8253.timerwhen)
clockintrsched0(next);
}
iunlock(&i8253);
}
+int nclockintr0;
static void
clockintr0(Ureg* ureg, void *v)
{
vlong now, when;
- if(!i8253.havecyc){
- clockintr(ureg, v);
- return;
- }
+nclockintr0++;
+ /* goes with syncing in squidboy */
+ if(m->havetsc)
+ rdtsc(&m->lasttsc);
now = fastticks(nil);
when = i8253.when;
- /*
- * 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;
-
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));
+ if(i8253.timerwhen || i8253.mode != Square)
+ clockintrsched0(checktimer(ureg, v));
}
void
i8253enable(void)
{
- i8253.when = fastticks(nil);
- i8253.fastperiod = (m->cpuhz + HZ/2) / HZ;
- i8253.fast2freq = (vlong)m->cpuhz * FreqMul / Freq;
+ uvlong hz;
+
+ i8253.when = fastticks(&hz);
+ i8253.fastperiod = (hz + HZ/2) / HZ;
+ i8253.fast2freq = (hz * FreqMul) / Freq;
i8253.enabled = 1;
intrenable(IrqCLOCK, clockintr0, 0, BUSUNKNOWN, "clock");
}
/*
- * return time elapsed since clock start in
- * 100 times hz
+ * return the total ticks of counter 1. We shift by
+ * 8 to give timesync more wriggle room for interpretation
+ * of the frequency
*/
uvlong
i8253read(uvlong *hz)
{
+ ushort y, x;
+ uvlong ticks;
+
if(hz)
- *hz = HZ*100;
- return m->ticks*100;
+ *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);
}
M pc/main.c => pc/main.c +1 -0
@@ 80,6 80,7 @@ main(void)
print("\nPlan 9\n");
+ i8253init();
cpuidentify();
screeninit();
meminit();
M pc/mp.c => pc/mp.c +11 -10
@@ 403,16 403,17 @@ squidboy(Apic* apic)
mprdthi |= (1<<apic->apicno)<<24;
unlock(&mprdthilock);
- /*
- * Restrain your octopus! Don't let it go out on the sea!
- */
- ilock(&mpclocksynclock);
- x = MACHP(0)->ticks;
- while(MACHP(0)->ticks == x)
- ;
- wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */
- iunlock(&mpclocksynclock);
-
+ if(m->havetsc){
+ /*
+ * Restrain your octopus! Don't let it go out on the sea!
+ */
+ ilock(&mpclocksynclock);
+ x = MACHP(0)->ticks;
+ while(MACHP(0)->ticks == x)
+ ;
+ wrmsr(0x10, MACHP(0)->lasttsc); /* synchronize fast counters */
+ iunlock(&mpclocksynclock);
+ }
lapicinit(apic);
lapiconline();
M pc/vgavmware.c => pc/vgavmware.c +6 -18
@@ 157,7 157,6 @@ vmwarelinear(VGAscr* scr, int* size, int* align)
oapsize = scr->apsize;
wasupamem = scr->isupamem;
-iprint("osize %d oaperture %.8lux oapsize %d wasupamem %d\n", osize, oaperture, oapsize, wasupamem);
p = pcimatch(nil, PCIVMWARE, 0);
if(p == nil)
error("no vmware card found");
@@ 189,12 188,8 @@ iprint("osize %d oaperture %.8lux oapsize %d wasupamem %d\n", osize, oaperture,
if(wasupamem && upamalloc(oaperture, oapsize, 0))
scr->isupamem = 1;
}else
-{
-memset((void*)KADDR(aperture), 0x7F, 1048576);
scr->isupamem = 1;
-}
-iprint("aperture %lux size %lux\n", aperture, *size);
if(oaperture && aperture != oaperture)
print("warning (BUG): redefinition of aperture does not change vmwarescreen segment\n");
addvgaseg("vmwarescreen", aperture, osize);
@@ 306,14 301,13 @@ vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
{
if(vm->mmio == nil)
return 0;
- vmfifowr(vm, Xrectropcopy);
- vmfifowr(vm, r.max.x);
- vmfifowr(vm, r.max.y);
+ vmfifowr(vm, Xrectcopy);
+ vmfifowr(vm, sr.min.x);
+ vmfifowr(vm, sr.min.y);
vmfifowr(vm, r.min.x);
vmfifowr(vm, r.min.y);
- vmfifowr(vm, sr.min.x - r.min.x);
- vmfifowr(vm, sr.min.y - r.min.y);
- vmfifowr(vm, 3); /* code for copy */
+ vmfifowr(vm, Dx(r));
+ vmfifowr(vm, Dy(r));
vmwait(vm);
return 1;
}
@@ 338,18 332,12 @@ vmwaredrawinit(VGAscr *scr)
{
ulong mmiobase, mmiosize;
-extern int iprintscreenputs;
- iprintscreenputs = 0;
-
if(scr->mmio==nil){
mmiobase = vmrd(vm, Rmemstart);
- if(mmiobase == 0){
- iprint("mmiobase 0\n");
+ if(mmiobase == 0)
return;
- }
mmiosize = vmrd(vm, Rmemsize);
scr->mmio = KADDR(upamalloc(mmiobase, mmiosize, 0));
-iprint("mmio %p\n", scr->mmio);
vm->mmio = scr->mmio;
vm->mmiosize = mmiosize;
if(scr->mmio == nil)
M port/devenv.c => port/devenv.c +23 -24
@@ 27,20 27,19 @@ envgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
}
eg = envgrp(c);
- qlock(eg);
-
+ rlock(eg);
for(e = eg->entries; e && s; e = e->link)
s--;
if(e == 0) {
- qunlock(eg);
+ runlock(eg);
return -1;
}
/* make sure name string continues to exist after we release lock */
kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
- qunlock(eg);
+ runlock(eg);
return 1;
}
@@ 100,10 99,10 @@ envopen(Chan *c, int omode)
else {
if(omode != OREAD && !envwriteable(c))
error(Eperm);
- qlock(eg);
+ rlock(eg);
e = envlookup(eg, nil, c->qid.path);
if(e == 0) {
- qunlock(eg);
+ runlock(eg);
error(Enonexist);
}
if((omode & OTRUNC) && e->value) {
@@ 112,7 111,7 @@ envopen(Chan *c, int omode)
e->value = 0;
e->len = 0;
}
- qunlock(eg);
+ runlock(eg);
}
c->mode = openmode(omode);
c->flag |= COPEN;
@@ 132,9 131,9 @@ envcreate(Chan *c, char *name, int omode, ulong)
omode = openmode(omode);
eg = envgrp(c);
- qlock(eg);
+ wlock(eg);
if(waserror()) {
- qunlock(eg);
+ wunlock(eg);
nexterror();
}
@@ 152,7 151,7 @@ envcreate(Chan *c, char *name, int omode, ulong)
eg->entries = e;
c->qid = e->qid;
- qunlock(eg);
+ wunlock(eg);
poperror();
c->offset = 0;
@@ 170,7 169,7 @@ envremove(Chan *c)
error(Eperm);
eg = envgrp(c);
- qlock(eg);
+ wlock(eg);
l = &eg->entries;
for(e = *l; e; e = e->link) {
if(e->qid.path == c->qid.path)
@@ 179,13 178,13 @@ envremove(Chan *c)
}
if(e == 0) {
- qunlock(eg);
+ wunlock(eg);
error(Enonexist);
}
*l = e->link;
eg->vers++;
- qunlock(eg);
+ wunlock(eg);
free(e->name);
if(e->value)
free(e->value);
@@ 215,10 214,10 @@ envread(Chan *c, void *a, long n, vlong off)
return devdirread(c, a, n, 0, 0, envgen);
eg = envgrp(c);
- qlock(eg);
+ rlock(eg);
e = envlookup(eg, nil, c->qid.path);
if(e == 0) {
- qunlock(eg);
+ rlock(eg);
error(Enonexist);
}
@@ 228,7 227,7 @@ envread(Chan *c, void *a, long n, vlong off)
n = 0;
else
memmove(a, e->value+offset, n);
- qunlock(eg);
+ runlock(eg);
return n;
}
@@ 249,10 248,10 @@ envwrite(Chan *c, void *a, long n, vlong off)
error(Etoobig);
eg = envgrp(c);
- qlock(eg);
+ wlock(eg);
e = envlookup(eg, nil, c->qid.path);
if(e == 0) {
- qunlock(eg);
+ wunlock(eg);
error(Enonexist);
}
@@ 268,7 267,7 @@ envwrite(Chan *c, void *a, long n, vlong off)
memmove(e->value+offset, a, n);
e->qid.vers++;
eg->vers++;
- qunlock(eg);
+ wunlock(eg);
return n;
}
@@ 299,7 298,7 @@ envcpy(Egrp *to, Egrp *from)
Evalue **l, *ne, *e;
l = &to->entries;
- qlock(from);
+ rlock(from);
for(e = from->entries; e; e = e->link) {
ne = smalloc(sizeof(Evalue));
ne->name = smalloc(strlen(e->name)+1);
@@ 313,7 312,7 @@ envcpy(Egrp *to, Egrp *from)
*l = ne;
l = &ne->link;
}
- qunlock(from);
+ runlock(from);
}
void
@@ 375,9 374,9 @@ getconfenv(void)
char *p, *q;
int n;
- qlock(eg);
+ rlock(eg);
if(waserror()) {
- qunlock(eg);
+ runlock(eg);
nexterror();
}
@@ 400,6 399,6 @@ getconfenv(void)
*q = 0;
poperror();
- qunlock(eg);
+ runlock(eg);
return p;
}
M port/devloopback.c => port/devloopback.c +7 -7
@@ 35,7 35,7 @@ struct Link
Queue *oq; /* output queue from other side & packets in the link */
Queue *iq;
- Cycintr ci; /* time to move packets from next packet from oq */
+ Timer ci; /* time to move packets from next packet from oq */
};
struct Loop
@@ 105,7 105,7 @@ static vlong gtime(uchar *p);
static void closelink(Link *link, int dofree);
static void pushlink(Link *link, vlong now);
static void freelb(Loop *lb);
-static void linkintr(Ureg*, Cycintr *ci);
+static void linkintr(Ureg*, Timer *ci);
static void
loopbackinit(void)
@@ 129,7 129,7 @@ loopbackattach(char *spec)
int chan;
int dev;
- if(!havecycintr())
+ if(!havetimer())
error("can't time packets");
dev = 0;
@@ 381,7 381,7 @@ closelink(Link *link, int dofree)
link->tqtail = nil;
link->tout = 0;
link->tin = 0;
- cycintrdel(&link->ci);
+ timerdel(&link->ci);
iunlock(link);
if(iq != nil){
qclose(iq);
@@ 604,7 604,7 @@ looper(Loop *lb)
}
static void
-linkintr(Ureg*, Cycintr *ci)
+linkintr(Ureg*, Timer *ci)
{
Link *link;
@@ 633,7 633,7 @@ pushlink(Link *link, vlong now)
return;
}
- cycintrdel(&link->ci);
+ timerdel(&link->ci);
/*
* put more blocks into the xmit queue
@@ 710,7 710,7 @@ pushlink(Link *link, vlong now)
if(tin){
if(tin < now)
panic("loopback unfinished business");
- cycintradd(&link->ci);
+ timeradd(&link->ci);
}
iunlock(link);
}
M port/devrealtime.c => port/devrealtime.c +3 -3
@@ 224,7 224,7 @@ devrtinit(void)
static Chan *
devrtattach(char *param)
{
- if(havecycintr() == 0)
+ if(havetimer() == 0)
error("no edf on multiprocessors");
return devattach('R', param);
}
@@ 232,7 232,7 @@ devrtattach(char *param)
static Walkqid *
devrtwalk(Chan *c, Chan *nc, char **name, int nname)
{
- if (havecycintr() == 0)
+ if (havetimer() == 0)
error("no edf on multiprocessors");
return devwalk(c, nc, name, nname, nil, 0, schedgen);
}
@@ 267,7 267,7 @@ devrtopen(Chan *c, int mode)
{
Task *t;
- if (havecycintr() == 0)
+ if (havetimer() == 0)
error("no edf on multiprocessors");
switch ((ulong)c->qid.path){
case Qlog:
M port/edf.c => port/edf.c +13 -13
@@ 26,8 26,8 @@ char *edf_statename[] = {
[EdfDeadline] = "Deadline",
};
-static Cycintr cycdeadline; /* Time of next deadline */
-static Cycintr cycrelease; /* Time of next release */
+static Timer cycdeadline; /* Time of next deadline */
+static Timer cycrelease; /* Time of next release */
static int initialized;
static uvlong fasthz;
@@ 70,8 70,8 @@ static void edf_resched(Task *t);
static void setdelta(void);
static void testdelta(Task *thetask);
static char * edf_testschedulability(Task *thetask);
-static void edfreleaseintr(Ureg *, Cycintr *cy);
-static void edfdeadlineintr(Ureg*, Cycintr*);
+static void edfreleaseintr(Ureg *, Timer *cy);
+static void edfdeadlineintr(Ureg*, Timer*);
void
edf_init(void)
@@ 214,11 214,11 @@ edfreleasetimer(void)
return;
DPRINT("edfreleasetimer clock\n");
if (cycrelease.when)
- cycintrdel(&cycrelease);
+ timerdel(&cycrelease);
cycrelease.when = t->r;
if (cycrelease.when <= now)
cycrelease.when = now;
- cycintradd(&cycrelease);
+ timeradd(&cycrelease);
clockintrsched();
}
@@ 271,7 271,7 @@ edfdeadline(Proc *p, SEvent why)
assert(0 && p == nil || nt == t);
}
if (cycdeadline.when){
- cycintrdel(&cycdeadline);
+ timerdel(&cycdeadline);
cycdeadline.when = 0;
clockintrsched();
}
@@ 406,13 406,13 @@ edf_expel(Task *t)
}
static void
-edfreleaseintr(Ureg*, Cycintr*)
+edfreleaseintr(Ureg*, Timer*)
{
Task *t;
DPRINT("%d edfreleaseintr\n", m->machno);
- cycintrdel(&cycrelease);
+ timerdel(&cycrelease);
cycrelease.when = 0;
clockintrsched();
@@ 433,7 433,7 @@ edfreleaseintr(Ureg*, Cycintr*)
}
static void
-edfdeadlineintr(Ureg*, Cycintr*)
+edfdeadlineintr(Ureg*, Timer*)
{
/* Task reached deadline */
@@ 442,7 442,7 @@ edfdeadlineintr(Ureg*, Cycintr*)
DPRINT("%d edfdeadlineintr\n", m->machno);
- cycintrdel(&cycdeadline);
+ timerdel(&cycdeadline);
cycdeadline.when = 0;
clockintrsched();
@@ 743,10 743,10 @@ edf_runproc(void)
iunlock(&edflock);
return p;
}
- cycintrdel(&cycdeadline);
+ timerdel(&cycdeadline);
}
cycdeadline.when = when;
- cycintradd(&cycdeadline);
+ timeradd(&cycdeadline);
clockintrsched();
iunlock(&edflock);
return p;
M port/portdat.h => port/portdat.h +1 -1
@@ 430,7 430,7 @@ struct Rgrp
struct Egrp
{
Ref;
- QLock;
+ RWlock;
Evalue *entries;
ulong path; /* qid.path of next Evalue to be allocated */
ulong vers; /* of Egrp */