summaryrefslogtreecommitdiff
path: root/appl/cmd/auxi
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auxi')
-rw-r--r--appl/cmd/auxi/cpuslave.b79
-rw-r--r--appl/cmd/auxi/digest.b91
-rw-r--r--appl/cmd/auxi/fpgaload.b67
-rw-r--r--appl/cmd/auxi/mangaload.b362
-rw-r--r--appl/cmd/auxi/mkfile24
-rw-r--r--appl/cmd/auxi/pcmcia.b491
-rw-r--r--appl/cmd/auxi/rdbgsrv.b222
-rw-r--r--appl/cmd/auxi/rstyxd.b114
8 files changed, 1450 insertions, 0 deletions
diff --git a/appl/cmd/auxi/cpuslave.b b/appl/cmd/auxi/cpuslave.b
new file mode 100644
index 00000000..66b409ac
--- /dev/null
+++ b/appl/cmd/auxi/cpuslave.b
@@ -0,0 +1,79 @@
+implement CPUslave;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+ draw: Draw;
+ Context, Display, Screen: import draw;
+include "arg.m";
+
+include "sh.m";
+
+stderr: ref Sys->FD;
+
+CPUslave: module
+{
+ init: fn(ctxt: ref Context, args: list of string);
+};
+
+usage()
+{
+ sys->fprint(stderr, "usage: cpuslave [-s screenid] command args\n");
+ raise "fail:usage";
+}
+
+init(nil: ref Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ draw = load Draw Draw->PATH;
+
+ arg := load Arg Arg->PATH;
+ if (arg == nil) {
+ sys->fprint(stderr, "cpuslave: cannot load %s: %r\n", Arg->PATH);
+ raise "fail:bad module";
+ }
+ screenid := -1;
+ arg->init(args);
+ while ((opt := arg->opt()) != 0) {
+ if (opt != 's' || (a := arg->arg()) == nil)
+ usage();
+ screenid = int a;
+ }
+ args = arg->argv();
+ if(args == nil)
+ usage();
+
+ file := hd args + ".dis";
+ cmd := load Command file;
+ if(cmd == nil)
+ cmd = load Command "/dis/"+file;
+ if(cmd == nil){
+ sys->fprint(stderr, "cpuslave: can't load %s: %r\n", hd args);
+ raise "fail:bad command";
+ }
+
+ ctxt: ref Context;
+ if (screenid >= 0) {
+ display := Display.allocate(nil);
+ if(display == nil){
+ sys->fprint(stderr, "cpuslave: can't initialize display: %r\n");
+ raise "fail:no display";
+ }
+
+ screen: ref Screen;
+ if(screenid >= 0){
+ screen = display.publicscreen(screenid);
+ if(screen == nil){
+ sys->fprint(stderr, "cpuslave: cannot access screen %d: %r\n", screenid);
+ raise "fail:bad screen";
+ }
+ }
+
+ ctxt = ref Context;
+ ctxt.screen = screen;
+ ctxt.display = display;
+ }
+
+ spawn cmd->init(ctxt, args);
+}
diff --git a/appl/cmd/auxi/digest.b b/appl/cmd/auxi/digest.b
new file mode 100644
index 00000000..108de205
--- /dev/null
+++ b/appl/cmd/auxi/digest.b
@@ -0,0 +1,91 @@
+implement Digest;
+
+#
+# read a classifier example file and write its digest
+#
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+include "strokes.m";
+ strokes: Strokes;
+ Classifier, Penpoint, Stroke: import strokes;
+ readstrokes: Readstrokes;
+ writestrokes: Writestrokes;
+
+include "arg.m";
+
+Digest: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+usage()
+{
+ sys->fprint(sys->fildes(2), "Usage: digest [file.cl ...]\n");
+ raise "fail:usage";
+}
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+ strokes = load Strokes Strokes->PATH;
+ if(strokes == nil)
+ nomod(Strokes->PATH);
+ strokes->init();
+ readstrokes = load Readstrokes Readstrokes->PATH;
+ if(readstrokes == nil)
+ nomod(Readstrokes->PATH);
+ readstrokes->init(strokes);
+ writestrokes = load Writestrokes Writestrokes->PATH;
+ if(writestrokes == nil)
+ nomod(Writestrokes->PATH);
+ writestrokes->init(strokes);
+
+ arg := load Arg Arg->PATH;
+ if(arg == nil)
+ nomod(Arg->PATH);
+ arg->init(args);
+ while((opt := arg->opt()) != 0)
+ case opt {
+ * =>
+ usage();
+ }
+ args = arg->argv();
+ arg = nil;
+
+ for(; args != nil; args = tl args){
+ ofile := file := hd args;
+ n := len file;
+ if(n >= 3 && ofile[n-3:] == ".cl")
+ ofile = ofile[0:n-3];
+ ofile += ".clx";
+ (err, rec) := readstrokes->read_classifier(hd args, 1, 0);
+ if(err != nil)
+ error(sys->sprint("error reading classifier from %s: %s", file, err));
+ fd := sys->create(ofile, Sys->OWRITE, 8r666);
+ if(fd == nil)
+ error(sys->sprint("can't create %s: %r", file));
+ err = writestrokes->write_digest(fd, rec.cnames, rec.dompts);
+ if(err != nil)
+ error(sys->sprint("error writing digest to %s: %s", file, err));
+ }
+}
+
+nomod(s: string)
+{
+ error(sys->sprint("can't load %s: %r", s));
+}
+
+error(s: string)
+{
+ sys->fprint(sys->fildes(2), "digest: %s\n", s);
+ raise "fail:error";
+}
diff --git a/appl/cmd/auxi/fpgaload.b b/appl/cmd/auxi/fpgaload.b
new file mode 100644
index 00000000..5c37b80b
--- /dev/null
+++ b/appl/cmd/auxi/fpgaload.b
@@ -0,0 +1,67 @@
+implement Fpgaload;
+
+include"sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "arg.m";
+
+Fpgaload: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ arg := load Arg Arg->PATH;
+ if(arg == nil)
+ error(sys->sprint("can't load %s: %r", Arg->PATH));
+ arg->init(args);
+ arg->setusage("fpgaload [-c clock] file.rbf");
+ clock := -1;
+ while((c := arg->opt()) != 0)
+ case c {
+ 'c' =>
+ clock = int arg->earg();
+ if(clock <= 0)
+ error("invalid clock value");
+ * =>
+ arg->usage();
+ }
+ args = arg->argv();
+ if(args == nil)
+ arg->usage();
+ arg = nil;
+
+ fd := sys->open(hd args, Sys->OREAD);
+ if(fd == nil)
+ error(sys->sprint("can't open %s: %r", hd args));
+ ofd := sys->open("#G/fpgaprog", Sys->OWRITE);
+ if(ofd == nil)
+ error(sys->sprint("can't open %s: %r", "#G/fpgaprog"));
+ a := array[128*1024] of byte;
+ while((n := sys->read(fd, a, len a)) > 0)
+ if(sys->write(ofd, a, n) != n)
+ error(sys->sprint("write error: %r"));
+ if(n < 0)
+ error(sys->sprint("read error: %r"));
+ if(clock >= 0)
+ setclock(clock);
+}
+
+setclock(n: int)
+{
+ fd := sys->open("#G/fpgactl", Sys->OWRITE);
+ if(fd == nil)
+ error(sys->sprint("can't open %s: %r", "#G/fpgactl"));
+ if(sys->fprint(fd, "bclk %d", n) < 0)
+ error(sys->sprint("can't set clock to %d: %r", n));
+}
+
+error(s: string)
+{
+ sys->fprint(sys->fildes(2), "fpgaload: %s\n", s);
+ raise "fail:error";
+}
diff --git a/appl/cmd/auxi/mangaload.b b/appl/cmd/auxi/mangaload.b
new file mode 100644
index 00000000..380dd22e
--- /dev/null
+++ b/appl/cmd/auxi/mangaload.b
@@ -0,0 +1,362 @@
+implement Mangaload;
+
+# to do:
+# - set arp entry based on /lib/ndb if necessary
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "ip.m";
+ ip: IP;
+ IPaddr: import ip;
+
+include "timers.m";
+ timers: Timers;
+ Timer: import timers;
+
+include "arg.m";
+
+Mangaload: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+# manga parameters
+FlashBlocksize: con 16r10000;
+FlashSize: con 16r400000; # 4meg for now
+FlashUserArea: con 16r3C0000;
+
+# magic values
+FooterOffset: con 16rFFEC;
+FooterSig: con 16rA0FFFF9F; # ARM flash library
+FileInfosize: con 64;
+FileNamesize: con FileInfosize - 3*4; # x, y, z
+Packetdatasize: con 1500-28; # ether data less IP + ICMP header
+RequestTimeout: con 500;
+Probecount: con 10; # query unit every so many packets
+
+# manga uses extended TFTP ops in ICMP InfoRequest packets
+Tftp_Req: con 0;
+Tftp_Read: con 1;
+Tftp_Write: con 2;
+Tftp_Data: con 3;
+Tftp_Ack: con 4;
+Tftp_Error: con 5;
+Tftp_Last: con 6;
+
+Icmp: adt
+{
+ ttl: int; # time to live
+ src: IPaddr;
+ dst: IPaddr;
+ ptype: int;
+ code: int;
+ id: int;
+ seq: int;
+ data: array of byte;
+ munged: int; # packet received but corrupt
+
+ unpack: fn(b: array of byte): ref Icmp;
+};
+
+# ICMP packet types
+EchoReply: con 0;
+Unreachable: con 3;
+SrcQuench: con 4;
+EchoRequest: con 8;
+TimeExceed: con 11;
+Timestamp: con 13;
+TimestampReply: con 14;
+InfoRequest: con 15;
+InfoReply: con 16;
+
+Nmsg: con 32;
+Interval: con 1000; # ms
+
+debug := 0;
+flashblock := 1; # never 0, that's the boot firmware
+maxfilesize := 8*FlashBlocksize;
+flashlim := FlashSize/FlashBlocksize;
+loadinitrd := 0;
+maxlen := 512*1024;
+mypid := 0;
+Datablocksize: con 4096;
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ timers = load Timers Timers->PATH;
+ ip = load IP IP->PATH;
+ ip->init();
+
+
+ arg := load Arg Arg->PATH;
+ arg->init(args);
+ arg->setusage("mangaload [-48dr] destination file");
+ while((o := arg->opt()) != 0)
+ case o {
+ '4' =>
+ flashlim = 4*1024*1024/FlashBlocksize;
+ '8' =>
+ flashlim = 8*1024*1024/FlashBlocksize;
+ 'r' =>
+ loadinitrd = 1;
+ flashblock = 9;
+ if(flashlim > 4*1024*1024/FlashBlocksize)
+ maxfilesize = 113*FlashBlocksize;
+ else
+ maxfilesize = 50*FlashBlocksize;
+ 'd' =>
+ debug++;
+ }
+ args = arg->argv();
+ if(len args != 2)
+ arg->usage();
+ arg = nil;
+
+ sys->pctl(Sys->NEWPGRP|Sys->FORKFD, nil);
+
+ filename := hd tl args;
+ fd := sys->open(filename, Sys->OREAD);
+ if(fd == nil){
+ sys->fprint(sys->fildes(2), "mangaload: can't open %s: %r\n", filename);
+ raise "fail:open";
+ }
+ (ok, d) := sys->fstat(fd);
+ if(ok < 0){
+ sys->fprint(sys->fildes(2), "mangaload: can't stat %s: %r\n", filename);
+ raise "fail:stat";
+ }
+ if(d.length > big maxfilesize){
+ sys->fprint(sys->fildes(2), "mangaload: file %s too long (must not exceed %d bytes)\n",
+ filename, maxfilesize);
+ raise "fail:size";
+ }
+ filesize := int d.length;
+
+ port := sys->sprint("%d", 16r8695);
+ addr := netmkaddr(hd args, "icmp", port);
+ (rok, c) := sys->dial(addr, port);
+ if(rok < 0){
+ sys->fprint(sys->fildes(2), "mangaload: can't dial %s: %r\n", addr);
+ raise "fail:dial";
+ }
+
+ tpid := timers->init(20);
+
+ pids := chan of int;
+ replies := chan [2] of ref Icmp;
+ spawn reader(c.dfd, replies, pids);
+ rpid := <-pids;
+
+ flashoffset := flashblock * FlashBlocksize;
+
+ # file name first
+ bname := array of byte filename;
+ l := len bname;
+ buf := array[Packetdatasize] of byte;
+ ip->put4(buf, 0, filesize);
+ ip->put4(buf, 4, l);
+ buf[8:] = bname;
+ l += 2*4;
+ buf[l++] = byte 0;
+ ip->put4(buf, l, flashoffset);
+ l += 4;
+ {
+ if(send(c.dfd, buf[0:l], Tftp_Write, 0) < 0)
+ senderr();
+ (op, iseq, data) := recv(replies, 400);
+ sys->print("initial reply: %d %d\n", op, iseq);
+ if(op != Tftp_Ack){
+ why := "no response";
+ if(op == Tftp_Error)
+ why = "manga cannot receive file";
+ sys->fprint(sys->fildes(2), "mangaload: %s\n", why);
+ raise "fail:error";
+ }
+ sys->print("sending %s size %d at address %d (0x%x)\n", filename, filesize, flashoffset, flashoffset);
+ seq := 1;
+ nsent := 0;
+ last := 0;
+ while((n := sys->read(fd, buf, len buf)) >= 0 && !last){
+ last = n != len buf;
+ nretry := 0;
+ Retry:
+ for(;;){
+ if(++nsent%10 == 0){ # probe
+ o = Tftp_Req;
+ send(c.dfd, array[0] of byte, Tftp_Req, seq);
+ (op, iseq, data) = recv(replies, 500);
+ if(debug || op != Tftp_Ack)
+ sys->print("ack reply: %d %d\n", op, iseq);
+ if(op == Tftp_Last || op == Tftp_Error){
+ if(op == Tftp_Last)
+ sys->print("timed out\n");
+ else
+ sys->print("error reply\n");
+ raise "disaster";
+ }
+ if(debug)
+ sys->print("ok\n");
+ continue Retry;
+ }
+ send(c.dfd, buf[0:n], Tftp_Data, seq);
+ (op, iseq, data) = recv(replies, 40);
+ case op {
+ Tftp_Error =>
+ sys->fprint(sys->fildes(2), "mangaload: manga refused data\n");
+ raise "disaster";
+ Tftp_Ack =>
+ if(seq == iseq){
+ seq++;
+ break Retry;
+ }
+ sys->print("sequence error: rcvd %d expected %d\n", iseq, seq);
+ if(iseq > seq){
+ sys->print("unrecoverable sequence error\n");
+ send(c.dfd, array[0] of byte, Tftp_Data, ++seq); # stop manga
+ raise "disaster";
+ }
+ # resend
+ sys->seek(fd, -big ((seq-iseq)*len buf), 1);
+ seq = iseq;
+ Tftp_Last =>
+ seq++;
+ break Retry; # timeout ok: manga doesn't usually reply unless packet lost
+ }
+ }
+ }
+ }exception{
+ * =>
+ ;
+ }
+ kill(rpid);
+ kill(tpid);
+ sys->print("ok?\n");
+}
+
+kill(pid: int)
+{
+ if(pid)
+ sys->fprint(sys->open("#p/"+string pid+"/ctl", Sys->OWRITE), "kill");
+}
+
+senderr()
+{
+ sys->fprint(sys->fildes(2), "mangaload: icmp write failed: %r\n");
+ raise "disaster";
+}
+
+send(fd: ref Sys->FD, data: array of byte, op: int, seq: int): int
+{
+ buf := array[64*1024+512] of {* => byte 0};
+ buf[Odata:] = data;
+ ip->put2(buf, Oseq, seq);
+ buf[Otype] = byte InfoRequest;
+ buf[Ocode] = byte op;
+ if(sys->write(fd, buf, Odata+len data) < Odata+len data)
+ return -1;
+ if(debug)
+ sys->print("sent op=%d seq=%d ld=%d\n", op, seq, len data);
+ return 0;
+}
+
+flush(input: chan of ref Icmp)
+{
+ for(;;)alt{
+ <-input =>
+ ;
+ * =>
+ return;
+ }
+}
+
+recv(input: chan of ref Icmp, msec: int): (int, int, array of byte)
+{
+ t := Timer.start(msec);
+ alt{
+ <-t.timeout =>
+ return (Tftp_Last, 0, nil);
+ ic := <-input =>
+ t.stop();
+ if(ic.ptype == InfoReply)
+ return (ic.code, ic.seq, ic.data);
+ return (Tftp_Last, 0, nil);
+ }
+}
+
+reader(fd: ref Sys->FD, out: chan of ref Icmp, pid: chan of int)
+{
+ pid <-= sys->pctl(0, nil);
+ for(;;){
+ buf := array[64*1024+512] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n <= 0){
+ if(n == 0)
+ sys->werrstr("unexpected eof");
+ break;
+ }
+ ic := Icmp.unpack(buf[0:n]);
+ if(ic != nil){
+ if(debug)
+ sys->print("recv type=%d op=%d seq=%d id=%d\n", ic.ptype, ic.code, ic.seq, ic.id);
+ out <-= ic;
+ }else
+ sys->fprint(sys->fildes(2), "mangaload: corrupt icmp packet rcvd\n");
+ }
+ sys->print("read: %r\n");
+ out <-= nil;
+}
+
+# IP and ICMP packet header
+Ovihl: con 0;
+Otos: con 1;
+Olength: con 2;
+Oid: con Olength+2;
+Ofrag: con Oid+2;
+Ottl: con Ofrag+2;
+Oproto: con Ottl+1;
+Oipcksum: con Oproto+1;
+Osrc: con Oipcksum+2;
+Odst: con Osrc+4;
+Otype: con Odst+4;
+Ocode: con Otype+1;
+Ocksum: con Ocode+1;
+Oicmpid: con Ocksum+2;
+Oseq: con Oicmpid+2;
+Odata: con Oseq+2;
+
+Icmp.unpack(b: array of byte): ref Icmp
+{
+ if(len b < Odata)
+ return nil;
+ ic := ref Icmp;
+ ic.ttl = int b[Ottl];
+ ic.src = IPaddr.newv4(b[Osrc:]);
+ ic.dst = IPaddr.newv4(b[Odst:]);
+ ic.ptype = int b[Otype];
+ ic.code = int b[Ocode];
+ ic.seq = ip->get2(b, Oseq);
+ ic.id = ip->get2(b, Oicmpid);
+ ic.munged = 0;
+ if(len b > Odata)
+ ic.data = b[Odata:];
+ return ic;
+}
+
+netmkaddr(addr, net, svc: string): string
+{
+ if(net == nil)
+ net = "net";
+ (n, nil) := sys->tokenize(addr, "!");
+ if(n <= 1){
+ if(svc== nil)
+ return sys->sprint("%s!%s", net, addr);
+ return sys->sprint("%s!%s!%s", net, addr, svc);
+ }
+ if(svc == nil || n > 2)
+ return addr;
+ return sys->sprint("%s!%s", addr, svc);
+}
diff --git a/appl/cmd/auxi/mkfile b/appl/cmd/auxi/mkfile
new file mode 100644
index 00000000..6d8dfc88
--- /dev/null
+++ b/appl/cmd/auxi/mkfile
@@ -0,0 +1,24 @@
+<../../../mkconfig
+
+TARG=\
+ cpuslave.dis\
+ digest.dis\
+ fpgaload.dis\
+ mangaload.dis\
+ pcmcia.dis\
+ rdbgsrv.dis\
+ rstyxd.dis\
+
+SYSMODULES=\
+ arg.m\
+ bufio.m\
+ draw.m\
+ sh.m\
+ string.m\
+ strokes.m\
+ styx.m\
+ sys.m\
+
+DISBIN=$ROOT/dis/auxi
+
+<$ROOT/mkfiles/mkdis
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();
+}
diff --git a/appl/cmd/auxi/rdbgsrv.b b/appl/cmd/auxi/rdbgsrv.b
new file mode 100644
index 00000000..2a958eee
--- /dev/null
+++ b/appl/cmd/auxi/rdbgsrv.b
@@ -0,0 +1,222 @@
+implement RDbgSrv;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+
+include "styx.m";
+ styx: Styx;
+ Rmsg, Tmsg: import styx;
+
+include "arg.m";
+ arg: Arg;
+
+RDbgSrv: module
+{
+ init: fn(nil: ref Draw->Context, argv: list of string);
+};
+
+debug:= 0;
+dev:= "/dev/eia0";
+speed:= 38400;
+progname: string;
+rpid := 0;
+wpid := 0;
+
+usage()
+{
+ sys->fprint(stderr(), "Usage: rdbgsrv [-d n] [-s speed] [-f dev] mountpoint\n");
+ raise "fail: usage";
+}
+
+init(nil: ref Draw->Context, av: list of string)
+{
+ sys = load Sys Sys->PATH;
+ if(sys == nil)
+ return;
+ styx = load Styx Styx->PATH;
+ if(styx == nil){
+ sys->fprint(stderr(), "rdbgsrv: can't load %s; %r\n", Styx->PATH);
+ raise "fail:load";
+ }
+ arg = load Arg Arg->PATH;
+ if(arg == nil){
+ sys->fprint(stderr(), "rdbgsrv: can't load %s: %r\n", Arg->PATH);
+ raise "fail:load";
+ }
+
+ arg->init(av);
+ progname = arg->progname();
+ while(o := arg->opt())
+ case o {
+ 'd' =>
+ d := arg->arg();
+ if(d == nil)
+ usage();
+ debug = int d;
+ 's' =>
+ s := arg->arg();
+ if(s == nil)
+ usage();
+ speed = int s;
+ 'f' =>
+ s := arg->arg();
+ if(s == nil)
+ usage();
+ dev = s;
+ 'h' =>
+ usage();
+ }
+
+ mtpt := arg->arg();
+ if(mtpt == nil)
+ usage();
+
+ ctl := dev + "ctl";
+ cfd := sys->open(ctl, Sys->OWRITE);
+ if(cfd == nil){
+ sys->fprint(stderr(), "%s: can't open %s: %r\n", progname, ctl);
+ raise "fail: open eia\n";
+ }
+
+ sys->fprint(cfd, "b%d", speed);
+ sys->fprint(cfd, "l8");
+ sys->fprint(cfd, "pn");
+ sys->fprint(cfd, "s1");
+
+ (rfd, wfd) := start(dev);
+ if(rfd == nil){
+ sys->fprint(stderr(), "%s: failed to start protocol\n", progname);
+ raise "fail:proto start";
+ }
+
+ fds := array[2] of ref Sys->FD;
+
+ if(sys->pipe(fds) == -1){
+ sys->fprint(stderr(), "%s: pipe: %r\n", progname);
+ raise "fail:no pipe";
+ }
+
+ if(debug)
+ sys->fprint(stderr(), "%s: starting server\n", progname);
+
+ rc := chan of int;
+ spawn copymsg(fds[1], wfd, "->", rc);
+ rpid = <-rc;
+ spawn copymsg(rfd, fds[1], "<-", rc);
+ wpid = <-rc;
+
+ if(sys->mount(fds[0], nil, mtpt, Sys->MREPL, nil) == -1) {
+ fds[1] = nil;
+ sys->fprint(stderr(), "%s: can't mount on %s: %r\n", progname, mtpt);
+ quit("mount");
+ }
+}
+
+stderr(): ref Sys->FD
+{
+ return sys->fildes(2);
+}
+
+killpid(pid: int)
+{
+ fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE);
+ if(fd != nil)
+ sys->fprint(fd, "kill");
+}
+
+quit(err: string)
+{
+ killpid(rpid);
+ killpid(wpid);
+ if(err != nil)
+ raise "fail:"+err;
+ exit;
+}
+
+start(name:string): (ref Sys->FD, ref Sys->FD)
+{
+ rfd := sys->open(name, Sys->OREAD);
+ wfd := sys->open(name, Sys->OWRITE);
+ if(rfd == nil || wfd == nil)
+ return (nil, nil);
+ if(sys->fprint(wfd, "go") < 0)
+ return (nil, nil);
+ c := array[1] of byte;
+ state := 0;
+ for(;;) {
+ if(sys->read(rfd, c, 1) != 1)
+ return (nil, nil);
+ if(state == 0 && c[0] == byte 'o')
+ state = 1;
+ else if(state == 1 && c[0] == byte 'k')
+ break;
+ else
+ state = 0;
+ }
+ return (rfd, wfd);
+}
+
+copymsg(f: ref Sys->FD, t: ref Sys->FD, dir: string, pidc: chan of int)
+{
+ pidc <-= sys->pctl(0, nil);
+
+ {
+ for(;;) {
+ (msg, err) := styx->readmsg(f, 0);
+ if(msg == nil){
+ sys->fprint(stderr(), "%s: %s: read error: %s\n", progname, dir, err);
+ quit("error");
+ }
+ if(debug &1)
+ trace(dir, msg);
+ if(debug & 2)
+ dump(dir, msg, len msg);
+ if(sys->write(t, msg, len msg) != len msg){
+ sys->fprint(stderr(), "%s: %s: write error: %r\n", progname, dir);
+ quit("error");
+ }
+ }
+ }exception e{
+ "*" =>
+ sys->print("%s: %s: %s: exiting\n", progname, dir, e);
+ quit("exception");
+ }
+}
+
+trace(sourcept: string, op: array of byte )
+{
+ if(styx->istmsg(op)){
+ (nil, m) := Tmsg.unpack(op);
+ if(m != nil)
+ sys->print("%s: %s\n", sourcept, m.text());
+ else
+ sys->print("%s: unknown\n", sourcept);
+ }else{
+ (nil, m) := Rmsg.unpack(op);
+ if(m != nil)
+ sys->print("%s: %s\n", sourcept, m.text());
+ else
+ sys->print("%s: unknown\n", sourcept);
+ }
+}
+
+dump(msg: string, buf: array of byte, n: int)
+{
+ sys->print("%s: [%d bytes]: ", msg, n);
+ s := "";
+ for(i:=0;i<n;i++) {
+ if((i % 20) == 0) {
+ sys->print(" %s\n", s);
+ s = "";
+ }
+ sys->print("%2.2x ", int buf[i]);
+ if(int buf[i] >= 32 && int buf[i] < 127)
+ s[len s] = int buf[i];
+ else
+ s += ".";
+ }
+ for(i %= 20; i < 20; i++)
+ sys->print(" ");
+ sys->print(" %s\n\n", s);
+}
diff --git a/appl/cmd/auxi/rstyxd.b b/appl/cmd/auxi/rstyxd.b
new file mode 100644
index 00000000..2f853ad5
--- /dev/null
+++ b/appl/cmd/auxi/rstyxd.b
@@ -0,0 +1,114 @@
+implement Rstyxd;
+
+include "sys.m";
+include "draw.m";
+include "sh.m";
+include "string.m";
+
+sys: Sys;
+str: String;
+stderr: ref Sys->FD;
+
+Rstyxd: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+#
+# argv is a list of Inferno supported algorithms from Security->Auth
+#
+init(nil: ref Draw->Context, nil: list of string)
+{
+ sys = load Sys Sys->PATH;
+ str = load String String->PATH;
+ if (str == nil)
+ badmod(String->PATH);
+
+ fd := sys->fildes(0);
+ stderr = sys->fildes(2);
+ sys->pctl(sys->FORKFD, fd.fd :: nil);
+
+ args := readargs(fd);
+ if(args == nil)
+ err(sys->sprint("error reading arguments: %r"));
+
+ cmd := hd args;
+ s := "";
+ for (a := args; a != nil; a = tl a)
+ s += hd a + " ";
+ sys->fprint(stderr, "rstyxd: cmd: %s\n", s);
+ s = nil;
+ file: string;
+ if(cmd == "sh")
+ file = "/dis/sh.dis";
+ else
+ file = cmd + ".dis";
+ mod := load Command file;
+ if(mod == nil){
+ mod = load Command "/dis/"+file;
+ if(mod == nil)
+ badmod("/dis/"+file);
+ }
+
+ sys->pctl(Sys->FORKNS|Sys->FORKENV, nil);
+
+ if(sys->mount(fd, nil, "/n/client", Sys->MREPL, "") < 0)
+ err(sys->sprint("cannot mount connection on /n/client: %r"));
+
+ if(sys->bind("/n/client/dev", "/dev", Sys->MBEFORE) < 0)
+ err(sys->sprint("cannot bind /n/client/dev to /dev: %r"));
+
+ fd = sys->open("/dev/cons", sys->OREAD);
+ sys->dup(fd.fd, 0);
+ fd = sys->open("/dev/cons", sys->OWRITE);
+ sys->dup(fd.fd, 1);
+ sys->dup(fd.fd, 2);
+ fd = nil;
+
+ mod->init(nil, args);
+}
+
+readargs(fd: ref Sys->FD): list of string
+{
+ buf := array[1024] of byte;
+ c := array[1] of byte;
+ for(i:=0; ; i++){
+ if(i>=len buf || sys->read(fd, c, 1)!=1)
+ return nil;
+ buf[i] = c[0];
+ if(c[0] == byte '\n')
+ break;
+ }
+ nb := int string buf[0:i];
+ if(nb <= 0)
+ return nil;
+ args := readn(fd, nb);
+ if (args == nil)
+ return nil;
+ return str->unquoted(string args[0:nb]);
+}
+
+readn(fd: ref Sys->FD, nb: int): array of byte
+{
+ buf:= array[nb] of byte;
+ for(n:=0; n<nb;){
+ m := sys->read(fd, buf[n:], nb-n);
+ if(m <= 0)
+ return nil;
+ n += m;
+ }
+ return buf;
+}
+
+
+err(s: string)
+{
+ sys->fprint(stderr, "rstyxd: %s\n", s);
+ raise "fail:error";
+}
+
+badmod(s: string)
+{
+ sys->fprint(stderr, "rstyxd: can't load %s: %r\n", s);
+ raise "fail:load";
+}