plan 9 kernel history: overview | file list | diff list |
1990/0227/power/devhs.c (diff list | history)
power/devhs.c on 1990/0227 | ||
1990/0227 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #include "io.h" enum { Maxtxburst= 1024, /* maximum transmit burst size */ Vmevec= 0xd0, /* vme vector for interrupts */ Intlevel= 5, /* level to interrupt on */ }; struct hsvmestats { ulong parity; ulong rintr; ulong tintr; } hsvmestats; #define ALIVE 0x0001 #define IENABLE 0x0004 #define EXOFLOW 0x0008 #define IRQ 0x0010 #define EMUTE 0x0020 #define EPARITY 0x0040 #define EFRAME 0x0080 #define EROFLOW 0x0100 #define REF 0x0800 #define XFF 0x4000 #define XHF 0x8000 #define FORCEW 0x0008 #define IPL(x) ((x)<<5) #define NORESET 0xFF00 #define RESET 0x0000 #define CTL 0x0100 #define CHNO 0x0200 #define TXEOD 0x0400 #define NND 0x8000 Rendez hsvmer; #define DELAY(n) { \ register int N = 12*(n); \ while (--N > 0); \ } static void hsvmeintr(int); void hsvmerestart(struct hsvme *addr) { addr->csr = RESET; wbflush(); DELAY(20000); /* * set interrupt vector * turn on addrice * set forcew to a known value * interrupt on level `Intlevel' */ addr->vector = 0xd0; addr->csr = NORESET|IPL(Intlevel)|IENABLE|ALIVE; wbflush(); DELAY(500); addr->csr = NORESET|IPL(Intlevel)|FORCEW|IENABLE|ALIVE; wbflush(); DELAY(500); } void hsvmereset(void) { struct hsvme *addr; addr = HSVME; addr->csr = RESET; wbflush(); DELAY(20000); /* * routine to call on interrupt */ setvmevec(Vmevec, hsvmeintr); } void hsvmeinit(void) { } /* * enable the device for interrupts */ static int never(void *arg) { return 0; } Chan* hsvmeattach(char *spec) { struct hsvme *addr; addr = HSVME; hsvmerestart(addr); print("hsvme csr %ux\n", addr->csr); return devattach('h', spec); } Chan* hsvmeclone(Chan *c, Chan *nc) { return devclone(c, nc); } int hsvmewalk(Chan *c, char *name) { if(c->qid != CHDIR) return 0; if(strcmp(name, "hsvme") == 0){ c->qid = 1; return 1; } return 0; } void hsvmestat(Chan *c, char *dp) { print("hsvmestat\n"); error(0, Egreg); } Chan* hsvmeopen(Chan *c, int omode) { c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void hsvmecreate(Chan *c, char *name, int omode, ulong perm) { error(0, Eperm); } void hsvmeclose(Chan *c) { } long hsvmeread(Chan *c, void *buf, long n) { error(0, Egreg); return 0; } long hsvmewrite(Chan *c, void *buf, long n) { error(0, Egreg); return 0; } void hsvmeremove(Chan *c) { error(0, Eperm); } void hsvmewstat(Chan *c, char *dp) { error(0, Eperm); } void hsvmeuserstr(Error *e, char *buf) { consuserstr(e, buf); } void hsvmeerrstr(Error *e, char *buf) { rooterrstr(e, buf); } static void hsvmeintr(int vec) { ushort csr; struct hsvme *addr; print("hsvme intr\n"); addr = HSVME; wbflush(); csr = addr->csr; do { if (addr->csr & REF) { hsvmestats.rintr++; print("hsvme rintr\n"); } if (addr->csr & XHF) { hsvmestats.tintr++; print("hsvme tintr\n"); } if ((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)) { hsvmestats.parity++; hsvmerestart(addr); print("hsvme %ux: reset, csr = 0x%x\n", HSVME, csr); } wbflush(); } while ((csr = addr->csr) & REF); } |