From 437dd1f6f13d774d07428f40ece2d4574a80b3e2 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 5 Sep 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-09-05 --- gnot/dat.h | 6 +- gnot/devcons.c | 96 ++++++----- gnot/devdk.c | 8 +- gnot/fns.h | 1 + gnot/main.c | 3 +- gnot/proc.c | 8 +- gnot/stasync.c | 432 +++++++++++++++++++++++++++++++++++++++++++++++++ gnot/stream.c | 20 +++ gnot/trap.c | 5 +- port/stream.c | 114 +++++-------- power/dat.h | 2 +- power/fns.h | 1 + power/io.h | 22 +-- power/main.c | 27 +++- power/trap.c | 68 ++++---- 15 files changed, 634 insertions(+), 179 deletions(-) create mode 100644 gnot/stasync.c diff --git a/gnot/dat.h b/gnot/dat.h index c5c17d5376c9ea04030c029bae28c009fcc6ace8..3e2acdf012922b429e2a9b3d3e91920d572ee8f0 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -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]; }; diff --git a/gnot/devcons.c b/gnot/devcons.c index 2d0f0c4c705fc3901c441cfb6fc78cac84488772..860b5f2ec87d9c289bc1fc437075124448d40b44 100644 --- a/gnot/devcons.c +++ b/gnot/devcons.c @@ -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; } diff --git a/gnot/devdk.c b/gnot/devdk.c index dcc56fa917e1a046b139bf43657dfc204ef608ed..4b9d04847bc1e38a96fd7a6f993f5ac3c497afe0 100644 --- a/gnot/devdk.c +++ b/gnot/devdk.c @@ -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; diff --git a/gnot/fns.h b/gnot/fns.h index 7af8fa4935a6d6334c14bf6ea19b0b40909593c8..e39bd04b1173f9eeb21dbe8513a29c99742a3ec7 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -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); diff --git a/gnot/main.c b/gnot/main.c index b6d74a69019801a8f8e2ee6c407fa18b89981e24..003a631dd2f66399d858446d45748b54cac972d5 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -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<machno; m->fpstate = FPinit; - fprestore((FPsave*)&fpnull); + fprestore(&initfp); } void diff --git a/gnot/proc.c b/gnot/proc.c index 16230e9fcd58a080e2500b35988322739b5e65d9..cb30f17233096aa89aafbed37c46ad1c5dd2538a 100644 --- a/gnot/proc.c +++ b/gnot/proc.c @@ -5,7 +5,7 @@ #include "fns.h" #include "errno.h" -#include +#include 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); diff --git a/gnot/stasync.c b/gnot/stasync.c new file mode 100644 index 0000000000000000000000000000000000000000..398b50112b499ce181dbb66868face4706e1f3de --- /dev/null +++ b/gnot/stasync.c @@ -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; +} diff --git a/gnot/stream.c b/gnot/stream.c index b58a642457b32ed07854da4942f7c9c30c398a0b..3afd951b6e0eb3ab1ced2b60c4006e47be287774 100644 --- a/gnot/stream.c +++ b/gnot/stream.c @@ -231,6 +231,26 @@ freeb(Block *bp) wakeup(&bcp->r); } +/* + * 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. diff --git a/gnot/trap.c b/gnot/trap.c index 3872346ca45d459e317e39835143d997087271b8..a70fd95ddffa99e057e51f06f321f1e43a15211d 100644 --- a/gnot/trap.c +++ b/gnot/trap.c @@ -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; } diff --git a/port/stream.c b/port/stream.c index 9c65b4161f06682796d39dbd4e7fc82ed5ed0db9..fbe4f530e32493c2d550618a86d242faec30565b 100644 --- a/port/stream.c +++ b/port/stream.c @@ -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; isize) - 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); @@ -478,54 +487,6 @@ getb(Blist *q) return bp; } -/* - * 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 */ @@ -625,14 +586,6 @@ streamparse(char *name, Block *bp) return 0; } -/* - * 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; ii[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 diff --git a/power/trap.c b/power/trap.c index 042d0d8490a77ddaab616c5a35206d3eab0417ec..75ac2fe00732c93d7d8a0570efcc3200fa7c8ca5 100644 --- a/power/trap.c +++ b/power/trap.c @@ -179,6 +179,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) { @@ -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)