ref: d1540c7f666e3c5d636b48c956b444205b50502d
dir: /appl/cmd/rdp.b/
implement Rdp; include "sys.m"; sys: Sys; print, sprint: import sys; include "draw.m"; include "string.m"; str: String; df_port: con "/dev/eia0"; df_bps: con 38400; Rdp: module { init: fn(nil: ref Draw->Context, arg: list of string); }; dfd: ref sys->FD; cfd: ref sys->FD; ifd: ref sys->FD; pifd: ref sys->FD; p_isopen := 0; R_R15: con 15; R_PC: con 16; R_CPSR: con 17; R_SPSR: con 18; NREG: con 19; debug := 0; nocr := 0; tmode := 0; # echar := 16r1c; # ctrl-\ echar := 16r1d; # ctrl-] (because Tk grabs the ctrl-\ ) bint(x: int): array of byte { b := array[4] of byte; b[0] = byte x; b[1] = byte (x>>8); b[2] = byte (x>>16); b[3] = byte (x>>24); return b; } intb(b: array of byte): int { return int b[0] | (int b[1] << 8) | (int b[2] << 16) | (int b[3] << 24); } statusmsg(n: int): string { m: string; case n { 0 => m = nil; 1 => m = "Reset"; 2 => m = "Undefined instruction"; 3 => m = "Software interrupt"; 4 => m = "Prefetch abort"; 5 => m = "Data abort"; 6 => m = "Address exception"; 7 => m = "IRQ"; 8 => m = "FIQ"; 9 => m = "Error"; 10 => m = "Branch Through 0"; 253 => m = "Insufficient privilege"; 254 => m = "Unimplemented message"; 255 => m = "Undefined message"; * => m = sprint("Status %d", n); } return m; } sdc: chan of (array of byte, int); scc: chan of int; serinp() { b: array of byte = nil; save: array of byte = nil; x := 0; for(;;) { m := <- scc; if(m == 0) { save = b[0:x]; continue; } b = nil; t: int; do { alt { m = <- scc => if(m == 0) print("<strange error>\n"); b = nil; * => ; } if(b == nil) { if(m >= 0) t = m; else t = -m; x = 0; b = array[t] of byte; } if(save != nil) { r := len save; if(r > (t-x)) r = t-x; b[x:] = save[0:r]; save = save[r:]; if(len save == 0) save = nil; x += r; continue; } r := sys->read(dfd, b[x:], t-x); if(r < 0) sdc <-= (array of byte sprint("fail:%r"), -1); if(r == 0) sdc <-= (array of byte "fail:hangup", -1); if(debug) { if(r == 1) print("<%ux>", int b[x]); else print("<%ux,%ux...(%d)>", int b[x], int b[x+1], r); } x += r; } while(m >= 0 && x < t); sdc <-= (b, x); } } sreadn(n: int): array of byte { b: array of byte; if(n == 0) return array[0] of byte; scc <-= n; (b, n) = <- sdc; if(n < 0) raise string b; return b[0:n]; } # yes, it's kind of a hack... fds := array[32] of ref Sys->FD; oscmd() { arg := array[4] of int; buf := array[4] of array of byte; b := sreadn(5); op := intb(b[:4]); argd := int b[4]; for(i := 0; i<4; i++) { t := (argd >> (i*2))&3; case t { 0 => ; 1 => arg[i] = int sreadn(1)[0]; 2 => arg[i] = intb(sreadn(4)); 3 => c := int sreadn(1)[0]; if(c < 255) { buf[i] = array[c] of byte; if(c <= 32) { buf[i][0:] = sreadn(c); } else arg[i] = intb(sreadn(4)); } else { b: array of byte; b = sreadn(8); c = intb(b[:4]); arg[i] = intb(b[4:8]); buf[i] = array[c] of byte; } } } for(i = 0; i<4; i++) if(buf[i] != nil && len buf[i] > 32) rdi_read(arg[i], buf[i], len buf[i]); r := 0; case op { 0 or 2 => ; * => out(""); } case op { 0 => if(debug) print("SWI_WriteC(%d)\n", arg[0]); out(string byte arg[0]); 2 => if(debug) print("SWI_Write0(<%d>)\n", len buf[0]); out(string buf[0]); 4 => if(debug) print("SWI_ReadC()\n"); sys->read(ifd, b, 1); r = int b[0]; 16r66 => fname := string buf[0]; if(debug) print("SWI_Open(%s, %d)\n", fname, arg[1]); fd: ref Sys->FD; case arg[1] { 0 or 1 => fd = sys->open(fname, Sys->OREAD); 2 or 3 => fd = sys->open(fname, Sys->ORDWR); 4 or 5 => fd = sys->open(fname, Sys->OWRITE); if(fd == nil) fd = sys->create(fname, Sys->OWRITE, 8r666); 6 or 7 => fd = sys->open(fname, Sys->OWRITE|Sys->OTRUNC); if(fd == nil) fd = sys->create(fname, Sys->OWRITE, 8r666); 8 or 9 => fd = sys->open(fname, Sys->OWRITE); if(fd == nil) fd = sys->create(fname, Sys->OWRITE, 8r666); else sys->seek(fd, big 0, Sys->SEEKEND); 10 or 11 => fd = sys->open(fname, Sys->ORDWR); if(fd == nil) fd = sys->create(fname, Sys->ORDWR, 8r666); else sys->seek(fd, big 0, Sys->SEEKEND); } if(fd != nil) { r = fd.fd; if(r >= len fds) { print("<fd %d out of range 1-%d>\n", r, len fds); r = 0; } else fds[r] = fd; } 16r68 => if(debug) print("SWI_Close(%d)\n", arg[0]); if(arg[0] <= 0 || arg[0] >= len fds) r = -1; else { if(fds[arg[0]] != nil) fds[arg[0]] = nil; else r = -1; } 16r69 => if(debug) print("SWI_Write(%d, <%d>)\n", arg[0], len buf[1]); if(arg[0] <= 0 || arg[0] >= len fds) r = -1; else r = sys->write(fds[arg[0]], buf[1], len buf[1]); r = arg[2]-r; 16r6a => if(debug) print("SWI_Read(%d, 0x%ux, %d)\n", arg[0], arg[1], arg[2]); if(arg[0] <= 0 || arg[0] >= len fds) r = -1; else { d := array[arg[2]] of byte; r = sys->read(fds[arg[0]], d, arg[2]); if(r > 0) rdi_write(d, arg[1], r); } r = arg[2]-r; 16r6b => if(debug) print("SWI_Seek(%d, %d)\n", arg[0], arg[1]); if(arg[0] <= 0 || arg[0] >= len fds) r = -1; else r = int sys->seek(fds[arg[0]], big arg[1], 0); 16r6c => if(debug) print("SWI_Flen(%d)\n", arg[0]); if(arg[0] <= 0 || arg[0] >= len fds) r = -1; else { d: Sys->Dir; (r, d) = sys->fstat(fds[arg[0]]); if(r >= 0) r = int d.length; } 16r6e => if(debug) print("SWI_IsTTY(%d)\n", arg[0]); r = 0; # how can we detect if it's a TTY? * => print("unsupported: SWI 0x%ux\n", op); } b = array[6] of byte; b[0] = byte 16r13; if(debug) print("r0=%d\n", r); if(r >= 0 && r <= 16rff) { b[1] = byte 1; b[2] = byte r; sys->write(dfd, b, 3); } else { b[1] = byte 2; b[2:] = bint(r); sys->write(dfd, b, 6); } } terminal() { b := array[1024] of byte; c := 3; # num of invalid chars before resetting tmode = 1; for(;;) { n: int; b: array of byte; alt { scc <-= -8192 => (b, n) = <- sdc; (b, n) = <- sdc => ; } if(n < 0) raise string b; c -= out(string b[:n]); if(c < 0) { scc <-= 0; raise "rdp:tmode"; } if(!tmode) { return; } } } getreply(n: int): (array of byte, int) { loop: for(;;) { c := int sreadn(1)[0]; case c { 16r21 => oscmd(); 16r7f => raise "rdp:reset"; 16r5f => break loop; * => print("<%ux?>", c); scc <-= 0; raise "rdp:tmode"; } } b := sreadn(n+1); s := int b[n]; if(s != 0) { out(""); print("[%s]\n", statusmsg(s)); } return (b[:n], s); } outstr: string; tpid: int; timeout(t: int, c: chan of int) { tpid = sys->pctl(0, nil); if(t > 0) sys->sleep(t); c <-= 0; tpid = 0; } bsc: chan of string; bufout() { buf := ""; tc := chan of int; n: int; s: string; for(;;) { alt { n = <- tc => print("%s", buf); buf = ""; s = <- bsc => #if(tpid) { # kill(tpid); # tpid = 0; #} if((len buf+len s) >= 1024) { print("%s", buf); buf = s; } if(s == "" || debug) { print("%s", buf); buf = ""; } else { buf += s; if(tpid == 0) spawn timeout(300, tc); } } } } out(s: string): int { if(bsc == nil) { bsc = chan of string; spawn bufout(); } c := 0; if(nocr || tmode) { n := ""; for(i:=0; i<len s; i++) { if(!(nocr && s[i] == '\r')) n[len n] = s[i]; if(s[i] >= 16r7f) c++; } bsc <-= n; } else bsc <-= s; return c; } reset(r: int) { out(""); if(debug) print("reset(%d)\n", r); p_isopen = 0; b := array of byte sprint("b9600"); sys->write(cfd, b, len b); if(r) { b[0] = byte 127; sys->write(dfd, b, 1); print("<sending reset>"); } ok := 0; s := ""; for(;;) { n: int; b: array of byte; scc <-= -8192; (b, n) = <- sdc; if(n < 0) raise string b; for(i := 0; i<n; i++) { if(b[i] == byte 127) { if(!ok) print("\n"); ok = 1; s = ""; continue; } if(b[i] == byte 0) { if(ok && i == n-1) { out(s); out(""); return; } else { s = ""; continue; } } if(b[i] < byte 127) s += string b[i:i+1]; else ok = 0; } } } sa1100_reset() { rdi_write(bint(1), int 16r90030000, 4); } setbps(bps: int) { # for older Emu's using setserial hacks... if(bps > 38400) sys->write(cfd, array of byte "b38400", 6); out(""); print("<bps=%d>\n", bps); b := array of byte sprint("b%d", bps); if(sys->write(cfd, b, len b) != len b) print("setbps failed: %r\n"); } rdi_open(bps: int) { if(debug) print("rdi_open(%d)\n", bps); b := array[7] of byte; usehack := 0; if(!p_isopen) { b[0] = byte 0; b[1] = byte (0 | (1<<1)); b[2:] = bint(0); case bps { 9600 => b[6] = byte 1; 19200 => b[6] = byte 2; 38400 => b[6] = byte 3; # 57600 => b[6] = byte 4; # 115200 => b[6] = byte 5; # 230400 => b[6] = byte 6; * => b[6] = byte 1; usehack = 1; } sys->write(dfd, b, 7); getreply(0); p_isopen = 1; if(usehack) sa1100_setbps(bps); else setbps(bps); } } rdi_close() { if(debug) print("rdi_close()\n"); b := array[1] of byte; if(p_isopen) { b[0] = byte 1; sys->write(dfd, b, 1); getreply(0); p_isopen = 0; } } rdi_cpuread(reg: array of int, mask: int) { if(debug) print("rdi_cpuread(..., 0x%ux)\n", mask); n := 0; for(i := 0; i<NREG; i++) if(mask&(1<<i)) n += 4; b := array[6+n] of byte; b[0] = byte 4; b[1] = byte 255; # current mode b[2:] = bint(mask); sys->write(dfd, b, 6); (b, nil) = getreply(n); n = 0; for(i = 0; i<NREG; i++) if(mask&(1<<i)) { reg[i] = intb(b[n:n+4]); n += 4; } } rdi_cpuwrite(reg: array of int, mask: int) { if(debug) print("rdi_cpuwrite(..., 0x%ux)\n", mask); n := 0; for(i := 0; i<32; i++) if(mask&(1<<i)) n += 4; b := array[6+n] of byte; b[0] = byte 5; b[1] = byte 255; # current mode b[2:] = bint(mask); n = 6; for(i = 0; i<32; i++) if(mask&(1<<i)) { b[n:] = bint(reg[i]); n += 4; } sys->write(dfd, b, n); getreply(0); } dump(b: array of byte, n: int) { for(i := 0; i<n; i++) print(" %d: %2.2ux\n", i, int b[i]); } rdi_read(addr: int, b: array of byte, n: int): int { if(debug) print("rdi_read(0x%ux, ..., 0x%ux)\n", addr, n); if(n == 0) return 0; sb := array[9] of byte; sb[0] = byte 2; sb[1:] = bint(addr); sb[5:] = bint(n); sys->write(dfd, sb, 9); (b[0:], nil) = getreply(n); # if error, need to read count of bytes transferred return n; } rdi_write(b: array of byte, addr: int, n: int): int { if(debug) print("rdi_write(..., 0x%ux, 0x%ux)\n", addr, n); if(n == 0) return 0; sb := array[9+n] of byte; sb[0] = byte 3; sb[1:] = bint(addr); sb[5:] = bint(n); sb[9:] = b[:n]; sys->write(dfd, sb, 9); x := 0; while(n) { q := n; if(q > 8192) q = 8192; r := sys->write(dfd, b[x:], q); if(debug) print("rdi_write: r=%d ofs=%d n=%d\n", r, x, n); if(r < 0) raise "fail:hangup"; x += r; n -= r; } getreply(0); return n; } rdi_execute() { if(debug) print("rdi_execute()\n"); sb := array[2] of byte; sb[0] = byte 16r10; sb[1] = byte 0; sys->write(dfd, sb, 2); getreply(0); out(""); } rdi_info(n: int, arg: int) { sb := array[9] of byte; sb[0] = byte 16r12; sb[1:] = bint(n); sb[5:] = bint(arg); sys->write(dfd, sb, 9); getreply(0); } regdump() { out(""); reg := array[NREG] of int; # rdi_cpuread(reg, 16rffff|(1<<R_PC)|(1<<R_CPSR)|(1<<R_SPSR)); rdi_cpuread(reg, 16rffff|(1<<R_PC)|(1<<R_CPSR)); for(i := 0; i < 16; i += 4) print(" r%-2d=%8.8ux r%-2d=%8.8ux r%-2d=%8.8ux r%-2d=%8.8ux\n", i, reg[i], i+1, reg[i+1], i+2, reg[i+2], i+3, reg[i+3]); print(" pc=%8.8ux psr=%8.8ux\n", reg[R_PC], reg[R_CPSR]); } printable(b: array of byte): string { s := ""; for(i := 0; i < len b; i++) if(b[i] >= byte ' ' && b[i] <= byte 126) s += string b[i:i+1]; else s += "."; return s; } examine(a: int, n: int) { b := array[4] of byte; for(i := 0; i<n; i++) { rdi_read(a, b, 4); print("0x%8.8ux: 0x%8.8ux \"%s\"\n", a, intb(b), printable(b)); a += 4; } } atoi(s: string): int { b := 10; if(len s < 1) return 0; if(s[0] == '0') { b = 8; s = s[1:]; if(len s < 1) return 0; if(s[0] == 'x' || s[0] == 'X') { b = 16; s = s[1:]; } } n: int; (n, nil) = str->toint(s, b); return n; } regnum(s: string): int { if(len s < 2) return -1; if(s[0] == 'r' && s[1] >= '0' && s[1] <= '9') return atoi(s[1:]); case s { "pc" => return R_PC; "cpsr" or "psr" => return R_CPSR; "spsr" => return R_SPSR; * => return -1; } } cmdhelp() { print(" e <addr> [<count>] - examine memory\n"); print(" d <addr> [<value>...] - deposit values in memory\n"); print(" get <file> <addr> - read file into memory at addr\n"); print(" load <file> - load AIF file and set the PC\n"); print(" r - print all registers\n"); print(" <reg>=<val> - set register value\n"); print(" sb - run builtin sboot (pc=0x40; g)\n"); print(" reset - trigger SA1100 software reset\n"); print(" bps <speed> - change bps rate (SA1100 only)\n"); print(" q - quit\n"); } cmdmode() { b := array[1024] of byte; for(;;) { print("rdp: "); r := sys->read(ifd, b, len b); if(r < 0) raise sprint("fail:%r"); if(r == 0 || (r == 1 && b[0] == byte 4)) break; n: int; a: list of string; (n, a) = sys->tokenize(string b[0:r], " \t\n="); if(n < 1) continue; case hd a { "sb" => sbmode(); rdi_execute(); "q" or "quit" => return; "r" or "reg" => regdump(); "get" or "getfile" or "l" or "load" => { if((hd a)[0] == 'l') aifload(hd tl a, -1); else aifload(hd tl a, atoi(hd tl tl a)); }exception e{ "fail:*" => print("error: %s\n", e[5:]); continue; } "g" or "go" => rdi_execute(); "reset" => sa1100_reset(); "e" => a = tl a; x := atoi(hd a); n = 1; a = tl a; if(a != nil) n = atoi(hd a); examine(x, n); "d" => a = tl a; x := atoi(hd a); for(i := 2; i<n; i++) { a = tl a; rdi_write(bint(atoi(hd a)), x, 4); x += 4; } "info" => a = tl a; rdi_info(16r180, atoi(hd a)); "bps" => sa1100_setbps(atoi(hd tl a)); "help" or "?" => cmdhelp(); * => if((rn := regnum(hd a)) > -1) { reg := array[NREG] of int; reg[rn] = atoi(hd tl a); rdi_cpuwrite(reg, 1<<rn); } else print("?\n"); } } } sbmode() { if(debug) print("sbmode()\n"); reg := array[NREG] of int; reg[R_PC] = 16r40; rdi_cpuwrite(reg, 1<<R_PC); } sbmodeofs(ofs: int) { if(debug) print("sbmode(0x%ux)\n", ofs); reg := array[NREG] of int; reg[0] = ofs; reg[R_PC] = 16r48; rdi_cpuwrite(reg, (1<<0)|(1<<R_PC)); } inp: string = ""; help: con "(q)uit, (i)nt, (b)reak, !c(r), !(l)ine, !(t)erminal, (s<bps>), (.)cont, (!cmd)\n"; menu(fi: ref Sys->FD) { w := israw; if(israw) raw(0); mloop: for(;;) { out(""); print("rdp> "); b := array[256] of byte; r := sys->read(fi, b, len b); case int b[0] { 'q' => killgrp(); exit; 'i' => b[0] = byte 16r18; sys->write(dfd, b[0:1], 1); break mloop; 'b' => sys->write(cfd, array of byte "k", 1); break mloop; '!' => cmd := string b[1:r-1]; print("!%s\n", cmd); # system(cmd) print("!\n"); break mloop; 'l' => w = !w; break mloop; 'r' => nocr = !nocr; break mloop; 'd' => debug = !debug; break mloop; 't' => sys->write(pifd, array[] of { byte 4 }, 1); sdc <-= (array of byte "rdp:tmode", -1); break mloop; '.' => break mloop; 's' => bps := atoi(string b[1:r-1]); setbps(bps); * => print(help); continue; } } if(israw != w) raw(w); } input() { fi := sys->fildes(0); b := array[1024] of byte; iloop: for(;;) { r := sys->read(fi, b, len b); if(r < 0) { print("stdin: %r"); killgrp(); exit; } for(i:=0; i<r; i++) { if(b[i] == byte echar) { menu(fi); continue iloop; } } if(r == 0) { b[0] = byte 4; # ctrl-d r = 1; } if(tmode) sys->write(dfd, b, r); else sys->write(pifd, b, r); } } ccfd: ref Sys->FD; israw := 0; raw(on: int) { if(ccfd == nil) { ccfd = sys->open("/dev/consctl", Sys->OWRITE); if(ccfd == nil) { print("/dev/consctl: %r\n"); return; } } if(on) sys->fprint(ccfd, "rawon"); else sys->fprint(ccfd, "rawoff"); israw = on; } killgrp() { pid := sys->pctl(0, nil); f := "/prog/"+string pid+"/ctl"; fd := sys->open(f, Sys->OWRITE); if(fd == nil) print("%s: %r\n", f); else sys->fprint(fd, "killgrp"); } kill(pid: int) { f := "/prog/"+string pid+"/ctl"; fd := sys->open(f, Sys->OWRITE); if(fd == nil) print("%s: %r\n", f); else sys->fprint(fd, "kill"); } # Code for switching to previously unsupported bps rates: ##define UTCR1 0x4 ##define UTCR2 0x8 ##define UTCR3 0xc ##define UTDR 0x14 ##define UTSR0 0x1c ##define UTSR1 0x20 # #TEXT _startup(SB), $-4 # MOVW $0x80000000,R2 # ORR $0x00050000,R2 # # MOVW $0, R1 # MOVW R1, UTDR(R2) /* send ack */ # #wait: # MOVW UTSR1(R2), R1 # TST $1, R1 /* TBY */ # BNE wait # # MOVW $0x90000000,R3 # ORR $0x00000010,R3 # MOVW (R4),R1 # ADD $0x5a000,R1 /* 100 ms */ #delay1: # MOVW (R3),R1 # SUB.S $0x5a000, R1 /* 100 ms */ # BLO delay1 # # MOVW UTCR3(R2), R5 /* save utcr3 */ # MOVW $0, R1 # MOVW R1, UTCR3(R2) /* disable xmt/rcv */ # # MOVW R0, R1 # AND $0xff, R1 # MOVW R1, UTCR2(R2) # MOVW R0 >> 8, R1 # MOVW R1, UTCR1(R2) # # MOVW $0xff, R1 # MOVW R1, UTSR0(R2) /* clear sticky bits */ # # MOVW $3, R1 # MOVW R1, UTCR3(R2) /* enable xmt/rcv */ # # MOVW $0, R0 #sync: # MOVW R0, UTDR(R2) /* send sync char */ #syncwait: # MOVW UTSR1(R2), R1 # TST $1, R1 /* TBY */ # BNE syncwait # TST $2, R1 /* RNE */ # BEQ sync # MOVW UTDR(R2), R0 # MOVW R0, UTDR(R2) /* echo rcvd char */ # # MOVW $0xff, R1 # MOVW R1, UTSR0(R2) /* clear sticky bits */ # MOVW R5, UTCR3(R2) /* re-enable xmt/rcv and interrupts */ # # WORD $0xef000011 /* exit */ bpscode := array[] of { 16re3a22102, 16re3822805, 16re3a11000, 16re5821014, 16re5921020, 16re3110001, big 16r1afffffc, 16re3a33209, 16re3833010, 16re5941000, 16re2811a5a, 16re5931000, 16re2511a5a, big 16r3afffffc, 16re592500c, 16re3a11000, 16re582100c, 16re1a11000, 16re20110ff, 16re5821008, 16re1a11420, 16re5821004, 16re3a110ff, 16re582101c, 16re3a11003, 16re582100c, 16re3a00000, 16re5820014, 16re5921020, 16re3110001, big 16r1afffffc, 16re3110002, big 16r0afffff9, 16re5920014, 16re5820014, 16re3a110ff, 16re582101c, 16re582500c, 16ref000011, }; sa1100_setbps(bps: int) { print("<sa1100_setbps %d>", bps); nb := len bpscode*4; b := array[nb] of byte; for(i := 0; i < len bpscode; i++) b[i*4:] = bint(int bpscode[i]); rdi_write(b, 16r8080, nb); reg := array[NREG] of int; d := (3686400/(bps*16))-1; reg[0] = d; reg[R_PC] = 16r8080; rdi_cpuwrite(reg, (1<<0)|(1<<R_PC)); sb := array[2] of byte; sb[0] = byte 16r10; sb[1] = byte 0; sys->write(dfd, sb, 2); rb := sreadn(1); setbps(bps); do rb = sreadn(1); while(rb[0] != byte 0); sb[0] = byte 16rff; sys->write(dfd, sb, 1); do rb = sreadn(1); while(rb[0] != sb[0]); getreply(0); } aifload(fname: string, adr: int) { out(""); if(adr < 0) print("<aifload %s>\n", fname); fd := sys->open(fname, Sys->OREAD); if(fd == nil) raise sprint("fail:%s:%r", fname); d: Sys->Dir; (nil, d) = sys->fstat(fd); b := array[int d.length] of byte; sys->read(fd, b, len b); if(adr < 0) { if(len b < 128) raise sprint("fail:%s:not aif", fname); tsize := intb(b[20:24]); dsize := intb(b[24:28]); bsize := intb(b[32:36]); tbase := intb(b[40:44]); dbase := intb(b[52:56]); print("%ux/%ux: %ux+%ux+%ux\n", tbase, dbase, tsize, dsize, bsize); rdi_write(b, tbase, tsize+dsize); reg := array[NREG] of int; reg[R_PC] = tbase+8; rdi_cpuwrite(reg, 1<<R_PC); } else rdi_write(b, adr, int d.length); } init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; str = load String String->PATH; sys->pctl(Sys->NEWPGRP, nil); port := df_port; bps := df_bps; usecmdmode := 0; ofs := -1; prog: string = nil; argv = tl argv; while(argv != nil) { a := hd argv; argv = tl argv; if(len a >= 2 && a[0] == '-') case a[1] { 'c' => usecmdmode = 1; 'O' => ofs = atoi(a[2:]); 'd' => debug = 1; 'p' => port = a[2:]; 's' => bps = atoi(a[2:]); 'r' => nocr = 1; 'l' => raw(1); 'e' => if(a[2] == '^') echar = a[3]&16r1f; else echar = a[2]; 't' => tmode = 1; 'h' => print("usage: rdp [-crdlht] [-e<c>] [-O<ofs>] [-p<port>] [-s<bps>] [prog]\n"); return; * => print("invalid option: %s\n", a); return; } else prog = a; } print("rdp 0.17 (port=%s, bps=%d)\n", port, bps); dfd = sys->open(port, Sys->ORDWR); if(dfd == nil) { sys->print("open %s failed: %r\n", port); return; } cfd = sys->open(port+"ctl", Sys->OWRITE); if(cfd == nil) sys->print("warning: open %s failed: %r\n", port+"ctl"); pfd := array[2] of ref Sys->FD; sys->pipe(pfd); ifd = pfd[1]; pifd = pfd[0]; (scc, sdc) = (chan of int, chan of (array of byte, int)); spawn serinp(); spawn input(); r := 1; { if(tmode) terminal(); reset(r); if(!p_isopen) { rdi_open(bps); rdi_info(16r180, (1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)); } # print("\n<connection established>\n"); print("\n<contact has been made>\n"); if(usecmdmode) { cmdmode(); } else { if(prog != nil) aifload(prog, -1); else if(ofs != -1) sbmodeofs(ofs); else sbmode(); reg := array[NREG] of int; # rdi_cpuread(reg, (1<<R_PC)|(1<<R_CPSR)); # print("<execute at %ux; cpsr=%ux>\n", reg[R_PC], reg[R_CPSR]); rdi_cpuread(reg, (1<<R_PC)); print("<execute at %ux>\n", reg[R_PC]); rdi_execute(); } rdi_close(); # Warning: this will make Linux emu crash... killgrp(); }exception e{ "fail:*" => if(israw) raw(0); killgrp(); raise e; "rdp:*" => out(""); if(debug) print("<exception: %s>\n", e); case e { "rdp:error" => ; "rdp:tmode" => tmode = !tmode; if(tmode) print("<terminal mode>\n"); else print("<rdp mode>\n"); "rdp:reset" => r = 0; * => r = 1; } } }