M gnot/dat.h => gnot/dat.h +1 -1
@@ 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;
};
M port/devmnt.c => port/devmnt.c +2 -2
@@ 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);
M port/devproc.c => port/devproc.c +4 -4
@@ 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;
}
M port/pgrp.c => port/pgrp.c +2 -2
@@ 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; i<p->nmtab; 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);
}
}
M power/dat.h => power/dat.h +1 -1
@@ 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;
};
M power/devhotrod.c => power/devhotrod.c +92 -64
@@ 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
M power/io.h => power/io.h +10 -3
@@ 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)
M power/main.c => power/main.c +3 -3
@@ 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;
}
M power/trap.c => power/trap.c +25 -13
@@ 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)
M ss/dat.h => ss/dat.h +1 -1
@@ 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;
};