Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

//
// 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,
};