From fb6fc6c2654be6262d6627acd63f5d6e327ae042 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 12 Feb 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-02-12 --- gnot/dat.h | 2 +- port/devmnt.c | 4 +- port/devproc.c | 8 +-- port/pgrp.c | 4 +- power/dat.h | 2 +- power/devhotrod.c | 156 +++++++++++++++++++++++++++------------------- power/io.h | 13 +++- power/main.c | 6 +- power/trap.c | 38 +++++++---- ss/dat.h | 2 +- 10 files changed, 141 insertions(+), 94 deletions(-) diff --git a/gnot/dat.h b/gnot/dat.h index 21470d2d8feeaa6257f31cd71976603045b93088..975ce3a30a06f39bd27764eb952d1bbbd40f9231 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -288,7 +288,7 @@ struct Pgrp char user[NAMELEN]; int nmtab; /* highest active mount table entry, +1 */ int nenv; /* highest active env table entry, +1 */ - Lock debug; /* single access via devproc.c */ + QLock debug; /* single access via devproc.c */ Mtab *mtab; Envp *etab; }; diff --git a/port/devmnt.c b/port/devmnt.c index d5ec39b019e7e0d7bf8cce36a4f418596368c335..f92f4d161d205652f40188606c888974b7f1103e 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -688,10 +688,10 @@ mntxmit(Mnt *m, Mnthdr *mh) error(Eshutdown); #ifdef BIT3 /* - * Bit3 does its own multiplexing. (Well, the file server does.) + * Bit3 and Hotrod do their own multiplexing. (Well, the file server does.) * The code is different enough that it's broken out separately here. */ - if(devchar[q->msg->type] != '3') + if(devchar[q->msg->type]!='3' && devchar[q->msg->type]!='H') goto Normal; incref(q); diff --git a/port/devproc.c b/port/devproc.c index f0da947b85c2ddc02e1029f74d0cd19559709bff..14c14e6442033064e2263f97cebd19f127b74d63 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -374,17 +374,17 @@ procwrite(Chan *c, void *va, long n) */ if(QID(c->qid) == Qnotepg){ pg = pgrptab(c->pgrpid.path-1); - lock(&pg->debug); + qlock(&pg->debug); if(waserror()){ - unlock(&pg->debug); + qunlock(&pg->debug); nexterror(); } if(pg->pgrpid != c->pgrpid.vers){ - unlock(&pg->debug); + qunlock(&pg->debug); goto Died; } pgrpnote(pg, va, n, NUser); - unlock(&pg->debug); + qunlock(&pg->debug); return n; } diff --git a/port/pgrp.c b/port/pgrp.c index 6035ecf599d53b2d2e2bd07a18865e37dcfe832c..3c7c61bc67f108109e7f4c47e5e6cbf3c1a6177e 100644 --- a/port/pgrp.c +++ b/port/pgrp.c @@ -115,7 +115,7 @@ closepgrp(Pgrp *p) Envp *ep; if(decref(p) == 0){ - lock(&p->debug); + qlock(&p->debug); p->pgrpid = -1; m = p->mtab; for(i=0; inmtab; i++,m++) @@ -130,7 +130,7 @@ closepgrp(Pgrp *p) lock(&pgrpalloc); p->next = pgrpalloc.free; pgrpalloc.free = p; - unlock(&p->debug); + qunlock(&p->debug); unlock(&pgrpalloc); } } diff --git a/power/dat.h b/power/dat.h index 5494825a472e296d006dd06428eeaa3968dc6723..4082f4efa12f546b05263cdf9ccfb484cb33befc 100644 --- a/power/dat.h +++ b/power/dat.h @@ -285,7 +285,7 @@ struct Pgrp char user[NAMELEN]; int nmtab; /* highest active mount table entry, +1 */ int nenv; /* highest active env table entry, +1 */ - Lock debug; /* single access via devproc.c */ + QLock debug; /* single access via devproc.c */ Mtab *mtab; Envp *etab; }; diff --git a/power/devhotrod.c b/power/devhotrod.c index f6b4988a0b3cb1a5277614b9d69d50295c3ff7e6..07577ecb485874ef405aa5b352bc68a7f957af3a 100644 --- a/power/devhotrod.c +++ b/power/devhotrod.c @@ -5,6 +5,7 @@ #include "fns.h" #include "errno.h" #include "devtab.h" +#include "fcall.h" #include "io.h" @@ -42,6 +43,7 @@ struct HotQ{ struct Hotrod{ QLock; + QLock buflock; Lock busy; Device *addr; /* address of the device */ int vec; /* vme interrupt vector */ @@ -50,6 +52,7 @@ struct Hotrod{ HotQ rq; /* read this queue to receive replies */ int ri; /* where to read next response */ Rendez r; + uchar buf[MAXFDATA+100]; }; Hotrod hotrod[Nhotrod]; @@ -62,13 +65,15 @@ void hotrodintr(int); enum{ RESET= 0, /* params: Q address, length of queue */ REBOOT= 1, /* params: none */ + READ= 2, /* params: buffer, count, returned count */ + WRITE= 3, /* params: buffer, count */ }; void hotsend(Hotrod *h, Hotmsg *m) { print("hotsend send %d %lux %lux\n", m->cmd, m, m->param[0]); - h->wq->msg[h->wi] = m; + h->wq->msg[h->wi] = (Hotmsg*)MP2VME(m); while(h->wq->msg[h->wi]) ; print("hotsend done\n"); @@ -155,6 +160,7 @@ hotrodopen(Chan *c, int omode) { Device *dp; Hotrod *hp; + Hotmsg *mp; if(c->qid.path == CHDIR){ if(omode != OREAD) @@ -174,9 +180,10 @@ hotrodopen(Chan *c, int omode) */ hp->wi = 0; hp->ri = 0; - u->khot.cmd = RESET; - u->khot.param[0] = (ulong)&hp->rq; - u->khot.param[1] = NhotQ; + mp = &u->khot; + mp->cmd = RESET; + mp->param[0] = MP2VME(&hp->rq); + mp->param[1] = NhotQ; hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); } c->mode = openmode(omode); @@ -205,45 +212,60 @@ hotrodclose(Chan *c) } /* - * read the hotrod memory + * Read and write use physical addresses if they can, which they usually can. + * Most I/O is from devmnt, which has local buffers. Therefore just check + * that buf is in KSEG0 and is at an even address. */ + long hotrodread(Chan *c, void *buf, long n) { Hotrod *hp; - Device *dp; - ulong *from; - ulong *to; - ulong *end; - - if(c->qid.path != Qhotrod) - error(Egreg); - - /* - * allow full word access only - */ - if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1))) - error(Ebadarg); + Hotmsg *mp; hp = &hotrod[c->dev]; - dp = hp->addr; - if(c->offset >= sizeof(dp->mem)) - return 0; - if(c->offset+n > sizeof(dp->mem)) - n = sizeof(dp->mem) - c->offset; - - /* - * avoid memcpy to ensure VME 32-bit reads - */ - qlock(hp); - to = buf; - from = &dp->mem[c->offset/sizeof(ulong)]; - end = to + (n/sizeof(ulong)); - while(to != end){ - *to++ = *from++; + switch(c->qid.path){ + case Qhotrod: + if(n > sizeof hp->buf) + error(Egreg); + if((((ulong)buf)&(KSEGM|3)) == KSEG0){ + /* + * use supplied buffer, no need to lock for reply + */ + mp = &u->khot; + mp->param[2] = 0; /* reply count */ + qlock(hp); + mp->cmd = READ; + mp->param[0] = MP2VME(buf); + mp->param[1] = n; + hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); + qunlock(hp); + do + n = mp->param[2]; + while(n == 0); + }else{ + /* + * use hotrod buffer. lock the buffer till the reply + */ + mp = &u->uhot; + mp->param[2] = 0; /* reply count */ + qlock(&hp->buflock); + qlock(hp); + mp->cmd = READ; + mp->param[0] = MP2VME(hp->buf); + mp->param[1] = n; + hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot); + qunlock(hp); + do + n = mp->param[2]; + while(n == 0); + memcpy(buf, hp->buf, n); + qunlock(&hp->buflock); + } + return n; } - qunlock(hp); - return n; + error(Egreg); + return 0; } /* @@ -253,37 +275,43 @@ long hotrodwrite(Chan *c, void *buf, long n) { Hotrod *hp; - Device *dp; - ulong *from; - ulong *to; - ulong *end; - - if(c->qid.path != Qhotrod) - error(Egreg); - /* - * allow full word access only - */ - if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1))) - error(Ebadarg); + Hotmsg *mp; hp = &hotrod[c->dev]; - dp = hp->addr; - if(c->offset >= sizeof(dp->mem)) - return 0; - if(c->offset+n > sizeof(dp->mem)) - n = sizeof(dp->mem) - c->offset; - - /* - * avoid memcpy to ensure VME 32-bit writes - */ - qlock(hp); - from = buf; - to = &dp->mem[c->offset/sizeof(ulong)]; - end = to + (n/sizeof(ulong)); - while(to != end) - *to++ = *from++; - qunlock(hp); - return n; + switch(c->qid.path){ + case 1: + if(n > sizeof hp->buf) + error(Egreg); + if((((ulong)buf)&(KSEGM|3)) == KSEG0){ + /* + * use supplied buffer, no need to lock for reply + */ + mp = &u->khot; + qlock(hp); + mp->cmd = WRITE; + mp->param[0] = MP2VME(buf); + mp->param[1] = n; + hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); + qunlock(hp); + }else{ + /* + * use hotrod buffer. lock the buffer till the reply + */ + mp = &u->uhot; + qlock(&hp->buflock); + qlock(hp); + memcpy(hp->buf, buf, n); + mp->cmd = WRITE; + mp->param[0] = MP2VME(hp->buf); + mp->param[1] = n; + hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot); + qunlock(hp); + qunlock(&hp->buflock); + } + return n; + } + error(Egreg); + return 0; } void diff --git a/power/io.h b/power/io.h index d33071780eb8b125c8cc4dfdb00586d7a9595c0a..53932fd04913196c62877a8b05938dcfd3a56f77 100644 --- a/power/io.h +++ b/power/io.h @@ -71,8 +71,15 @@ struct MODE { #define MODEREG IO2(MODE, 0xF40000) +/* + * VME addressing. + * MP2VME takes a physical MP bus address and returns an address + * usable by a VME device through A32 space + */ #define MASTER 0x0 #define SLAVE 0x4 +#define MP2VME(addr) (((ulong)(addr) & 0x0fffffff) | (SLAVE<<28)) + struct INTVEC { struct { @@ -84,9 +91,9 @@ struct INTVEC { #define INTVECREG IO2(INTVEC, 0xF60000) #define NVRAM IO2(uchar, 0xF10000) #define INTPENDREG IO2(uchar, 0xF20000) /* same as LED */ -#define IO2CLRMASK IO2(uchar, 0xFE0000) -#define IO2SETMASK IO2(uchar, 0xFE8000) -#define IO2MASK IO2(ushort, 0xFE8000) +#define INTPENDREG3 IO2(uchar, 0xFF0000) /* same as ENET ID */ +#define IO2CLRMASK IO2(ulong, 0xFE0000) +#define IO2SETMASK IO2(ulong, 0xFE8000) #define MPBERR0 IO2(ulong, 0xF48000) #define MPBERR1 IO2(ulong, 0xF4C000) #define RTC (NVRAM+0x3ff8) diff --git a/power/main.c b/power/main.c index 2b0e4f828f30fe1ee7bac208775b4da973b108b0..eeec2678731aa1198e75bc6b28125f54c215aa7d 100644 --- a/power/main.c +++ b/power/main.c @@ -137,7 +137,7 @@ ioboardinit(void) ioid = *IOID; if(ioid >= IO3R1) - maxlevel = 11; + maxlevel = 8; else maxlevel = 8; @@ -177,9 +177,9 @@ ioboardinit(void) SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */ /* - * enable all interrupts on the IO2 + * Enable all interrupts on the IO2. If IO3, run in compatibility mode. */ - *IO2SETMASK = 0xff; + *IO2SETMASK = 0xff000000; } diff --git a/power/trap.c b/power/trap.c index 2c682e640d5de75730d1b3d7b3b2024eaf34a8f8..4b9b0f4524bea12bc884d0c12caf51195bc2c786 100644 --- a/power/trap.c +++ b/power/trap.c @@ -175,7 +175,8 @@ trap(Ureg *ur) void intr(Ureg *ur) { - int i, pend; + int i, any; + uchar pend, npend; long v; ulong cause; @@ -189,19 +190,20 @@ intr(Ureg *ur) cause &= ~INTR1; } if(cause & INTR5){ - + any = 0; if(!(*MPBERR1 & (1<<8))){ print("MP bus error %lux %lux\n", *MPBERR0, *MPBERR1); *MPBERR0 = 0; i = *SBEADDR; USED(i); + any = 1; } /* * directions from IO2 manual * 1. clear all IO2 masks */ - *IO2CLRMASK = 0xff; + *IO2CLRMASK = 0xff000000; /* * 2. wait for interrupt in progress @@ -212,7 +214,7 @@ intr(Ureg *ur) /* * 3. read pending interrupts */ - pend = SBCCREG->fintpending & 0xff; + npend = pend = SBCCREG->fintpending; /* * 4. clear pending register @@ -223,22 +225,26 @@ intr(Ureg *ur) /* * 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; + any = 1; } if(ioid < IO3R1){ + if(!(v & 7)) + any = 1; if(!(v & (1<<2))) lanceintr(); if(!(v & (1<<1))) lanceparity(); if(!(v & (1<<0))) print("SCSI interrupt\n"); - } else { + }else{ + if(v & 7) + any = 1; if(v & (1<<2)) lanceintr(); if(v & (1<<1)) @@ -249,26 +255,32 @@ intr(Ureg *ur) } /* * 5b. process vme - * i bet i can guess your level + * i can guess your level */ - pend >>= 1; - for(i=1; pend; i++) { + for(i=1; pend>>=1; 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); + print("io2 mp bus error %d %lux %lux\n", + i, *MPBERR0, *MPBERR1); *MPBERR0 = 0; } v &= 0xff; (*vmevec[v])(v); + any = 1; } - pend >>= 1; + } + /* + * if nothing else, assume bus error + */ + if(!any){ + print("bogus intr lvl 5 pend %lux on %d\n", npend, m->machno); + delay(100); } /* * 6. re-enable interrupts */ - *IO2SETMASK = 0xff; + *IO2SETMASK = 0xff000000; cause &= ~INTR5; } if(cause) diff --git a/ss/dat.h b/ss/dat.h index b941445f70c2d1b33e69ebffc3866c8e56aba08c..c9e1d8be6ca87c2c83270a90963eb8262bd04ea2 100644 --- a/ss/dat.h +++ b/ss/dat.h @@ -293,7 +293,7 @@ struct Pgrp char user[NAMELEN]; int nmtab; /* highest active mount table entry, +1 */ int nenv; /* highest active env table entry, +1 */ - Lock debug; /* single access via devproc.c */ + QLock debug; /* single access via devproc.c */ Mtab *mtab; Envp *etab; };