// // channel element driver // #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "msaturn.h" enum{ Ucuunknown = 0, Ucu64, Ndsp = 16, Cedead = 0, Cereset, Celoaded, Cerunning, Qdir = 0, Qctl, Qce, Cpldbase = Saturn + 0x6000000, Cplducuversion_ucu = 0x1c, Cebase = Saturn + 0x3000000, Cesize = 0x100000, }; typedef struct Cpld Cpld; struct Cpld{ uchar led; uchar fpga1; uchar slotid; uchar version; uchar watchdog; uchar spi; uchar asicreset; uchar dspreset; uchar generalreset; uchar ucuversion; uchar fpga2; }; typedef struct Circbuf Circbuf; struct Circbuf{ uchar *nextin; uchar *nextout; uchar *start; uchar *end; }; typedef struct Dsp Dsp; struct Dsp{ Ref; int state; Circbuf *cb; }; typedef struct Ce Ce; struct Ce{ int ucutype; Ce *ces[Ndsp]; }; static Cpld*cpld = (Cpld*)Cpldbase; static Ce ce; static void ceinit(void) { if(cpld->ucuversion & Cplducuversion_ucu) ce.ucutype = Ucu64; else{ print("ceinit: unsuppoerted UCU\n"); return; } } static Chan* ceattach(char*spec) { return devattach('C', spec); } #define DEV(q) ((int)(((q).path >> 8) & 0xff)) #define TYPE(q) ((int)((q).path & 0xff)) #define QID(d, t) ((((d) & 0xff) << 8) | (t)) static int cegen(Chan*c, char*, Dirtab*, int, int i, Dir*dp) { Qid qid; switch(TYPE(c->qid)){ case Qdir: if(i == DEVDOTDOT){ mkqid(&qid, QID(0, Qdir), 0, QTDIR); devdir(c, qid, "#C", 0, eve, 0555, dp); return 1; } if(i == 0){ mkqid(&qid, QID(-1, Qctl), 0, QTFILE); devdir(c, qid, "cectl", 0, eve, 0644, dp); return 1; } if (--i >= Ndsp) return -1; mkqid(&qid, QID(Qce, i), 0, QTFILE); snprint(up->genbuf, sizeof(up->genbuf), "ce%d", i); devdir(c, qid, up->genbuf, 0, eve, 0644, dp); return 1; default: return -1; } } static Walkqid * cewalk(Chan*c, Chan*nc, char**name, int nname) { return devwalk(c, nc, name, nname, 0, 0, cegen); } static int cestat(Chan*c, uchar*db, int n) { return devstat(c, db, n, 0, 0, cegen); } static Chan* ceopen(Chan*c, int omode) { c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } static void ceclose(Chan*) {} static long ceread(Chan*c, void*a, long n, vlong) { switch(TYPE(c->qid)){ case Qdir: return devdirread(c, a, n, 0, 0, cegen); default: error("unsupported operation"); } return 0; } static long cewrite(Chan*, void*, long, vlong) { return 0; } Dev cedevtab = { 'C', "channel element", devreset, ceinit, devshutdown, ceattach, cewalk, cestat, ceopen, devcreate, ceclose, ceread, devbread, cewrite, devbwrite, devremove, devwstat, devpower, };