M pc/clock.c => pc/clock.c +0 -1
@@ 42,7 42,6 @@ clockintr(Ureg* ureg, void*)
m->ticks++;
if(m->proc)
m->proc->pc = ureg->pc;
- fixtod();
accounttime();
if(kproftimer != nil)
M pc/ether589.c => pc/ether589.c +1 -0
@@ 152,4 152,5 @@ ether589link(void)
{
addethercard("3C589", reset);
addethercard("3C562", reset);
+ addethercard("589E", reset);
}
M pc/etherelnk3.c => pc/etherelnk3.c +13 -2
@@ 1399,11 1399,22 @@ tcm59Xpci(void)
}
}
+static char* tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
static int
tcm5XXpcmcia(Ether* ether)
{
- if(!cistrcmp(ether->type, "3C589") || !cistrcmp(ether->type, "3C562"))
- return ether->port;
+ int i;
+
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ if(!cistrcmp(ether->type, tcmpcmcia[i]))
+ return ether->port;
+ }
return 0;
}
M port/devaudio.c => port/devaudio.c +1 -1
@@ 885,7 885,7 @@ audioclose(Chan *c)
b = audio.filling;
if(b) {
audio.filling = 0;
- memset(b->virt, 0, Bufsize-audio.curcount);
+ memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);
swab(b->virt);
putbuf(&audio.full, b);
}
M port/devcons.c => port/devcons.c +12 -118
@@ 27,6 27,7 @@ static struct
} kbd;
char sysname[NAMELEN];
+vlong fasthz;
static ulong randomread(void*, ulong);
static void randominit(void);
@@ 393,115 394,6 @@ static Dirtab consdir[]={
"user", {Quser}, NAMELEN, 0666,
};
-ulong boottime; /* seconds since epoch at boot */
-
-struct
-{
- Lock;
- vlong hz; /* frequency of fast clock */
- vlong last; /* last reading of fast clock */
- vlong off; /* offset from epoch to last */
- vlong lastns; /* last return value from gettod */
- vlong bias; /* current bias */
- vlong delta; /* amount to add to bias each slow clock tick */
- int n; /* number of times to add in delta */
- int i; /* number of times we've added in delta */
-} tod;
-
-void
-settod(vlong now, vlong delta, int n)
-{
- ilock(&tod);
- tod.last = fastticks(nil);
- tod.off = now;
- tod.delta = delta;
- tod.n = n;
- tod.i = 0;
- iunlock(&tod);
-}
-
-// largest vlong devided by 10, 100, ...
-static vlong vlmax[9] = {
- 9223372036LL,
- 92233720368LL,
- 922337203685LL,
- 9223372036854LL,
- 92233720368547LL,
- 922337203685477LL,
- 9223372036854775LL,
- 92233720368547758LL,
- 922337203685477580LL,
-};
-static vlong vlmult[9] = {
- 1000000000LL,
- 100000000LL,
- 10000000LL,
- 1000000LL,
- 100000LL,
- 10000LL,
- 1000LL,
- 100LL,
- 10LL,
-};
-
-vlong
-gettod(void)
-{
- vlong x;
- int i;
-
- ilock(&tod);
- if(tod.hz == 0)
- x = fastticks((uvlong*)&tod.hz);
- else
- x = fastticks(nil);
- x -= tod.last;
-
- /* convert to nanoseconds */
- for(i = 0; i < 9; i++)
- if(x < vlmax[i]){
- x *= vlmult[i];
- break;
- }
- x /= tod.hz;
- if(i > 0)
- x *= vlmult[9-i];
-
- /* convert to epoch */
- x += tod.off;
-
- /* add in bias */
- x += tod.bias;
-
- if(x < tod.lastns)
- x = tod.lastns;
- tod.lastns = x;
- iunlock(&tod);
-
- return x;
-}
-
-void
-fixtod(void)
-{
- ilock(&tod);
- if(tod.n > tod.i)
- tod.bias += tod.delta;
- iunlock(&tod);
-}
-
-long
-seconds(void)
-{
- vlong x;
- int i;
-
- x = gettod();
- x /= 1000000000LL;
- i = x;
- return i;
-}
-
int
readvlnum(ulong off, char *buf, ulong n, uvlong val, int size)
{
@@ 549,6 441,7 @@ readstr(ulong off, char *buf, ulong n, char *str)
static void
consinit(void)
{
+ todinit();
randominit();
}
@@ 718,8 611,8 @@ consread(Chan *c, void *buf, long n, vlong off)
return n;
case Qfastclock:
- if(tod.hz == 0L)
- ticks = fastticks((uvlong*)&tod.hz);
+ if(fasthz == 0L)
+ ticks = fastticks((uvlong*)&fasthz);
else
ticks = fastticks(nil);
@@ 729,7 622,7 @@ consread(Chan *c, void *buf, long n, vlong off)
if(k+n > 4*NUMSIZE)
n = 4*NUMSIZE - k;
readvlnum(0, tmp, 2*NUMSIZE, ticks, 2*NUMSIZE);
- readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, tod.hz, 2*NUMSIZE);
+ readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, fasthz, 2*NUMSIZE);
memmove(buf, tmp+k, n);
return n;
@@ 758,17 651,17 @@ consread(Chan *c, void *buf, long n, vlong off)
return 0;
case Qnsec:
- x = gettod();
+ x = todget();
return readvlnum((ulong)offset, buf, n, x, 2*NUMSIZE);
case Qmsec:
- x = gettod();
+ x = todget();
x /= 1000000LL;
i = x;
return readnum((ulong)offset, buf, n, i, NUMSIZE);
case Qtime:
- x = gettod();
+ x = todget();
x /= 1000000000LL;
i = x;
return readnum((ulong)offset, buf, n, i, NUMSIZE);
@@ 902,7 795,7 @@ conswrite(Chan *c, void *va, long n, vlong off)
cbuf[n] = 0;
nsec = strtol(cbuf, 0, 0);
nsec *= 1000000000LL;
- settod(nsec, 0, 0);
+ todset(nsec, 0, 0);
break;
case Qfastclock:
@@ 915,7 808,8 @@ conswrite(Chan *c, void *va, long n, vlong off)
f = strtovl(cbuf, 0, 0);
if(f <= 0L)
error(Ebadarg);
- tod.hz = f;
+ fasthz = f;
+ todsetfreq(f);
break;
case Qnsec:
@@ 928,7 822,7 @@ conswrite(Chan *c, void *va, long n, vlong off)
nsec = strtovl(cbuf, &a, 0);
delta = strtovl(a, &a, 0);
n = strtol(a, &a, 0);
- settod(nsec, delta, n);
+ todset(nsec, delta, n);
break;
case Qkey:
M port/devpipe.c => port/devpipe.c +2 -2
@@ 294,7 294,7 @@ pipewrite(Chan *c, void *va, long n, vlong)
/* avoid notes when pipe is a mounted queue */
if((c->flag & CMSG) == 0)
postnote(up, 1, "sys: write on closed pipe", NUser);
- error(Ehungup);
+ nexterror();
}
p = c->aux;
@@ 326,7 326,7 @@ pipebwrite(Chan *c, Block *bp, ulong)
/* avoid notes when pipe is a mounted queue */
if((c->flag & CMSG) == 0)
postnote(up, 1, "sys: write on closed pipe", NUser);
- error(Ehungup);
+ nexterror();
}
p = c->aux;
M port/portfns.h => port/portfns.h +5 -1
@@ 96,7 96,6 @@ int fault(ulong, int);
void fdclose(int, int);
Chan* fdtochan(int, int, int, int);
int fixfault(Segment*, ulong, int, int);
-void fixtod(void);
void flushmmu(void);
void forkchild(Proc*, Ureg*);
void forkret(void);
@@ 296,6 295,11 @@ void srvrecover(Chan*, Chan*);
int swapcount(ulong);
int swapfull(void);
void swapinit(void);
+vlong todget(void);
+void todfix(void);
+void todsetfreq(vlong);
+void todinit(void);
+void todset(vlong, vlong, int);
Block* trimblock(Block*, int, int);
void tsleep(Rendez*, int (*)(void*), void*, int);
void unbreak(Proc*);
M port/qio.c => port/qio.c +7 -5
@@ 65,6 65,8 @@ enum
Hdrspc = 64, /* leave room for high-level headers */
Bdead = 0x51494F42, /* "QIOB" */
+
+ Maxatomic = 32*1024,
};
void
@@ 1092,7 1094,7 @@ qbwrite(Queue *q, Block *b)
}
/*
- * write to a queue. only 128k at a time is atomic.
+ * write to a queue. only Maxatomic bytes at a time is atomic.
*/
int
qwrite(Queue *q, void *vp, int len)
@@ 1107,8 1109,8 @@ qwrite(Queue *q, void *vp, int len)
sofar = 0;
do {
n = len-sofar;
- if(n > 128*1024)
- n = 128*1024;
+ if(n > Maxatomic)
+ n = Maxatomic;
b = allocb(n);
if(waserror()){
@@ 1143,8 1145,8 @@ qiwrite(Queue *q, void *vp, int len)
sofar = 0;
do {
n = len-sofar;
- if(n > 128*1024)
- n = 128*1024;
+ if(n > Maxatomic)
+ n = Maxatomic;
b = allocb(n);
memmove(b->wp, p+sofar, n);
A port/tod.c => port/tod.c +154 -0
@@ 0,0 1,154 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+
+// frequency of the tod clock
+#define TODFREQ 1000000000LL
+
+enum
+{
+ Log2mult= 22, // multiplier should have 22 bits
+ Log2todfreq= 30, // number of significant bits of TODFREQ
+};
+
+static vlong logtab[40];
+
+struct {
+ Lock;
+ int shift; // time = (ticks*multiplier)>>shift
+ vlong multiplier; // ...
+ vlong hz; // frequency of fast clock
+ vlong last; // last reading of fast clock
+ vlong off; // offset from epoch to last
+ vlong lasttime; // last return value from gettod
+ vlong delta; // amount to add to bias each slow clock tick
+ int n; // number of times to add in delta
+ int i; // number of times we've added in delta
+} tod;
+
+int
+log2(vlong x)
+{
+ int i;
+
+ for(i = 0; i < nelem(logtab); i++){
+ if(x < logtab[i])
+ break;
+ }
+ return i+8;
+}
+
+void
+todinit(void)
+{
+ vlong v;
+ int i;
+
+ v = 1LL<<8;
+ for(i = 0; i < nelem(logtab); i++){
+ logtab[i] = v;
+ v <<= 1;
+ }
+ fastticks((uvlong*)&tod.hz);
+ todsetfreq(tod.hz);
+ addclock0link(todfix);
+}
+
+//
+// This routine makes sure that the multiplier has
+// at least Log2mult bits to guarantee that precision.
+//
+void
+todsetfreq(vlong f)
+{
+ // this ensures that the multiplier has 22 bits
+ ilock(&tod);
+ tod.hz = f;
+ tod.shift = Log2mult - Log2todfreq + log2(f);
+ tod.multiplier = (TODFREQ<<tod.shift)/f;
+ iunlock(&tod);
+}
+
+//
+// Set the time of day struct
+//
+void
+todset(vlong t, vlong delta, int n)
+{
+ ilock(&tod);
+ tod.i = tod.n = 0;
+ if(t >= 0){
+ tod.off = t;
+ tod.last = fastticks(nil);
+ tod.lasttime = 0;
+ } else {
+ tod.delta = delta;
+ tod.n = n;
+ }
+ iunlock(&tod);
+}
+
+//
+// get time of day
+//
+vlong
+todget(void)
+{
+ vlong ticks, x, diff;
+
+ ilock(&tod);
+
+ if(tod.hz == 0)
+ ticks = fastticks((uvlong*)&tod.hz);
+ else
+ ticks = fastticks(nil);
+ diff = ticks - tod.last;
+
+ // convert to epoch
+ x = (diff*tod.multiplier)>>tod.shift;
+ x += tod.off;
+
+ // protect against overflows
+ if(diff > (1LL<<(63-Log2mult))){
+ tod.last = ticks;
+ tod.off = x;
+ }
+
+ /* time can't go backwards */
+ if(x < tod.lasttime)
+ x = tod.lasttime;
+ tod.lasttime = x;
+
+ iunlock(&tod);
+ return x;
+}
+
+//
+// called every clock tick
+//
+void
+todfix(void)
+{
+ if((MACHP(0)->ticks % HZ) != 0)
+ return;
+ ilock(&tod);
+ if(tod.n > tod.i++)
+ tod.off += tod.delta;
+ iunlock(&tod);
+}
+
+long
+seconds(void)
+{
+ vlong x;
+ int i;
+
+ x = todget();
+ x /= TODFREQ;
+ i = x;
+ return i;
+}