M gnot/dat.h => gnot/dat.h +3 -3
@@ 106,10 106,10 @@ struct Chan
struct FPsave
{
- char type;
- char size;
+ uchar type;
+ uchar size;
short reserved;
- char junk[180];
+ char junk[212]; /* 68881: sizes 24, 180; 68882: 56, 212 */
char reg[3*4+8*12];
};
M gnot/devcons.c => gnot/devcons.c +53 -43
@@ 357,12 357,12 @@ enum{
Qpid,
Qppid,
Qrcons,
- Qrs232ctl,
Qtime,
Quser,
Qklog,
Qmsec,
Qclock,
+ Qrs232ctl = STREAMQID(1, Sctlqid),
Qrs232 = STREAMQID(1, Sdataqid),
};
@@ 479,14 479,17 @@ consopen(Chan *c, int omode)
{
int ch;
- if(c->qid==Quser && omode==(OWRITE|OTRUNC)){
- /* truncate? */
- if(strcmp(u->p->pgrp->user, "bootes") == 0) /* BUG */
- u->p->pgrp->user[0] = 0;
- else
- error(0, Eperm);
- }
- if(c->qid == Qrcons)
+ switch(c->qid){
+ case Quser:
+ if(omode==(OWRITE|OTRUNC)){
+ /* truncate? */
+ if(strcmp(u->p->pgrp->user, "bootes") == 0) /* BUG */
+ u->p->pgrp->user[0] = 0;
+ else
+ error(0, Eperm);
+ }
+ break;
+ case Qrcons:
if(incref(&raw) == 1){
lock(&lineq);
while((ch=getc(&kbdq)) != -1){
@@ 496,8 499,12 @@ consopen(Chan *c, int omode)
}
unlock(&lineq);
}
- if(c->qid == Qrs232)
+ break;
+ case Qrs232:
+ case Qrs232ctl:
streamopen(c, &rs232info);
+ break;
+ }
return devopen(c, omode, consdir, NCONS, consgen);
}
@@ 688,31 695,8 @@ conswrite(Chan *c, void *va, long n)
break;
case Qrs232:
- n = streamwrite(c, va, n, 1);
- break;
-
case Qrs232ctl:
- qlock(&rs232);
- if(waserror()){
- qunlock(&rs232);
- nexterror();
- }
- if(n<=2 || n>=sizeof buf)
- error(0, Ebadarg);
- strncpy(buf, a, n);
- buf[n] = 0;
- l = strtoul(buf+1, 0, 0);
- switch(buf[0]){
- case 'B':
- duartbaud(l); break;
- case 'D':
- duartdtr(l); break;
- case 'K':
- duartbreak(l); break;
- default:
- error(0, Ebadarg);
- }
- qunlock(&rs232);
+ n = streamwrite(c, va, n, 1);
break;
case Qtime:
@@ 776,32 760,58 @@ consuserstr(Error *e, char *buf)
/*
* rs232 stream routines
+ *
+ * A kernel process, rs232kproc, stages blocks to be output and
+ * packages input bytes into stream blocks to send upstream.
+ * The process is awakened whenever the interrupt side is almost
+ * out of bytes to xmit or 1/16 second has elapsed since a byte
+ * was input.
*/
+static int
+rs232empty(void *a)
+{
+ Rs232 *r;
+
+ r = a;
+ return r->out.w == r->out.r;
+}
+
static void
rs232output(Rs232 *r)
{
int next;
Queue *q;
Block *bp;
+ long l;
qlock(&r->outlock);
q = r->wq;
/*
- * free emptied blocks
- */
- for(; r->out.f != r->out.r; r->out.f = NEXT(r->out.f)){
- freeb(r->out.bp[r->out.f]);
- r->out.bp[r->out.f] = 0;
- }
-
- /*
* stage new blocks
+ *
+ * if we run into a control block, wait till the queue
+ * is empty before doing the control.
*/
- for(next = NEXT(r->out.w); next!=r->out.r; next = NEXT(next)){
+ for(next = NEXT(r->out.w); next != r->out.r; next = NEXT(next)){
bp = getq(q);
if(bp == 0)
break;
+ if(bp->type == M_CTL){
+ while(!rs232empty(r))
+ sleep(&r->r, rs232empty, r);
+ l = strtoul((char *)(bp->rptr+1), 0, 0);
+ switch(*bp->rptr){
+ case 'B':
+ duartbaud(l); break;
+ case 'D':
+ duartdtr(l); break;
+ case 'K':
+ duartbreak(l); break;
+ }
+ freeb(bp);
+ break;
+ }
r->out.bp[r->out.w] = bp;
r->out.w = next;
}
M gnot/devdk.c => gnot/devdk.c +3 -5
@@ 397,7 397,8 @@ dkiput(Queue *q, Block *bp)
/*
* we assume that each put is a message.
*
- * add a 2 byte channel number to the start of each message
+ * add a 2 byte channel number to the start of each message,
+ * low order byte first.
*/
static void
dkoput(Queue *q, Block *bp)
@@ 415,10 416,7 @@ dkoput(Queue *q, Block *bp)
dp = lp->dp;
line = lp - dp->line;
- if(bp->base && bp->rptr - bp->base >= 2)
- bp->rptr -= 2;
- else
- panic("dkoput");
+ bp = padb(bp, 2);
bp->rptr[0] = line;
bp->rptr[1] = line>>8;
M gnot/fns.h => gnot/fns.h +1 -0
@@ 106,6 106,7 @@ char *nextelem(char*, char*);
void notify(Ureg*);
void nullput(Queue*, Block*);
int openmode(ulong);
+Block* padb(Block*, int);
void pageinit(void);
void panic(char*, ...);
void pexit(char*, int);
M gnot/main.c => gnot/main.c +1 -2
@@ 59,14 59,13 @@ void
machinit(void)
{
int n;
- long fpnull = 0;
n = m->machno;
memset(m, 0, sizeof(Mach));
m->machno = n;
m->mmask = 1<<m->machno;
m->fpstate = FPinit;
- fprestore((FPsave*)&fpnull);
+ fprestore(&initfp);
}
void
M gnot/proc.c => gnot/proc.c +4 -4
@@ 5,7 5,7 @@
#include "fns.h"
#include "errno.h"
-#include <balu.h>
+#include <gnot.h>
struct
{
@@ 79,8 79,6 @@ sched(void)
{
Proc *p;
ulong tlbvirt, tlbphys;
- void (*f)(ulong);
- long fpnull = 0;
Balu balu;
if(u){
@@ 88,6 86,8 @@ sched(void)
fpsave(&u->fpsave);
if(u->fpsave.type){
+ if(u->fpsave.size > sizeof u->fpsave.junk)
+ panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk);
fpregsave(u->fpsave.reg);
u->p->fpstate = FPactive;
m->fpstate = FPdirty;
@@ 107,7 107,7 @@ if(u->p->mach)panic("mach non zero");
if(p->fpstate != m->fpstate){
if(p->fpstate == FPinit){
u->p->fpstate = FPinit;
- fprestore((FPsave*)&fpnull);
+ fprestore(&initfp);
m->fpstate = FPinit;
}else{
fpregrestore(u->fpsave.reg);
A gnot/stasync.c => gnot/stasync.c +432 -0
@@ 0,0 1,432 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "errno.h"
+
+#define DPRINT if(asyncdebug)kprint
+
+typedef struct Async {
+ QLock;
+
+ int inuse;
+ QLock xmit; /* transmit lock */
+ int chan; /* current urp channel */
+ Block *bp; /* current buffer */
+ int count;
+ ushort crc;
+
+ /* statistics */
+
+ ulong toolong;
+ ulong tooshort;
+ ulong badcrc;
+ ulong badescape;
+ ulong in; /* bytes in */
+ ulong out; /* bytes out */
+} Async;
+
+Async async[Nasync];
+
+/*
+ * async stream module definition
+ */
+static void asynciput(Queue*, Block*);
+static void asyncoput(Queue*, Block*);
+static void asyncopen(Queue*, Stream*);
+static void asyncclose(Queue*);
+Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async" };
+
+int asyncdebug = 1;
+int asyncerror;
+
+static ushort crc_table[256] = {
+#include "crc_16.h"
+};
+
+#define BOT 0050 /* begin trailer */
+#define BOTM 0051 /* begin trailer, more data follows */
+#define BOTS 0052 /* seq update alg. on this trailer */
+
+#define MAXFRAME 256
+#define FRAME 0x7e
+#define STUF 0x9d
+
+#define CRCSTART (crc_table[0xff])
+#define CRCFUNC(crc,x) (crc_table[((crc)^(x))&0xff]^((crc)>>8))
+
+/*
+ * create the kernel process for input
+ */
+static void
+asyncopen(Queue *q, Stream *s)
+{
+ DPRINT("asyncstopen %d\n", s->dev);
+
+ for(ap = async; ap < &async[Nasync]; ap++){
+ qlock(ap);
+ if(ap->inuse == 0)
+ break;
+ qunlock(ap);
+ }
+ if(ap == &async[Nasync])
+ error(0, Enoasync);
+ q->ptr = q->other->ptr = ap;
+
+ ap->bp = allocb(256);
+ ap->chan = -1;
+ ap->count = 0;
+ ap->toolong = 0;
+ ap->tooshort = 0;
+ ap->badcrc = 0;
+ ap->badescape = 0;
+ ap->chan0 = 0;
+ ap->in = 0;
+ ap->out = 0;
+}
+
+static void
+asyncclose(Queue * q)
+{
+ Async *ap = (Async *)q->ptr;
+
+ DPRINT("asyncstclose %d\n", ap-async);
+ qlock(ap);
+ ap->inuse = 0;
+ qunlock(ap);
+}
+
+/*
+ * free all blocks of a message in `q', `bp' is the first block
+ * of the message
+ */
+static void
+freemsg(Queue *q, Block *bp)
+{
+ for(; bp; bp = getq(q)){
+ if(bp->flags & S_DELIM){
+ freeb(bp);
+ return;
+ }
+ freeb(bp);
+ }
+}
+
+static void
+showframe(char *t, Async *ap, uchar *buf, int n)
+{
+ kprint("a%d %s [", ap-async, t);
+ while (--n >= 0)
+ kprint(" %2.2ux", *buf++);
+ kprint(" ]\n");
+}
+
+void
+aswrite(Async *ap)
+{
+ int n = ap->bp - ap->buf;
+ if (n <= 0)
+ return;
+ if (asyncdebug > 2)
+ showframe("out", ap, ap->buf, n);
+ (*devtab[ap->c->type].write)(ap->c, ap->buf, n);
+ ap->out += n;
+ ap->bp = ap->buf;
+}
+
+void
+asputf(Async *ap, int frame)
+{
+ uchar *p = ap->bp;
+ int c;
+ if (ap->count > 0) {
+ if (asyncerror)
+ ap->crc^=1, asyncerror=0;
+ *p++ = c = ap->crc&0xff;
+ if (c == FRAME)
+ *p++ = 0x00;
+ *p++ = c = (ap->crc>>8)&0xff;
+ if (c == FRAME)
+ *p++ = 0x00;
+ ap->count = 0;
+ }
+ if (frame) {
+ *p++ = FRAME;
+ *p++ = FRAME;
+ }
+ ap->bp = p;
+ aswrite(ap);
+}
+
+void
+asputc(Async *ap, int c)
+{
+ int d;
+ uchar *p = ap->bp;
+ if (ap->count <= 0) {
+ *p++ = FRAME;
+ *p++ = FRAME;
+ *p++ = d = 0x80|((ap->chan>>5)&0x7e);
+ ap->crc = CRCFUNC(CRCSTART, d);
+ *p++ = d = 0x80|((ap->chan<<1)&0x7e);
+ ap->crc = CRCFUNC(ap->crc, d);
+ }
+ *p++ = c;
+ if (c == FRAME)
+ *p++ = 0x00;
+ ap->crc = CRCFUNC(ap->crc, c);
+ ap->bp = p;
+ if (++ap->count >= MAXFRAME-4)
+ asputf(ap, 0);
+ else if (p-ap->buf >= sizeof(ap->buf)-8)
+ aswrite(ap);
+}
+
+/*
+ * output a block
+ *
+ * the first 2 bytes of every message are the channel number,
+ * low order byte first. the third is a possible trailing control
+ * character.
+ */
+void
+asyncoput(Queue *q, Block *bp)
+{
+ Async *ap = (Async *)q->ptr;
+ int c, chan, ctl;
+
+ if(bp->type != M_DATA){
+ freeb(bp);
+ return;
+ }
+
+ /*
+ * get a whole message before handing bytes to the device
+ */
+ if(!putq(q, bp))
+ return;
+
+ /*
+ * one transmitter at a time
+ */
+ qlock(&ap->xmit);
+
+ /*
+ * parse message
+ */
+ bp = getq(q);
+ if(bp->wptr - bp->rptr < 3){
+ freemsg(q, bp);
+ qunlock(&ap->xmit);
+ return;
+ }
+ chan = bp->rptr[0] | (bp->rptr[1]<<8);
+ ctl = bp->rptr[2];
+ bp->rptr += 3;
+
+ /*
+ * new frame if the channel number has changed
+ */
+ if (chan != ap->chan && ap->count > 0)
+ asputf(ap, 0);
+ ap->chan = chan;
+
+ if (asyncdebug > 1)
+ kprint("a%d->(%d)%3.3uo %d\n",
+ ap-async, chan, ctl, bp->wptr - bp->rptr);
+
+ /*
+ * send the 8 bit data
+ */
+ for(;;){
+ /*
+ * put in next packet
+ */
+ while (bp->rptr < bp->wptr) {
+ asputc(ap, c = *bp->rptr++);
+ if (c == STUF)
+ asputc(ap, 0);
+ }
+
+ /*
+ * get next block
+ */
+ if(bp->flags & S_DELIM){
+ freeb(bp);
+ break;
+ }
+ freeb(bp);
+ bp = getq(q);
+ if(bp==0)
+ break;
+ }
+
+ /*
+ * send the control byte if there is one
+ */
+ if(ctl){
+ asputc(ap, STUF);
+ asputc(ap, ctl);
+ switch (ctl) {
+ case BOT:
+ case BOTM:
+ case BOTS:
+ break;
+ default:
+ asputf(ap, 1);
+ }
+ }
+
+ qunlock(&ap->xmit);
+ return;
+}
+
+/*
+ * Read bytes from the raw input.
+ */
+
+void
+asdeliver(Async *ap, uchar *p, int n)
+{
+ Block *bp = 0;
+ int chan, c;
+
+ if (!ap->rq)
+ return;
+
+ chan = *p++ & 0x7e;
+ chan = (chan<<5)|((*p++ & 0x7e)>>1);
+ if (chan==0) {
+ DPRINT("a%d deliver chan 0\n", ap-async);
+ ap->chan0++;
+ return;
+ }
+ for (n-=4; n>0; n--) {
+ if (!bp) {
+ bp = allocb(n+2);
+ bp->flags |= S_DELIM;
+ bp->wptr[0] = chan;
+ bp->wptr[1] = chan>>8;
+ bp->wptr[2] = 0;
+ bp->wptr += 3;
+ }
+ if ((c = *p++) == STUF) {
+ --n;
+ if ((c = *p++) != 0) {
+ bp->rptr[2] = c;
+ if (asyncdebug > 1)
+ kprint("a%d<-(%d)%3.3uo %d\n",
+ ap-async, chan, bp->rptr[2],
+ bp->wptr - bp->rptr - 3);
+ PUTNEXT(ap->rq, bp);
+ bp = 0;
+ continue;
+ } else
+ c = STUF;
+ }
+ *bp->wptr++ = c;
+ }
+ if (bp) {
+ if (asyncdebug > 1)
+ kprint("a%d<-(%d)%3.3uo %d\n",
+ ap-async, chan, bp->rptr[2],
+ bp->wptr - bp->rptr - 3);
+ PUTNEXT(ap->rq, bp);
+ }
+}
+
+enum { Hunt=0, Framing, Framed, Data, Escape };
+
+static void
+asynckproc(void *arg)
+{
+ Async *ap = (Async *)arg;
+ int c, state, count; unsigned short crc;
+ uchar buf[MAXFRAME], ibuf[MAXFRAME], *p;
+ int nibuf;
+
+ DPRINT("asynckproc %d\n", ap-async);
+ nibuf = 0;
+ state = Hunt;
+Loop:
+ if (--nibuf < 0) {
+ if (ap->rq)
+ nibuf = (*devtab[ap->c->type].read)(ap->c,
+ ibuf, sizeof ibuf);
+ if (nibuf <= 0) {
+ unlock(&ap->kstart);
+ wakeup(&ap->r);
+ return;
+ }
+ ap->in += nibuf--;
+ p = ibuf;
+ }
+ c = *p++;
+ switch (state) {
+ case Hunt: /* wait for framing byte */
+ if (c == FRAME)
+ state = Framing;
+ break;
+
+ case Framing: /* saw 1 framing byte after Hunt */
+ if (c == FRAME)
+ state = Framed;
+ else
+ state = Hunt;
+ break;
+
+ case Framed: /* saw 2 or more framing bytes */
+ if (c == FRAME)
+ break;
+ state = Data;
+ crc = CRCSTART;
+ count = 0;
+ goto Datachar;
+
+ case Data: /* mid-frame */
+ if (c == FRAME) {
+ state = Escape;
+ break;
+ }
+ Datachar:
+ if (count >= MAXFRAME) {
+ DPRINT("a%d pkt too long\n", ap-async);
+ ap->toolong++;
+ state = Hunt;
+ break;
+ }
+ crc = CRCFUNC(crc, c);
+ buf[count++] = c;
+ break;
+
+ case Escape: /* saw framing byte in Data */
+ switch (c) {
+ case FRAME:
+ if (asyncdebug > 2)
+ showframe("in", ap, buf, count);
+ if (count < 5) {
+ DPRINT("a%d pkt too short\n", ap-async);
+ ap->tooshort++;
+ } else if (crc != 0) {
+ DPRINT("a%d bad crc\n", ap-async);
+ ap->badcrc++;
+ } else {
+ asdeliver(ap, buf, count);
+ }
+ state = Framed;
+ break;
+ case 0:
+ c = FRAME;
+ state = Data;
+ goto Datachar;
+ default:
+ DPRINT("a%d bad escape\n", ap-async);
+ ap->badescape++;
+ state = Hunt;
+ break;
+ }
+ break;
+ }
+ goto Loop;
+}
M gnot/stream.c => gnot/stream.c +20 -0
@@ 232,6 232,26 @@ freeb(Block *bp)
}
/*
+ * pad a block to the front with n bytes
+ */
+Block *
+padb(Block *bp, int n)
+{
+ Block *nbp;
+
+ if(bp->base && bp->rptr-bp->base>=n){
+ bp->rptr -= n;
+ return bp;
+ } else {
+ nbp = allocb(n);
+ nbp->wptr = nbp->lim;
+ nbp->rptr = nbp->wptr - n;
+ nbp->next = nbp;
+ return nbp;
+ }
+}
+
+/*
* allocate a pair of queues. flavor them with the requested put routines.
* the `QINUSE' flag on the read side is the only one used.
*/
M gnot/trap.c => gnot/trap.c +2 -3
@@ 94,7 94,7 @@ trap(Ureg *ur)
sprint(buf, "pc=%lux trap: %s", ur->pc, excname(ur->vo));
postnote(u->p, 1, buf, NDebug);
}else{
- print("kernel trap vo=%ux pc=%lux\n", ur->vo, ur->pc);
+ print("kernel trap vo=0x%ux pc=%lux\n", ur->vo, ur->pc);
dumpregs(ur);
exit();
}
@@ 243,7 243,6 @@ syscall(Ureg *aur)
ulong r0;
Ureg *ur;
char *msg;
- long fpnull = 0;
u->p->insyscall = 1;
ur = aur;
@@ 258,7 257,7 @@ syscall(Ureg *aur)
splhi();
fpsave(&u->fpsave);
if(u->p->fpstate==FPactive || u->fpsave.type){
- fprestore((FPsave*)&fpnull);
+ fprestore(&initfp);
u->p->fpstate = FPinit;
m->fpstate = FPinit;
}
M port/stream.c => port/stream.c +42 -72
@@ 24,19 24,6 @@ Qinfo procinfo = { stputq, nullput, 0, 0, "process" };
*/
static Qinfo *lds[Nlds+1];
-void
-newqinfo(Qinfo *qi)
-{
- int i;
-
- for(i=0; i<Nlds && lds[i]; i++)
- if(lds[i] == qi)
- return;
- if(i == Nlds)
- panic("pushable");
- lds[i] = qi;
-}
-
/*
* All stream structures are ialloc'd at boot time
*/
@@ 68,6 55,14 @@ Bclass bclass[Nclass]={
};
/*
+ * the per stream directory structure
+ */
+Dirtab streamdir[]={
+ "data", Sdataqid, 0, 0600,
+ "ctl", Sctlqid, 0, 0600,
+};
+
+/*
* Dump all block information of how many blocks are in which queues
*/
void
@@ 120,19 115,26 @@ dumpqueues(void)
* Allocate streams, queues, and blocks. Allocate n block classes with
* 1/2(m+1) to class m < n-1
* 1/2(n-1) to class n-1
+ *
+ * All data areas are alligned to their size.
+ *
+ * No data area crosses a 4k boundary. This allows us to use the
+ * VME/SCSI/LANCE to MP bus maps on the SGI power series machines.
*/
void
streaminit(void)
{
- int class, i, n;
+ int class, i, n, left;
Block *bp;
Bclass *bcp;
+ uchar *ptr;
slist = (Stream *)ialloc(conf.nstream * sizeof(Stream), 0);
qlist = (Queue *)ialloc(conf.nqueue * sizeof(Queue), 0);
blist = (Block *)ialloc(conf.nblock * sizeof(Block), 0);
bp = blist;
n = conf.nblock;
+ left = 0;
for(class = 0; class < Nclass; class++){
if(class < Nclass-1)
n = n/2;
@@ 143,8 145,15 @@ streaminit(void)
* starts on a page boundary. This makes sure
* no block crosses a page boundary.
*/
- if(bcp->size)
- bp->base = (uchar *)ialloc(bcp->size, i == 0);
+ if(bcp->size){
+ if(bcp->size > left){
+ left = bcp->size>4096 ? bcp->size : 4096;
+ ptr = (uchar *)ialloc(left, 1);
+ }
+ bp->base = ptr;
+ ptr += bcp->size;
+ left -= bcp->size;
+ }
bp->lim = bp->base + bcp->size;
bp->flags = class;
freeb(bp);
@@ 479,54 488,6 @@ getb(Blist *q)
}
/*
- * make sure the first block has n bytes
- */
-Block *
-pullup(Block *bp, int n)
-{
- Block *nbp;
- int i;
-
- /*
- * this should almost always be true, the rest it
- * just for to avoid every caller checking.
- */
- if(BLEN(bp) >= n)
- return bp;
-
- /*
- * if not enough room in the first block,
- * add another to the front of the list.
- if(bp->lim - bp->rptr < n){
- nbp = allocb(n);
- nbp->next = bp;
- bp = nbp;
- }
-
- /*
- * copy bytes from the trailing blocks into the first
- */
- n -= BLEN(bp);
- while(nbp = bp->next){
- i = BLEN(nbp);
- if(i > n) {
- memcpy(bp->wptr, nbp->rptr, n);
- bp->wptr += n;
- nbp->rptr += n;
- return bp;
- } else {
- memcpy(bp->wptr, nbp->rptr, i);
- bp->wptr += i;
- bp->next = nbp->next;
- nbp->next = 0;
- freeb(nbp);
- }
- }
- freeb(bp);
- return 0;
-}
-
-/*
* grow the front of a list of blocks by n bytes
*/
Block *
@@ 626,14 587,6 @@ streamparse(char *name, Block *bp)
}
/*
- * the per stream directory structure
- */
-Dirtab streamdir[]={
- "data", Sdataqid, 0, 0600,
- "ctl", Sctlqid, 0, 0600,
-};
-
-/*
* A stream device consists of the contents of streamdir plus
* any directory supplied by the actual device.
*
@@ 1197,3 1150,20 @@ streamstat(Chan *c, char *db, char *name)
devdir(c, c->qid, name, n, 0, &dir);
convD2M(&dir, db);
}
+
+/*
+ * announce a line discipline that can be pushed
+ */
+void
+newqinfo(Qinfo *qi)
+{
+ int i;
+
+ for(i=0; i<Nlds && lds[i]; i++)
+ if(lds[i] == qi)
+ return;
+ if(i == Nlds)
+ panic("pushable");
+ lds[i] = qi;
+}
+
M power/dat.h => power/dat.h +1 -1
@@ 477,7 477,7 @@ enum {
Sctlqid = Sdataqid-1,
Slowqid = Sctlqid,
Streamhi= (17*1024), /* byte count high water mark */
- Streambhi= 16, /* block count high water mark */
+ Streambhi= 32, /* block count high water mark */
};
/*
M power/fns.h => power/fns.h +1 -0
@@ 97,6 97,7 @@ Orig *lookorig(ulong, ulong, int, Chan*);
void machinit(void);
void mapstack(Proc*);
int mount(Chan*, Chan*, int);
+void mpbuserror(void);
Chan *namec(char*, int, int, ulong);
void nexterror(void);
Alarm *newalarm(void);
M power/io.h => power/io.h +12 -10
@@ 44,9 44,12 @@ struct SBCC
#define LANCERAM IO2(uchar, 0xE00000)
#define LANCEEND IO2(uchar, 0xF00000)
+#define LANCE3RAM IO2(uchar, 0xFF4000)
+#define LANCE3END IO2(uchar, 0xFF8000)
#define LANCERDP IO2(ushort, 0xFC0002)
#define LANCERAP IO2(ushort, 0xFC000a)
#define LANCEID IO2(ushort, 0xFF0002)
+
#define IOID IO2(uchar, 0xFFFFF0)
#define IO2R1 1 /* IO2 revision level 1 */
#define IO2R2 2 /* IO2 revision level 2 */
@@ 83,21 86,20 @@ struct INTVEC {
#define MPBERR1 IO2(ulong, 0xF4C000)
#define SBEADDR ((ulong *)(UNCACHED|0x1F080000))
-/*
- * IO board type
- */
-extern int ioid;
+extern int ioid; /* io board type */
+extern int iolevels; /* number of io levels */
+extern int iomask; /* interrupts to enable */
/*
* The IO2/IO3 slave maps. These maps are used to map
* external addresses to MP bus addresses.
*/
enum {
- a24map, /* VME A24 non-priv address space */
- a32map, /* VME A32 non-priv address space */
- lancemap, /* Lance chip address space */
- scsi1map, /* SCSI bus 1 address space */
- scsi0map, /* SCSI bus 0 address space */
- nomap,
+ A24map, /* VME A24 non-priv address space */
+ A32map, /* VME A32 non-priv address space */
+ Lancemap, /* Lance chip address space */
+ Scsi1map, /* SCSI bus 1 address space */
+ Scsi0map, /* SCSI bus 0 address space */
+ Nomap,
};
#define WRITEMAP IO2(ulong, 0xFA0000);
M power/main.c => power/main.c +22 -5
@@ 35,9 35,11 @@ char confbuf[4*1024];
char sysname[64];
/*
- * IO board type
+ * IO board type, number of interrupt levels, and interrupt enable mask
*/
int ioid;
+int iolevels;
+int iomask;
void
main(void)
@@ 133,8 135,23 @@ void
ioboardinit(void)
{
long i;
+ int intrs;
+ /*
+ * set up interrupts based on IO board type
+ */
ioid = *IOID;
+ switch(ioid){
+ case IO2R1:
+ case IO2R2:
+ iolevels = 8;
+ iomask = 0xff;
+ break;
+ case IO3R1:
+ iolevels = 11;
+ iomask = 0x7fe;
+ break;
+ }
/*
* reset VME bus (MODEREG is on the IO2)
@@ 152,9 169,9 @@ ioboardinit(void)
setvmevec(i, novme);
/*
- * tell IO2 to sent all interrupts to CPU 0's SBCC
+ * tell IO2 to send all interrupts to CPU 0's SBCC
*/
- for(i=0; i<8; i++)
+ for(i=0; i<iolevels; i++)
INTVECREG->i[i].vec = 0<<8;
/*
@@ 174,13 191,13 @@ ioboardinit(void)
* The SBCC 16 bit registers are read/written as ulong, but only
* bits 23-16 and 7-0 are meaningful.
*/
- SBCCREG->fintenable |= 0xff; /* allow all interrupts on the IO2 */
+ SBCCREG->fintenable |= iomask; /* turn on all interrupts */
SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */
/*
* enable all interrupts on the IO2
*/
- *IO2SETMASK = 0xff;
+ *IO2SETMASK = iomask;
}
void
M power/trap.c => power/trap.c +37 -31
@@ 180,6 180,14 @@ trap(Ureg *ur)
}
void
+mpbuserror(void)
+{
+ print("io2 mp bus error %d %lux %lux\n", 0,
+ *MPBERR0, *MPBERR1);
+ *MPBERR0 = 0;
+}
+
+void
intr(ulong cause, ulong pc)
{
int i, pend;
@@ 227,33 235,34 @@ intr(ulong cause, ulong pc)
/*
* 5a. process lance, scsi
*/
- loop:
if(pend & 1) {
v = INTVECREG->i[0].vec;
- if(!(v & (1<<12))){
- print("io2 mp bus error %d %lux %lux\n", 0,
- *MPBERR0, *MPBERR1);
- *MPBERR0 = 0;
- }
- switch(ioid){
- case IO2R1:
- case IO2R2:
- if(!(v & (1<<2)))
- lanceintr();
- if(!(v & (1<<1)))
- lanceparity();
- if(!(v & (1<<0)))
- print("SCSI interrupt\n");
- break;
- case IO3R1:
- if(v & (1<<2))
- lance3intr();
- if(v & (1<<1))
- print("SCSI 1 interrupt\n");
- if(v & (1<<0))
- print("SCSI 0 interrupt\n");
- break;
- }
+ if(!(v & (1<<12)))
+ mpbuserror();
+ if(!(v & (1<<2)))
+ lanceintr();
+ if(!(v & (1<<1)))
+ lanceparity();
+ if(!(v & (1<<0)))
+ print("SCSI interrupt\n");
+ }
+ if(pend & (1<<10)) {
+ v = INTVECREG->i[10].vec;
+ if(!(v & (1<<12)))
+ mpbuserror();
+ lance3intr();
+ }
+ if(pend & (1<<8)) {
+ v = INTVECREG->i[10].vec;
+ if(!(v & (1<<12)))
+ mpbuserror();
+ print("SCSI0 interrupt\n");
+ }
+ if(pend & (1<<9)) {
+ v = INTVECREG->i[10].vec;
+ if(!(v & (1<<12)))
+ mpbuserror();
+ print("SCSI1 interrupt\n");
}
/*
* 5b. process vme
@@ 263,11 272,8 @@ intr(ulong cause, ulong pc)
for(i=1; pend; i++) {
if(pend & 1) {
v = INTVECREG->i[i].vec;
- if(!(v & (1<<12))){
- print("io2 mp bus error %d %lux %lux\n", i,
- *MPBERR0, *MPBERR1);
- *MPBERR0 = 0;
- }
+ if(!(v & (1<<12)))
+ mpbuserror();
v &= 0xff;
(*vmevec[v])(v);
}
@@ 276,7 282,7 @@ intr(ulong cause, ulong pc)
/*
* 6. re-enable interrupts
*/
- *IO2SETMASK = 0xff;
+ *IO2SETMASK = iomask;
cause &= ~INTR5;
}
if(cause)