diff options
Diffstat (limited to 'os/pc/devzt5512.c')
| -rw-r--r-- | os/pc/devzt5512.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/os/pc/devzt5512.c b/os/pc/devzt5512.c new file mode 100644 index 00000000..af189fff --- /dev/null +++ b/os/pc/devzt5512.c @@ -0,0 +1,308 @@ +/* + * Namespace Interface for Ziatech 5512 System Registers + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + + +enum{ + Qdir, + Qsysid, + Qwatchdog, + Qledctl, + Qpower, + Qswitch, + Qstat, +}; + +static +Dirtab zttab[]={ + ".", {Qdir,0,QTDIR}, 0, 0555, + "id", {Qsysid, 0}, 0, 0444, + "watchdog", {Qwatchdog, 0}, 0, 0600, + "ledctl", {Qledctl, 0}, 0, 0666, + "powerstat", {Qpower, 0}, 0, 0444, + "switch", {Qswitch, 0}, 0, 0444, + "stat", {Qstat, 0}, 0, 0444, +}; + +extern int watchdog; +void +watchdog_strobe(void) +{ + uchar sysreg; + + sysreg = inb(0x78); + sysreg &= (~1); + outb(0x78, sysreg); /* disable/strobe watchdog */ + sysreg |= 1; + outb(0x78, sysreg); /* enable watchdog */ +} + +static void +ztreset(void) /* default in dev.c */ +{ + uchar sysreg; + + if(watchdog) + addclock0link(watchdog_strobe); + /* clear status LEDs */ + sysreg = inb(0xe2); + sysreg &= ~3; /* clear usr1 */ + sysreg &= ~(3 << 2); /* clear usr2 */ + outb(0xe2, sysreg); +} + +static Chan* +ztattach(char* spec) +{ + return devattach('Z', spec); +} + +static int +ztwalk(Chan* c, char* name) +{ + return devwalk(c, name, zttab, nelem(zttab), devgen); +} + +static void +ztstat(Chan* c, char* db) +{ + devstat(c, db, zttab, nelem(zttab), devgen); +} + +static Chan* +ztopen(Chan* c, int omode) +{ + return devopen(c, omode, zttab, nelem(zttab), devgen); +} + +static void +ztclose(Chan* c) +{ + USED(c); +} + +static long +ztread(Chan* c, void* a, long n, vlong offset) +{ + uchar sysreg; + char buf[256]; + + USED(offset); + + switch(c->qid.path & ~CHDIR) { + case Qdir: + return devdirread(c, a, n, zttab, nelem(zttab), devgen); + case Qsysid: { + ulong rev; + sysreg = inb(0xe3); + rev = (ulong) (sysreg & 0x7f); + sysreg = inb(0xe2); + sprint(buf, "Board Rev: %lud\nSerial #: %lud\n", rev, (ulong)(sysreg >> 4)); + return readstr(offset, a, n, buf); + }; + case Qwatchdog: + sysreg = inb(0x78); + if((sysreg & 1) == 1) { + n = readstr(offset, a, n, "enabled"); + } else { + n = readstr(offset, a, n, "disabled"); + } + return n; + case Qledctl: + { + char usr1[6], usr2[6]; + sysreg = inb(0xe2); + switch( sysreg & 3 ) { + case 0: + case 3: + sprint(usr1, "off"); + break; + case 1: + sprint(usr1, "red"); + break; + case 2: + sprint(usr1, "green"); + }; + switch( (sysreg >> 2) & 3) { + case 0: + case 3: + sprint(usr2, "off"); + break; + case 1: + sprint(usr2, "red"); + break; + case 2: + sprint(usr2, "green"); + }; + sprint(buf, "usr1: %s\nusr2: %s\n",usr1, usr2); + return readstr(offset, a, n, buf); + }; + case Qpower: + sysreg = inb(0xe4); + sprint(buf, "DEG#: %d\nFAL#: %d\n", (sysreg & 2), (sysreg & 1)); + return readstr(offset, a, n, buf); + case Qswitch: + sysreg = inb(0xe4); + sprint(buf, "%d %d %d %d", (sysreg & (1<<6)), (sysreg & (1<<5)), (sysreg & (1<<4)), (sysreg & (1<<3))); + return readstr(offset, a, n, buf); + case Qstat: { + char bus[10],cpu[20], mode[20], boot[20]; + + sysreg = inb(0xe5); + switch (sysreg & 0x7) { + case 1: + sprint(bus, "66 MHz"); + break; + case 2: + sprint(bus, "60 MHz"); + break; + case 3: + sprint(bus, "50 MHz"); + break; + default: + sprint(bus, "unknown"); + }; + switch ((sysreg>>3)&0x7) { + case 0: + sprint(cpu, "75, 90, 100 MHz"); + break; + case 1: + sprint(cpu, "120, 133 MHz"); + break; + case 2: + sprint(cpu, "180, 200 MHz"); + break; + case 3: + sprint(cpu, "150, 166 MHz"); + default: + sprint(cpu, "unknown"); + }; + if(sysreg & (1<<6)) + sprint(mode, "Port 80 test mode"); + else + sprint(mode, "Normal decode"); + if(sysreg & (1<<7)) + sprint(boot,"EEPROM"); + else + sprint(boot,"Flash"); + sprint(buf,"Bus Frequency: %s\nPentium: %s\nTest Mode Status: %s\nBIOS Boot ROM: %s\n", + bus, cpu, mode, boot); + return readstr(offset, a, n, buf); + }; + default: + n=0; + break; + } + return n; +} + + + +static long +ztwrite(Chan* c, void *vp, long n, vlong offset) +{ + uchar sysreg; + char buf[256]; + char *a; + int nf; + char *fields[3]; + + a = vp; + if(n >= sizeof(buf)) + n = sizeof(buf)-1; + strncpy(buf, a, n); + buf[n] = 0; + + USED(a, offset); + + switch(c->qid.path & ~CHDIR){ + case Qwatchdog: + sysreg = inb(0x78); + + if(strncmp(buf, "enable", 6) == 0) { + if((sysreg & 1) != 1) + addclock0link(watchdog_strobe); + break; + } + n = 0; + error(Ebadarg); + case Qledctl: + nf = getfields(buf, fields, 3, 1, " \t\n"); + if(nf < 2) { + error(Ebadarg); + n = 0; + break; + } + sysreg = inb(0xe2); + USED(sysreg); + if(strncmp(fields[0],"usr1", 4)==0) { + sysreg &= ~3; + if(strncmp(fields[1], "off", 3)==0) { + outb(0xe2, sysreg); + break; + } + if(strncmp(fields[1], "red", 3)==0) { + sysreg |= 1; + outb(0xe2, sysreg); + break; + } + if(strncmp(fields[1], "green", 5)==0) { + sysreg |= 2; + outb(0xe2, sysreg); + break; + } + } + if(strncmp(fields[0],"usr2", 4)==0) { + sysreg &= ~(3 << 2); + if(strncmp(fields[1], "off", 3)==0) { + outb(0xe2, sysreg); + break; + } + if(strncmp(fields[1], "red", 3)==0) { + sysreg |= (1 << 2); + outb(0xe2, sysreg); + break; + } + if(strncmp(fields[1], "green", 5)==0) { + sysreg |= (2 << 2); + outb(0xe2, sysreg); + break; + } + } + n = 0; + error(Ebadarg); + default: + error(Ebadusefd); + } + return n; +} + + + +Dev zt5512devtab = { /* defaults in dev.c */ + 'Z', + "Ziatech5512", + + ztreset, /* devreset */ + devinit, /* devinit */ + ztattach, + devdetach, + devclone, /* devclone */ + ztwalk, + ztstat, + ztopen, + devcreate, /* devcreate */ + ztclose, + ztread, + devbread, /* devbread */ + ztwrite, + devbwrite, /* devbwrite */ + devremove, /* devremove */ + devwstat, /* devwstat */ +}; |
