#include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #include "io.h" typedef struct Hotrod Hotrod; typedef struct Device Device; enum { Vmevec= 0xd2, /* vme vector for interrupts */ Intlevel= 5, /* level to interrupt on */ Nhotrod= 2, }; /* * the hotrod fiber interface responds to 1MB * of either user or supervisor accesses at: * 0x30000000 to 0x300FFFFF in A32 space * and 0xB00000 to 0xBFFFFF in A24 space */ struct Device { ulong mem[1024*1024/sizeof(ulong)]; }; #define HOTROD VMEA24SUP(Device, 0xB00000) struct Hotrod { QLock; Device *addr; int vec; char name[NAMELEN]; }; Hotrod hotrod[Nhotrod]; static void hotrodintr(int); int hotrodgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) { if(i || c->dev>=Nhotrod) return -1; devdir(c, 0, hotrod[c->dev].name, sizeof(Device), 0666, dp); return 1; } /* * reset all hotrod boards */ void hotrodreset(void) { int i; Hotrod *hp; for(i=0; i= Nhotrod) error(0, Ebadarg); c = devattach('H', spec); c->dev = i; c->qid = CHDIR; return c; } Chan* hotrodclone(Chan *c, Chan *nc) { return devclone(c, nc); } int hotrodwalk(Chan *c, char *name) { return devwalk(c, name, 0, 0, hotrodgen); } void hotrodstat(Chan *c, char *dp) { devstat(c, dp, 0, 0, hotrodgen); } Chan* hotrodopen(Chan *c, int omode) { if(c->qid == CHDIR){ if(omode != OREAD) error(0, Eperm); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void hotrodcreate(Chan *c, char *name, int omode, ulong perm) { error(0, Eperm); } void hotrodclose(Chan *c) { } /* * read the hotrod memory */ long hotrodread(Chan *c, void *buf, long n) { Hotrod *hp; Device *dp; ulong *from; ulong *to; ulong *end; if(c->qid&CHDIR) return devdirread(c, buf, n, 0, 0, hotrodgen); /* * allow full word access only */ if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1))) error(0, Ebadarg); 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++; } qunlock(hp); return n; } /* * write hotrod memory */ long hotrodwrite(Chan *c, void *buf, long n) { Hotrod *hp; Device *dp; ulong *from; ulong *to; ulong *end; /* * allow full word access only */ if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1))) error(0, Ebadarg); 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; } void hotrodremove(Chan *c) { error(0, Eperm); } void hotrodwstat(Chan *c, char *dp) { error(0, Eperm); } void hotroduserstr(Error *e, char *buf) { consuserstr(e, buf); } void hotroderrstr(Error *e, char *buf) { rooterrstr(e, buf); } static void hotrodintr(int vec) { Hotrod *hp; print("hotrod%d interrupt\n", vec - Vmevec); hp = &hotrod[vec - Vmevec]; if(hp < hotrod || hp > &hotrod[Nhotrod]){ print("bad hotrod vec\n"); return; } }