## diffname power/devcyc.c 1992/0613 ## diff -e /dev/null /n/bootesdump/1992/0613/sys/src/9/power/devcyc.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "devtab.h" #include "fcall.h" #include "io.h" #include "../../fs/cyc/comm.h" typedef struct Commcyc Commcyc; enum { Vmevec= 0xd2, /* vme vector for interrupts */ Intlevel= 5, /* level to interrupt on */ Qdir= 0, /* Qid's */ Qcyc= 1, Ncyc= 1, }; Dirtab cycdir[]={ "cyc", {Qcyc}, 0, 0600, }; #define NCYCDIR (sizeof cycdir/sizeof(Dirtab)) struct Commcyc { Lock; QLock buflock; Lock busy; Comm *addr; /* address of the device */ int vec; /* vme interrupt vector */ int wi; /* where to write next cmd */ int ri; /* where to read next reply */ uchar buf[MAXFDATA+MAXMSG]; }; Commcyc cyclone[Ncyc]; void cycintr(int); #define CYCLONE VMEA24SUP(Comm, 0x10000); /* * Commands */ Cycmsg** cycsend(Commcyc *h, Cycmsg *m) { Cycmsg **mp; lock(h); mp = (Cycmsg**)&h->addr->reqstq[h->wi]; *mp = (Cycmsg*)MP2VME(m); h->wi++; if(h->wi >= NRQ) h->wi = 0; unlock(h); return mp; } void cycwait(Cycmsg **mp) { ulong l; l = 0; while(*mp){ delay(0); /* just a subroutine call; stay off VME */ if(++l > 10*1000*1000){ l = 0; panic("cycsend blocked"); } } return; } /* * reset all cyclone boards */ void cycreset(void) { int i; Commcyc *cp; for(cp=cyclone,i=0; iaddr = CYCLONE+i; /* * Write queue is at end of cyclone memory */ cp->vec = Vmevec+i; setvmevec(cp->vec, cycintr); } } void cycinit(void) { } /* * enable the device for interrupts, spec is the device number */ Chan* cycattach(char *spec) { int i; Chan *c; i = strtoul(spec, 0, 0); if(i >= Ncyc) error(Ebadarg); c = devattach('C', spec); c->dev = i; c->qid.path = CHDIR; c->qid.vers = 0; return c; } Chan* cycclone(Chan *c, Chan *nc) { return devclone(c, nc); } int cycwalk(Chan *c, char *name) { return devwalk(c, name, cycdir, NCYCDIR, devgen); } void cycstat(Chan *c, char *dp) { devstat(c, dp, cycdir, NCYCDIR, devgen); } Chan* cycopen(Chan *c, int omode) { Commcyc *cp; Cycmsg *mp, **cmp; if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eperm); }else if(c->qid.path == Qcyc){ cp = &cyclone[c->dev]; if(!canlock(&cp->busy)) error(Einuse); /* * Clear communications region */ memset(cp->addr->reqstq, 0, NRQ*sizeof(ulong)); cp->addr->reqstp = 0; memset(cp->addr->replyq, 0, NRQ*sizeof(ulong)); cp->addr->replyp = 0; /* * Issue reset */ cp->wi = 0; cp->ri = 0; mp = &u->kcyc; mp->cmd = Ureset; cmp = cycsend(cp, &((User*)(u->p->upage->pa|KZERO))->kcyc); cycwait(cmp); delay(100); print("reset\n"); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void cyccreate(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); error(Eperm); } void cycclose(Chan *c) { Commcyc *cp; Cycmsg **cmp; cp = &cyclone[c->dev]; if(c->qid.path != CHDIR){ u->kcyc.cmd = Ureboot; cmp = cycsend(cp, &((User*)(u->p->upage->pa|KZERO))->kcyc); cycwait(cmp); unlock(&cp->busy); } } int cycmsgintr(Cycmsg *hm) { return hm->intr; } /* * 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 cycread(Chan *c, void *buf, long n, ulong offset) { User *pu; Commcyc *cp; Cycmsg *mp, **cmp; ulong l, m, isflush; cp = &cyclone[c->dev]; switch(c->qid.path & ~CHDIR){ case Qdir: return devdirread(c, buf, n, cycdir, NCYCDIR, devgen); case Qcyc: if(n > sizeof cp->buf){ print("cyclone bufsize %d %d\n", n, sizeof cp->buf); error(Egreg); } pu = (User*)(u->p->upage->pa|KZERO); if((((ulong)buf)&(KSEGM|3)) == KSEG0){ /* * use supplied buffer, no need to lock for reply */ mp = &pu->kcyc; mp->cmd = Uread; mp->param[0] = MP2VME(buf); mp->param[1] = n; mp->param[2] = 0; /* reply checksum */ mp->param[3] = 0xdeadbeef; /* reply count */ mp->intr = 0; cycsend(cp, mp); while(waserror()) ; sleep(&mp->r, cycmsgintr, mp); poperror(); m = mp->param[3]; if(m==0 || m>n){ print("devcyc: count 0x%lux 0x%lux\n", m, n); error(Egreg); } } else{ /* * use cyclone buffer. lock the buffer until the reply */ mp = &pu->ucyc; qlock(&cp->buflock); mp->cmd = Uread; mp->param[0] = MP2VME(cp->buf); mp->param[1] = n; mp->param[2] = 0; /* reply checksum */ mp->param[3] = 0; /* reply count */ mp->intr = 0; cmp = cycsend(cp, mp); cycwait(cmp); l = 100*1000*1000; do m = mp->param[3]; while(m==0 && --l>0); if(m==0 || m>n){ print("devcyc: count %ld %ld\n", m, n); qunlock(&cp->buflock); error(Egreg); } memmove(buf, cp->buf, m); qunlock(&cp->buflock); } return m; } print("devcyc read unk\n"); error(Egreg); return 0; } long cycwrite(Chan *c, void *buf, long n, ulong offset) { User *pu; Commcyc *cp; Cycmsg *mp, **cmp; cp = &cyclone[c->dev]; switch(c->qid.path & ~CHDIR){ case Qdir: return devdirread(c, buf, n, cycdir, NCYCDIR, devgen); case Qcyc: if(n > sizeof cp->buf){ print("cyclone write bufsize\n"); error(Egreg); } pu = (User*)(u->p->upage->pa|KZERO); if((((ulong)buf)&(KSEGM|3)) == KSEG0){ /* * use supplied buffer, no need to lock for reply */ mp = &pu->kcyc; mp->cmd = Uwrite; mp->param[0] = MP2VME(buf); mp->param[1] = n; mp->param[2] = 0; cmp = cycsend(cp, mp); cycwait(cmp); }else{ /* * use cyclone buffer. lock the buffer until the reply */ mp = &pu->ucyc; qlock(&cp->buflock); memmove(cp->buf, buf, n); mp->cmd = Uwrite; mp->param[0] = MP2VME(cp->buf); mp->param[1] = n; mp->param[2] = 0; cmp = cycsend(cp, mp); cycwait(cmp); qunlock(&cp->buflock); } return n; } print("cyclone write unk\n"); error(Egreg); return 0; } void cycremove(Chan *c) { USED(c); error(Eperm); } void cycwstat(Chan *c, char *dp) { USED(c, dp); error(Eperm); } void cycintr(int vec) { Cycmsg *cm; Commcyc *h; ulong l, n, *r; h = &cyclone[vec - Vmevec]; if(h&cyclone[Ncyc]){ print("bad cyclone vec\n"); return; } r = h->addr->replyq; for(;;) { l = r[h->ri]; if(l == 0) break; r[h->ri++] = 0; if(h->ri >= NRQ) h->ri = 0; cm = (Cycmsg*)VME2MP(l); cm->intr = 1; n = cm->param[3]; if(n==0 || n > 10000) print("cycintr count 0x%lux\n", n); wakeup(&cm->r); } } . ## diffname power/devcyc.c 1992/0618 ## diff -e /n/bootesdump/1992/0613/sys/src/9/power/devcyc.c /n/bootesdump/1992/0618/sys/src/9/power/devcyc.c 207d ## diffname power/devcyc.c 1992/0622 ## diff -e /n/bootesdump/1992/0618/sys/src/9/power/devcyc.c /n/bootesdump/1992/0622/sys/src/9/power/devcyc.c 8d ## diffname power/devcyc.c 1992/0711 ## diff -e /n/bootesdump/1992/0622/sys/src/9/power/devcyc.c /n/bootesdump/1992/0711/sys/src/9/power/devcyc.c 301a USED(offset); . 225a USED(offset); . 224c ulong l, m; . ## diffname power/devcyc.c 1992/1227 ## diff -e /n/bootesdump/1992/0711/sys/src/9/power/devcyc.c /n/bootesdump/1992/1227/sys/src/9/power/devcyc.c 165a /* Set the interrupt vector for the cyclone to pick up */ cp->addr->vmevec = Vmevec; . ## diffname power/devcyc.c 1993/0501 ## diff -e /n/bootesdump/1992/1227/sys/src/9/power/devcyc.c /n/fornaxdump/1993/0501/sys/src/brazil/power/devcyc.c 335c mp = up->ucyc; . 322c mp = up->kcyc; . 317d 302d 283a . 270c mp = up->ucyc; . 246c mp = up->kcyc; . 240d 227d 224c ulong l, m; . 202,203c up->kcyc->cmd = Ureboot; cmp = cycsend(cp, up->kcyc); . 176c cmp = cycsend(cp, up->kcyc); . 174c mp = up->kcyc; . 10c #include "/sys/src/fs/cyc/comm.h" . ## diffname power/devcyc.c 1995/0108 # deleted ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/power/devcyc.c /n/fornaxdump/1995/0108/sys/src/brazil/power/devcyc.c 1,398d