summaryrefslogtreecommitdiff
path: root/appl/cmd/auxi/pcmcia.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auxi/pcmcia.b')
-rw-r--r--appl/cmd/auxi/pcmcia.b491
1 files changed, 491 insertions, 0 deletions
diff --git a/appl/cmd/auxi/pcmcia.b b/appl/cmd/auxi/pcmcia.b
new file mode 100644
index 00000000..d5d998b0
--- /dev/null
+++ b/appl/cmd/auxi/pcmcia.b
@@ -0,0 +1,491 @@
+implement Pcmcia;
+
+#
+# Copyright © 1995-2001 Lucent Technologies Inc. All rights reserved.
+# Revisions Copyright © 2001-2003 Vita Nuova Holdings Limited. All rights reserved.
+#
+
+include "sys.m";
+ sys: Sys;
+ print, fprint: import sys;
+
+include "draw.m";
+
+Pcmcia: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+End: con 16rFF;
+
+fd: ref Sys->FD;
+stderr: ref Sys->FD;
+pos := 0;
+
+hex := 0;
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ if(args != nil)
+ args = tl args;
+ if(args != nil && hd args == "-x"){
+ hex = 1;
+ args = tl args;
+ }
+
+ file := "#y/pcm0attr";
+ if(args != nil)
+ file = hd args;
+
+ fd = sys->open(file, Sys->OREAD);
+ if(fd == nil)
+ fatal(sys->sprint("can't open %s: %r", file));
+
+ for(next := 0; next >= 0;)
+ next = dtuple(next);
+}
+
+fatal(s: string)
+{
+ fprint(stderr, "pcmcia: %s\n", s);
+ raise "fail:error";
+}
+
+readc(): int
+{
+ x := array[1] of byte;
+ sys->seek(fd, big(2*pos), 0);
+ pos++;
+ rv := sys->read(fd, x, 1);
+ if(rv != 1){
+ if(rv < 0)
+ sys->print("readc err: %r\n");
+ return -1;
+ }
+ v := int x[0];
+ if(hex)
+ print("%2.2ux ", v);
+ return v;
+}
+
+dtuple(next: int): int
+{
+ pos = next;
+ if((ttype := readc()) < 0)
+ return -1;
+ if(ttype == End)
+ return -1;
+ if((link := readc()) < 0)
+ return -1;
+ case ttype {
+ * => print("unknown tuple type #%2.2ux\n", ttype);
+ 16r01 => tdevice(ttype, link);
+ 16r15 => tvers1(ttype, link);
+ 16r17 => tdevice(ttype, link);
+ 16r1A => tcfig(ttype, link);
+ 16r1B => tentry(ttype, link);
+ }
+ if(link == End)
+ next = -1;
+ else
+ next = next+2+link;
+ return next;
+}
+
+speedtab := array[16] of {
+0 => 0,
+1 => 250,
+2 => 200,
+3 => 150,
+4 => 100,
+};
+
+mantissa := array[16] of {
+1 => 10,
+2 => 12,
+3 => 13,
+4 => 15,
+5 => 20,
+6 => 25,
+7 => 30,
+8 => 35,
+9 => 40,
+10=> 45,
+11=> 50,
+12=> 55,
+13=> 60,
+14=> 70,
+15=> 80,
+};
+
+exponent := array[] of {
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+};
+
+typetab := array [256] of {
+1=> "Masked ROM",
+2=> "PROM",
+3=> "EPROM",
+4=> "EEPROM",
+5=> "FLASH",
+6=> "SRAM",
+7=> "DRAM",
+16rD=> "IO+MEM",
+* => "Unknown",
+};
+
+getlong(size: int): int
+{
+ x := 0;
+ for(i := 0; i < size; i++){
+ if((c := readc()) < 0)
+ break;
+ x |= c<<(i*8);
+ }
+ return x;
+}
+
+tdevice(dtype: int, tlen: int)
+{
+ while(tlen > 0){
+ if((id := readc()) < 0)
+ return;
+ tlen--;
+ if(id == End)
+ return;
+
+ speed := id & 16r7;
+ ns := 0;
+ if(speed == 16r7){
+ if((speed = readc()) < 0)
+ return;
+ tlen--;
+ if(speed & 16r80){
+ if((aespeed := readc()) < 0)
+ return;
+ ns = 0;
+ } else
+ ns = (mantissa[(speed>>3)&16rF]*exponent[speed&7])/10;
+ } else
+ ns = speedtab[speed];
+
+ ttype := id>>4;
+ if(ttype == 16rE){
+ if((ttype = readc()) < 0)
+ return;
+ tlen--;
+ }
+ tname := typetab[ttype];
+ if(tname == nil)
+ tname = "unknown";
+
+ if((size := readc()) < 0)
+ return;
+ tlen--;
+ bytes := ((size>>3)+1) * 512 * (1<<(2*(size&16r7)));
+
+ ttname := "attr device";
+ if(dtype == 1)
+ ttname = "device";
+ print("%s %d bytes of %dns %s\n", ttname, bytes, ns, tname);
+ }
+}
+
+tvers1(nil: int, tlen: int)
+{
+ if((major := readc()) < 0)
+ return;
+ tlen--;
+ if((minor := readc()) < 0)
+ return;
+ tlen--;
+ print("version %d.%d\n", major, minor);
+ while(tlen > 0){
+ s := "";
+ while(tlen > 0){
+ if((c := readc()) < 0)
+ return;
+ tlen--;
+ if(c == 0)
+ break;
+ if(c == End){
+ if(s != "")
+ print("\t%s<missing null>\n", s);
+ return;
+ }
+ s[len s] = c;
+ }
+ print("\t%s\n", s);
+ }
+}
+
+tcfig(nil: int, nil: int)
+{
+ if((size := readc()) < 0)
+ return;
+ rasize := (size&16r3) + 1;
+ rmsize := ((size>>2)&16rf) + 1;
+ if((last := readc()) < 0)
+ return;
+ caddr := getlong(rasize);
+ cregs := getlong(rmsize);
+
+ print("configuration registers at");
+ for(i := 0; i < 16; i++)
+ if((1<<i) & cregs)
+ print(" (%d) #%ux", i, caddr + i*2);
+ print("\n");
+}
+
+intrname := array[16] of {
+0 => "memory",
+1 => "I/O",
+4 => "Custom 0",
+5 => "Custom 1",
+6 => "Custom 2",
+7 => "Custom 3",
+* => "unknown"
+};
+
+vexp := array[8] of {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+vmant := array[16] of {
+ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+volt(name: string)
+{
+ if((c := readc()) < 0)
+ return;
+ exp := vexp[c&16r7];
+ microv := vmant[(c>>3)&16rf]*exp;
+ while(c & 16r80){
+ if((c = readc()) < 0)
+ return;
+ case c {
+ 16r7d =>
+ break; # high impedence when sleeping
+ 16r7e or 16r7f =>
+ microv = 0; # no connection
+ * =>
+ exp /= 10;
+ microv += exp*(c&16r7f);
+ }
+ }
+ print(" V%s %duV", name, microv);
+}
+
+amps(name: string)
+{
+ if((c := readc()) < 0)
+ return;
+ amps := vexp[c&16r7]*vmant[(c>>3)&16rf];
+ while(c & 16r80){
+ if((c = readc()) < 0)
+ return;
+ if(c == 16r7d || c == 16r7e || c == 16r7f)
+ amps = 0;
+ }
+ if(amps >= 1000000)
+ print(" I%s %dmA", name, amps/100000);
+ else if(amps >= 1000)
+ print(" I%s %duA", name, amps/100);
+ else
+ print(" I%s %dnA", name, amps*10);
+}
+
+power(name: string)
+{
+ print("\t%s: ", name);
+ if((feature := readc()) < 0)
+ return;
+ if(feature & 1)
+ volt("nominal");
+ if(feature & 2)
+ volt("min");
+ if(feature & 4)
+ volt("max");
+ if(feature & 8)
+ amps("static");
+ if(feature & 16r10)
+ amps("avg");
+ if(feature & 16r20)
+ amps("peak");
+ if(feature & 16r40)
+ amps("powerdown");
+ print("\n");
+}
+
+ttiming(name: string, scale: int)
+{
+ if((unscaled := readc()) < 0)
+ return;
+ scaled := (mantissa[(unscaled>>3)&16rf]*exponent[unscaled&7])/10;
+ scaled = scaled * vexp[scale];
+ print("\t%s %dns\n", name, scaled);
+}
+
+timing()
+{
+ if((c := readc()) < 0)
+ return;
+ i := c&16r3;
+ if(i != 3)
+ ttiming("max wait", i);
+ i = (c>>2)&16r7;
+ if(i != 7)
+ ttiming("max ready/busy wait", i);
+ i = (c>>5)&16r7;
+ if(i != 7)
+ ttiming("reserved wait", i);
+}
+
+range(asize: int, lsize: int)
+{
+ address := getlong(asize);
+ alen := getlong(lsize);
+ print("\t\t%ux - %ux\n", address, address+alen);
+}
+
+ioaccess := array[] of {
+ 0 => " no access",
+ 1 => " 8bit access only",
+ 2 => " 8bit or 16bit access",
+ 3 => " selectable 8bit or 8&16bit access",
+};
+
+iospace(c: int): int
+{
+ print("\tIO space %d address lines%s\n", c&16r1f, ioaccess[(c>>5)&3]);
+ if((c & 16r80) == 0)
+ return -1;
+
+ if((c = readc()) < 0)
+ return -1;
+
+ for(i := (c&16rf)+1; i; i--)
+ range((c>>4)&16r3, (c>>6)&16r3);
+ return 0;
+}
+
+iospaces()
+{
+ if((c := readc()) < 0)
+ return;
+ iospace(c);
+}
+
+irq()
+{
+ if((c := readc()) < 0)
+ return;
+ irqs: int;
+ if(c & 16r10){
+ if((irq1 := readc()) < 0)
+ return;
+ if((irq2 := readc()) < 0)
+ return;
+ irqs = irq1|(irq2<<8);
+ } else
+ irqs = 1<<(c&16rf);
+ level := "";
+ if(c & 16r20)
+ level = " level";
+ pulse := "";
+ if(c & 16r40)
+ pulse = " pulse";
+ shared := "";
+ if(c & 16r80)
+ shared = " shared";
+ print("\tinterrupts%s%s%s", level, pulse, shared);
+ for(i := 0; i < 16; i++)
+ if(irqs & (1<<i))
+ print(", %d", i);
+ print("\n");
+}
+
+memspace(asize: int, lsize: int, host: int)
+{
+ alen := getlong(lsize)*256;
+ address := getlong(asize)*256;
+ if(host){
+ haddress := getlong(asize)*256;
+ print("\tmemory address range #%ux - #%ux hostaddr #%ux\n",
+ address, address+alen, haddress);
+ } else
+ print("\tmemory address range #%ux - #%ux\n", address, address+alen);
+}
+
+misc()
+{
+}
+
+tentry(nil: int, nil: int)
+{
+ if((c := readc()) < 0)
+ return;
+ def := "";
+ if(c & 16r40)
+ def = " (default)";
+ print("configuration %d%s\n", c&16r3f, def);
+ if(c & 16r80){
+ if((i := readc()) < 0)
+ return;
+ tname := intrname[i & 16rf];
+ if(tname == "")
+ tname = sys->sprint("type %d", i & 16rf);
+ attrib := "";
+ if(i & 16r10)
+ attrib += " Battery status active";
+ if(i & 16r20)
+ attrib += " Write Protect active";
+ if(i & 16r40)
+ attrib += " Ready/Busy active";
+ if(i & 16r80)
+ attrib += " Memory Wait required";
+ print("\t%s device, %s\n", tname, attrib);
+ }
+ if((feature := readc()) < 0)
+ return;
+ case feature&16r3 {
+ 1 =>
+ power("Vcc");
+ 2 =>
+ power("Vcc");
+ power("Vpp");
+ 3 =>
+ power("Vcc");
+ power("Vpp1");
+ power("Vpp2");
+ }
+ if(feature&16r4)
+ timing();
+ if(feature&16r8)
+ iospaces();
+ if(feature&16r10)
+ irq();
+ case (feature>>5)&16r3 {
+ 1 =>
+ memspace(0, 2, 0);
+ 2 =>
+ memspace(2, 2, 0);
+ 3 =>
+ if((c = readc()) < 0)
+ return;
+ for(i := 0; i <= (c&16r7); i++)
+ memspace((c>>5)&16r3, (c>>3)&16r3, c&16r80);
+ break;
+ }
+ if(feature&16r80)
+ misc();
+}