M pc/clock.c => pc/clock.c +46 -6
@@ 21,6 21,7 @@ enum
* period is the counter period
*/
Freq= 1193182, /* Real clock frequency */
+ FHZ= 1000, /* hertz for fast clock */
};
/*
@@ 60,14 61,12 @@ clock(Ureg *ur)
m->ticks++;
- uartintr0(ur);
-
- if(m->ticks % 50)
- return;
-
checkalarms();
mouseclock();
+ /*
+ * process time accounting
+ */
p = m->proc;
if(p){
p->pc = ur->pc;
@@ 76,15 75,56 @@ clock(Ureg *ur)
}
if(u && p && p->state==Running){
+ /*
+ * preemption
+ */
if(anyready()){
if(p->hasspin)
p->hasspin = 0;
else
sched();
}
- if((ur->cs&0xffff) == UESEL){ /* if was in user mode */
+ /*
+ * notes for processes that might be spinning
+ * in user mode.
+ */
+ if((ur->cs&0xffff) == UESEL){
if(u->nnote)
notify(ur);
}
}
}
+
+/*
+ * a faster (1 MS) clock tick for a non-interrupting serial port or
+ * kernel profiling. m->ticks still increments as usual.
+ */
+void
+fclock(Ureg *ur)
+{
+ static ulong ticks;
+
+ uartintr0(ur); /* poll the serial port */
+ if((ticks++ % (FHZ/HZ)) == 0)
+ clock(ur);
+}
+
+void
+fclockinit(void)
+{
+ int x;
+
+ /*
+ * set vector for clock interrupts
+ */
+ setvec(Clockvec, fclock);
+
+ /*
+ * make clock output a square wave with a 1/FHZ period
+ */
+ x = splhi();
+ outb(Tmode, Load0square);
+ outb(T0cntr, (Freq/FHZ)); /* low byte */
+ outb(T0cntr, (Freq/FHZ)>>8); /* high byte */
+ splx(x);
+}
M pc/devuart.c => pc/devuart.c +53 -52
@@ 1,4 1,4 @@
-#include "u.h"
+
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
@@ 18,9 18,8 @@ enum
*/
Data= 0, /* xmit/rcv buffer */
Iena= 1, /* interrupt enable */
- Ircv= (1<<0), /* interrupt on receive */
- Ixmt= (1<<1), /* interrupt on xmit */
- Istat= 2, /* interrupt flag */
+ Istat= 2, /* interrupt flag (read) */
+ Tctl= 2, /* test control (write) */
Format= 3, /* byte format */
Bits8= (3<<0), /* 8 bits/byte */
Stop2= (1<<2), /* 2 stop bits */
@@ 42,6 41,9 @@ enum
Scratch=7, /* scratchpad */
Dlsb= 0, /* divisor lsb */
Dmsb= 1, /* divisor msb */
+
+ Serial= 0,
+ Modem= 1,
};
typedef struct Uart Uart;
@@ 62,7 64,6 @@ struct Uart
Queue *wq; /* write queue */
Rendez r; /* kproc waiting for input */
Alarm *a; /* alarm for waking the kernel process */
- int delay; /* between character input and waking kproc */
int kstarted; /* kproc started */
uchar delim[256/8]; /* characters that act as delimiters */
};
@@ 248,7 249,8 @@ uartintr0(Ureg *ur)
void
uartintr1(Ureg *ur)
{
- uartintr(&uart[1]);
+ if(uart[1].enabled)
+ uartintr(&uart[1]);
}
/*
@@ 262,36 264,42 @@ uartenable(Uart *up)
/*
* turn on power to the port
*/
- if(up == &uart[0]){
+ if(up == &uart[Serial]){
if(serial(0) < 0)
print("can't turn on serial port power\n");
}
/*
+ * speed up the clock to poll the uart
+ */
+ fclockinit();
+
+ /*
* set up i/o routines
*/
if(up->oq){
up->oq->puts = uartputs;
up->oq->ptr = up;
- up->sticky[Iena] |= Ixmt;
}
if(up->iq){
up->iq->ptr = up;
- up->sticky[Iena] |= Ircv;
}
up->enabled = 1;
- up->sticky[Iena] |= (1<<2) | (1<<3);
+ up->sticky[Iena] = 0xf;
/*
* turn on interrupts
*/
uartwrreg(up, Iena, 0);
+ uartwrreg(up, Tctl, 0x0);
/*
* turn on DTR and RTS
*/
uartdtr(up, 1);
uartrts(up, 1);
+
+print("uart enabled: Iena=%lux\n", uartrdreg(up, Iena));
}
/*
@@ 316,10 324,15 @@ uartdisable(Uart *up)
/*
* turn off power
*/
- if(up == &uart[0]){
+ if(up == &uart[Serial]){
if(serial(1) < 0)
print("can't turn off serial power\n");
}
+
+ /*
+ * slow the clock down again
+ */
+ clockinit();
}
/*
@@ 374,25 387,6 @@ uarttimer(Alarm *a)
wakeup(&up->iq->r);
}
-static int
-uartputc(IOQ *cq, int ch)
-{
- Uart *up = cq->ptr; int r;
-
- r = putc(cq, ch);
-
- /*
- * pass upstream within up->delay milliseconds
- */
- if(up->a==0){
- if(up->delay == 0)
- wakeup(&cq->r);
- else
- up->a = alarm(up->delay, uarttimer, up);
- }
- return r;
-}
-
static void
uartstopen(Queue *q, Stream *s)
{
@@ 403,18 397,17 @@ print("uartstopen: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n",
q, s->inuse, s->type, s->dev, s->id);
up = &uart[s->id];
+ up->iq->putc = 0;
uartenable(up);
qlock(up);
up->wq = WR(q);
WR(q)->ptr = up;
RD(q)->ptr = up;
- up->delay = 64;
- up->iq->putc = uartputc;
qunlock(up);
/* start with all characters as delimiters */
- memset(up->delim, 1, sizeof(up->delim));
+ memset(up->delim, 0xff, sizeof(up->delim));
if(up->kstarted == 0){
up->kstarted = 1;
@@ 468,6 461,18 @@ uartoput(Queue *q, Block *bp)
case 'd':
uartdtr(up, n);
break;
+ case 'e':
+ case 'E':
+ /*
+ * the characters in the block are the message
+ * delimiters to use upstream
+ */
+ memset(up->delim, 0, sizeof(up->delim));
+ while(++(bp->rptr) < bp->wptr){
+ m = *bp->rptr;
+ up->delim[m/8] |= 1<<(m&7);
+ }
+ break;
case 'K':
case 'k':
uartbreak(up, n);
@@ 476,15 481,9 @@ uartoput(Queue *q, Block *bp)
case 'r':
uartrts(up, n);
break;
- case 'W':
- case 'w':
- if(n>=0 && n<1000)
- up->delay = n;
- break;
}
}else while((m = BLEN(bp)) > 0){
while ((n = canputc(cq)) == 0){
-print("uartoput: sleeping\n");
sleep(&cq->r, canputc, cq);
}
if(n > m)
@@ 507,21 506,23 @@ uartkproc(void *a)
Block *bp;
int n;
-loop:
- while ((n = cangetc(cq)) == 0){
+ if(waserror())
+ print("uartkproc got an error\n");
+
+ for(;;){
sleep(&cq->r, cangetc, cq);
+ qlock(up);
+ if(up->wq == 0){
+ cq->out = cq->in;
+ }else{
+ n = cangetc(cq);
+ bp = allocb(n);
+ bp->flags |= S_DELIM;
+ bp->wptr += gets(cq, bp->wptr, n);
+ PUTNEXT(RD(up->wq), bp);
+ }
+ qunlock(up);
}
- qlock(up);
- if(up->wq == 0){
- cq->out = cq->in;
- }else{
- bp = allocb(n);
- bp->flags |= S_DELIM;
- bp->wptr += gets(cq, bp->wptr, n);
- PUTNEXT(RD(up->wq), bp);
- }
- qunlock(up);
- goto loop;
}
enum{
M pc/fault386.c => pc/fault386.c +1 -1
@@ 35,7 35,7 @@ fault386(Ureg *ur)
}
u->p->state = MMUing;
dumpregs(ur);
- panic("fault: 0x%lux 0x%lux", addr);
+ panic("fault: 0x%lux", addr);
}
faulting = 0;
u->p->insyscall = insyscall;
M pc/fns.h => pc/fns.h +6 -0
@@ 4,12 4,15 @@ void a20enable(void);
#define clearmmucache() /* 386 doesn't have one */
void clock(Ureg*);
void clockinit(void);
+void config(int);
void delay(int);
void dmaend(int);
long dmasetup(int, void*, long, int);
#define evenaddr(x) /* 386 doesn't care */
void fault386(Ureg*);
void faultinit(void);
+void fclock(Ureg*);
+void fclockinit(void);
#define flushvirt();
void fpsave(FPsave*);
void fprestore(FPsave*);
@@ 20,8 23,10 @@ int inss(int, void*, int);
int outss(int, void*, int);
void kbdinit(void);
void kbdintr(Ureg*);
+int mail(int);
void mmuinit(void);
void outb(int, int);
+int owl(int);
void prhex(ulong);
void procrestore(Proc*, uchar*);
void procsave(uchar*, int);
@@ 39,5 44,6 @@ void systrap(void);
void touser(void);
void trapinit(void);
int tas(Lock*);
+void uartintr0(Ureg*);
void vgainit(void);
#define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
M pc/main.c => pc/main.c +0 -8
@@ 373,14 373,6 @@ pmuwrbit(int index, int bit, int pos)
int
serial(int onoff)
{
- int x;
-
- /*
- * set config (enable everything)
- */
- x = splhi();
- config(0x00);
- splx(x);
return pmuwrbit(1, onoff, 6);
}
M pc/mem.h => pc/mem.h +1 -1
@@ 18,7 18,7 @@
/*
* Time
*/
-#define HZ (1000) /* clock frequency */
+#define HZ (20) /* clock frequency */
#define MS2HZ (1000/HZ) /* millisec per clock tick */
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
M pc/trap.c => pc/trap.c +7 -3
@@ 34,8 34,8 @@ enum
EOI= 0x20, /* non-specific end of interrupt */
};
-int int0mask = 0xff; /* interrupts enabled for first 8259 */
-int int1mask = 0xff; /* interrupts enabled for second 8259 */
+int int0mask = 0x00; /* interrupts enabled for first 8259 */
+int int1mask = 0x00; /* interrupts enabled for second 8259 */
/*
* trap/interrupt gates
@@ 231,7 231,7 @@ dumpregs(Ureg *ur)
else
print("registers for kernel\n");
print("FLAGS=%lux ECODE=%lux CS=%lux PC=%lux SS=%lux USP=%lux\n", ur->flags,
- ur->ecode, ur->cs, ur->pc, ur->ss, ur->usp);
+ ur->ecode, ur->cs&0xff, ur->pc, ur->ss&0xff, ur->usp);
print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
ur->ax, ur->bx, ur->cx, ur->dx);
@@ 286,7 286,11 @@ syscall(Ureg *ur)
}
if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
+ if(ax == EXITS)
+ print("%d exiting\n", u->p->pid);
ret = (*systab[ax])((ulong*)(sp+BY2WD));
+ if(ax == EXITS)
+ print("%d returned from sysexits!\n", u->p->pid);
poperror();
}
if(u->nerrlab){
M port/devcons.c => port/devcons.c +9 -0
@@ 44,7 44,14 @@ putstrn(char *str, int n)
{
int s, c, m;
char *t;
+static Lock fuck;
+loop:
+s = splhi();
+if(!canlock(&fuck)){
+ splx(s);
+ goto loop;
+}
while(n > 0){
if(printq.puts && *str=='\n')
(*printq.puts)(&printq, "\r", 1);
@@ 59,6 66,8 @@ putstrn(char *str, int n)
n -= m;
str += m;
}
+unlock(&fuck);
+splx(s);
}
/*
M port/devmnt.c => port/devmnt.c +15 -4
@@ 124,7 124,10 @@ loop:
lock(&mnthdralloc);
if(mh = mnthdralloc.free){ /* assign = */
mnthdralloc.free = mh->next;
- mh->flushing = 0;
+if(mh->active) print("mh->active\n");
+if(mh->flushing) print("mh->flushing\n");
+if(mh->mbr) print("mh->mbr\n");
+ mh->mbr = 0;
unlock(&mnthdralloc);
return mh;
}
@@ 619,8 622,10 @@ mntflush(Mnt *m, Mnthdr *omh) /* queue is unlocked */
{
Mnthdr *mh;
- if(omh->thdr.type == Tflush)
+ if(omh->thdr.type == Tflush){
+ omh->flushing = 0;
return;
+ }
mh = mhalloc();
if(waserror()){
@@ 680,8 685,10 @@ mntxmit(Mnt *m, Mnthdr *mh)
mh->mbr = 0;
mbw = mballoc();
if(waserror()){ /* 1 */
- if(mh->mbr)
+ if(mh->mbr){
mbfree(mh->mbr);
+ mh->mbr = 0;
+ }
mbfree(mbw);
nexterror();
}
@@ 780,6 787,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
qunlock(q);
qlocked = 0;
if(waserror()){ /* 3 */
+print("%d interrupted read %lux %lux\n", u->p->pid, mh, mh->mbr);
mnterrdequeue(m, mh);
nexterror();
}
@@ 789,7 797,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
}while(n == 0);
poperror(); /* 3 */
if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
-print("POO bad len %d %ux!\n", n, mh->mbr->buf[0]);
+print("%d POO bad len %d %ux %lux %lux\n", u->p->pid, n, mh->mbr->buf[0], mh, mh->mbr);
mnterrdequeue(m, mh);
error(Ebadmsg);
}
@@ 845,7 853,9 @@ print("POO bad len %d %ux!\n", n, mh->mbr->buf[0]);
qunlock(q);
qlocked = 0;
if(waserror()){ /* interrupted sleep */
+print("%d interrupted queued sleep %lux %lux %d %d\n", u->p->pid, mh, mh->mbr, mh->active, mh->flushing);
mnterrdequeue(m, mh);
+print("%d after flush sleep %lux %lux %d %d\n", u->p->pid, mh, mh->mbr, mh->active, mh->flushing);
nexterror();
}
sleep(&mh->r, mntreadreply, mh);
@@ 885,6 895,7 @@ print("POO bad len %d %ux!\n", n, mh->mbr->buf[0]);
memmove(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
}
mbfree(mh->mbr);
+ mh->mbr = 0;
mbfree(mbw);
USED(qlocked);
poperror(); /* 1 */
M port/queue.c => port/queue.c +37 -46
@@ 18,15 18,16 @@ initq(IOQ *q)
int
putc(IOQ *q, int c)
{
- uchar *nextin;
- if(q->in >= &q->buf[sizeof(q->buf)-1])
- nextin = q->buf;
+ uchar *next;
+
+ if(q->in == &q->buf[NQ-1])
+ next = q->buf;
else
- nextin = q->in+1;
- if(nextin == q->out)
+ next = q->in+1;
+ if(next == q->out)
return -1;
*q->in = c;
- q->in = nextin;
+ q->in = next;
return 0;
}
@@ 38,7 39,7 @@ getc(IOQ *q)
if(q->in == q->out)
return -1;
c = *q->out;
- if(q->out == q->buf+sizeof(q->buf)-1)
+ if(q->out == &q->buf[NQ-1])
q->out = q->buf;
else
q->out++;
@@ 48,60 49,44 @@ getc(IOQ *q)
void
puts(IOQ *q, void *buf, int n)
{
- int m; uchar *nextin;
- uchar *s = buf;
+ uchar *next;
+ uchar *p = buf;
- while(n){
- m = q->out - q->in - 1;
- if(m < 0)
- m = &q->buf[NQ] - q->in;
- if(m == 0)
- break;
- if(m > n)
- m = n;
- memmove(q->in, s, m);
- n -= m;
- s += m;
- nextin = q->in + m;
- if(nextin >= &q->buf[NQ])
- q->in = q->buf;
+ for(; n; n--){
+ if(q->in == &q->buf[NQ-1])
+ next = q->buf;
else
- q->in = nextin;
+ next = q->in + 1;
+ if(next == q->out)
+ break;
+ *q->in = *p++;
+ q->in = next;
}
}
int
gets(IOQ *q, void *buf, int n)
{
- int m, k = 0; uchar *nextout;
- uchar *s = buf;
+ uchar *p = buf;
- while(n){
- m = q->in - q->out;
- if(m < 0)
- m = &q->buf[NQ] - q->out;
- if(m == 0)
- return k;
- if(m > n)
- m = n;
- memmove(s, q->out, m);
- s += m;
- k += m;
- n -= m;
- nextout = q->out + m;
- if(nextout >= &q->buf[NQ])
+ for(; n && q->out != q->in; n--){
+ *p++ = *q->out;
+ if(q->out == &q->buf[NQ-1])
q->out = q->buf;
else
- q->out = nextout;
+ q->out++;
}
- return k;
+ return p - (uchar*)buf;
}
int
cangetc(void *arg)
{
- IOQ *q = (IOQ *)arg;
- int n = q->in - q->out;
+ IOQ *q;
+ int n;
+
+ q = (IOQ *)arg;
+ n = q->in - q->out;
if (n < 0)
n += sizeof(q->buf);
return n;
@@ 110,6 95,12 @@ cangetc(void *arg)
int
canputc(void *arg)
{
- IOQ *q = (IOQ *)arg;
- return sizeof(q->buf)-cangetc(q)-1;
+ IOQ *q;
+ int n;
+
+ q = (IOQ *)arg;
+ n = q->out - q->in - 1;
+ if (n < 0)
+ n += sizeof(q->buf);
+ return n;
}
M port/sysproc.c => port/sysproc.c +14 -12
@@ 21,7 21,7 @@ sysr1(ulong *arg)
long
sysfork(ulong *arg)
{
- return rfork(Forkfd|Forkeg|Forkpg);
+ return rfork(Forkfd);
}
/* This call will obsolete fork */
@@ 76,28 76,28 @@ rfork(ulong flag)
if(flag & Forkfd)
p->fgrp = dupfgrp(u->p->fgrp);
- else {
+ else{
p->fgrp = u->p->fgrp;
incref(p->fgrp);
}
if(flag & Forkpg) {
- p->pgrp = u->p->pgrp; /* Process groups */
- incref(p->pgrp);
- }
- else {
p->pgrp = newpgrp();
pgrpcpy(p->pgrp, u->p->pgrp);
}
+ else {
+ p->pgrp = u->p->pgrp; /* Process groups */
+ incref(p->pgrp);
+ }
if(flag & Forkeg) {
- p->egrp = u->p->egrp; /* Environment group */
- incref(p->egrp);
- }
- else {
p->egrp = newegrp();
envcpy(p->egrp, u->p->egrp);
}
+ else {
+ p->egrp = u->p->egrp; /* Environment group */
+ incref(p->egrp);
+ }
/*
* Sched
@@ 406,14 406,16 @@ long
sysexits(ulong *arg)
{
char *status;
+ char *inval = "invalid exit string";
status = (char*)arg[0];
if(status){
if(waserror())
- status = "invalid exit string";
+ status = inval;
else{
validaddr((ulong)status, 1, 0);
- vmemchr(status, 0, ERRLEN);
+ if(vmemchr(status, 0, ERRLEN) == 0)
+ status = inval;
}
poperror();
M power/devhotrod.c => power/devhotrod.c +1 -5
@@ 21,12 21,11 @@ ulong testbuf[NTESTBUF];
/*
* If defined, ENABBUSTEST causes bus error diagnostic to be run at device open
*/
-#define ENABBUSTEST
/*
* If 1, ENABCKSUM causes data transfers to have checksums
*/
-#define ENABCKSUM 1
+#define ENABCKSUM 0
typedef struct Hotrod Hotrod;
@@ 72,14 71,11 @@ hotsend(Hotrod *h, Hotmsg *m)
lock(h);
mp = (Hotmsg**)&h->addr->reqstq[h->wi];
-print("send 1 %lux\n", MP2VME(m)); delay(500);
*mp = (Hotmsg*)MP2VME(m);
-print("send 2\n"); delay(500);
h->wi++;
if(h->wi >= NRQ)
h->wi = 0;
unlock(h);
-print("send 3\n"); delay(500);
return mp;
}