1implement Rdp; 2include "sys.m"; 3 sys: Sys; 4 print, sprint: import sys; 5include "draw.m"; 6include "string.m"; 7 str: String; 8 9df_port: con "/dev/eia0"; 10df_bps: con 38400; 11 12Rdp: module 13{ 14 init: fn(nil: ref Draw->Context, arg: list of string); 15}; 16 17dfd: ref sys->FD; 18cfd: ref sys->FD; 19ifd: ref sys->FD; 20pifd: ref sys->FD; 21p_isopen := 0; 22 23R_R15: con 15; 24R_PC: con 16; 25R_CPSR: con 17; 26R_SPSR: con 18; 27NREG: con 19; 28 29debug := 0; 30nocr := 0; 31tmode := 0; 32# echar := 16r1c; # ctrl-\ 33echar := 16r1d; # ctrl-] (because Tk grabs the ctrl-\ ) 34 35bint(x: int): array of byte 36{ 37 b := array[4] of byte; 38 b[0] = byte x; 39 b[1] = byte (x>>8); 40 b[2] = byte (x>>16); 41 b[3] = byte (x>>24); 42 return b; 43} 44 45intb(b: array of byte): int 46{ 47 return int b[0] | (int b[1] << 8) 48 | (int b[2] << 16) | (int b[3] << 24); 49} 50 51 52statusmsg(n: int): string 53{ 54 m: string; 55 case n { 56 0 => m = nil; 57 1 => m = "Reset"; 58 2 => m = "Undefined instruction"; 59 3 => m = "Software interrupt"; 60 4 => m = "Prefetch abort"; 61 5 => m = "Data abort"; 62 6 => m = "Address exception"; 63 7 => m = "IRQ"; 64 8 => m = "FIQ"; 65 9 => m = "Error"; 66 10 => m = "Branch Through 0"; 67 253 => m = "Insufficient privilege"; 68 254 => m = "Unimplemented message"; 69 255 => m = "Undefined message"; 70 * => m = sprint("Status %d", n); 71 } 72 return m; 73} 74 75sdc: chan of (array of byte, int); 76scc: chan of int; 77 78serinp() 79{ 80 b: array of byte = nil; 81 save: array of byte = nil; 82 x := 0; 83 for(;;) { 84 m := <- scc; 85 if(m == 0) { 86 save = b[0:x]; 87 continue; 88 } 89 b = nil; 90 t: int; 91 do { 92 alt { 93 m = <- scc => 94 if(m == 0) 95 print("<strange error>\n"); 96 b = nil; 97 * => 98 ; 99 } 100 if(b == nil) { 101 if(m >= 0) 102 t = m; 103 else 104 t = -m; 105 x = 0; 106 b = array[t] of byte; 107 } 108 if(save != nil) { 109 r := len save; 110 if(r > (t-x)) 111 r = t-x; 112 b[x:] = save[0:r]; 113 save = save[r:]; 114 if(len save == 0) 115 save = nil; 116 x += r; 117 continue; 118 } 119 r := sys->read(dfd, b[x:], t-x); 120 if(r < 0) 121 sdc <-= (array of byte sprint("fail:%r"), -1); 122 if(r == 0) 123 sdc <-= (array of byte "fail:hangup", -1); 124 if(debug) { 125 if(r == 1) 126 print("<%ux>", int b[x]); 127 else 128 print("<%ux,%ux...(%d)>", int b[x], int b[x+1], r); 129 } 130 x += r; 131 } while(m >= 0 && x < t); 132 sdc <-= (b, x); 133 } 134} 135 136 137sreadn(n: int): array of byte 138{ 139 b: array of byte; 140 if(n == 0) 141 return array[0] of byte; 142 scc <-= n; 143 (b, n) = <- sdc; 144 if(n < 0) 145 raise string b; 146 return b[0:n]; 147} 148 149 150# yes, it's kind of a hack... 151fds := array[32] of ref Sys->FD; 152 153oscmd() 154{ 155 arg := array[4] of int; 156 buf := array[4] of array of byte; 157 b := sreadn(5); 158 op := intb(b[:4]); 159 argd := int b[4]; 160 for(i := 0; i<4; i++) { 161 t := (argd >> (i*2))&3; 162 case t { 163 0 => ; 164 1 => 165 arg[i] = int sreadn(1)[0]; 166 2 => 167 arg[i] = intb(sreadn(4)); 168 3 => 169 c := int sreadn(1)[0]; 170 if(c < 255) { 171 buf[i] = array[c] of byte; 172 if(c <= 32) { 173 buf[i][0:] = sreadn(c); 174 } else 175 arg[i] = intb(sreadn(4)); 176 } else { 177 b: array of byte; 178 b = sreadn(8); 179 c = intb(b[:4]); 180 arg[i] = intb(b[4:8]); 181 buf[i] = array[c] of byte; 182 } 183 } 184 } 185 for(i = 0; i<4; i++) 186 if(buf[i] != nil && len buf[i] > 32) 187 rdi_read(arg[i], buf[i], len buf[i]); 188 189 r := 0; 190 case op { 191 0 or 2 => ; 192 * => 193 out(""); 194 } 195 case op { 196 0 => 197 if(debug) 198 print("SWI_WriteC(%d)\n", arg[0]); 199 out(string byte arg[0]); 200 2 => 201 if(debug) 202 print("SWI_Write0(<%d>)\n", len buf[0]); 203 out(string buf[0]); 204 4 => 205 if(debug) 206 print("SWI_ReadC()\n"); 207 sys->read(ifd, b, 1); 208 r = int b[0]; 209 16r66 => 210 fname := string buf[0]; 211 if(debug) 212 print("SWI_Open(%s, %d)\n", fname, arg[1]); 213 fd: ref Sys->FD; 214 case arg[1] { 215 0 or 1 => 216 fd = sys->open(fname, Sys->OREAD); 217 2 or 3 => 218 fd = sys->open(fname, Sys->ORDWR); 219 4 or 5 => 220 fd = sys->open(fname, Sys->OWRITE); 221 if(fd == nil) 222 fd = sys->create(fname, Sys->OWRITE, 8r666); 223 6 or 7 => 224 fd = sys->open(fname, Sys->OWRITE|Sys->OTRUNC); 225 if(fd == nil) 226 fd = sys->create(fname, Sys->OWRITE, 8r666); 227 8 or 9 => 228 fd = sys->open(fname, Sys->OWRITE); 229 if(fd == nil) 230 fd = sys->create(fname, Sys->OWRITE, 8r666); 231 else 232 sys->seek(fd, big 0, Sys->SEEKEND); 233 10 or 11 => 234 fd = sys->open(fname, Sys->ORDWR); 235 if(fd == nil) 236 fd = sys->create(fname, Sys->ORDWR, 8r666); 237 else 238 sys->seek(fd, big 0, Sys->SEEKEND); 239 } 240 if(fd != nil) { 241 r = fd.fd; 242 if(r >= len fds) { 243 print("<fd %d out of range 1-%d>\n", r, len fds); 244 r = 0; 245 } else 246 fds[r] = fd; 247 } 248 16r68 => 249 if(debug) 250 print("SWI_Close(%d)\n", arg[0]); 251 if(arg[0] <= 0 || arg[0] >= len fds) 252 r = -1; 253 else { 254 if(fds[arg[0]] != nil) 255 fds[arg[0]] = nil; 256 else 257 r = -1; 258 } 259 16r69 => 260 if(debug) 261 print("SWI_Write(%d, <%d>)\n", arg[0], len buf[1]); 262 if(arg[0] <= 0 || arg[0] >= len fds) 263 r = -1; 264 else 265 r = sys->write(fds[arg[0]], buf[1], len buf[1]); 266 r = arg[2]-r; 267 16r6a => 268 if(debug) 269 print("SWI_Read(%d, 0x%ux, %d)\n", arg[0], arg[1], arg[2]); 270 if(arg[0] <= 0 || arg[0] >= len fds) 271 r = -1; 272 else { 273 d := array[arg[2]] of byte; 274 r = sys->read(fds[arg[0]], d, arg[2]); 275 if(r > 0) 276 rdi_write(d, arg[1], r); 277 } 278 r = arg[2]-r; 279 16r6b => 280 if(debug) 281 print("SWI_Seek(%d, %d)\n", arg[0], arg[1]); 282 if(arg[0] <= 0 || arg[0] >= len fds) 283 r = -1; 284 else 285 r = int sys->seek(fds[arg[0]], big arg[1], 0); 286 16r6c => 287 if(debug) 288 print("SWI_Flen(%d)\n", arg[0]); 289 if(arg[0] <= 0 || arg[0] >= len fds) 290 r = -1; 291 else { 292 d: Sys->Dir; 293 (r, d) = sys->fstat(fds[arg[0]]); 294 if(r >= 0) 295 r = int d.length; 296 } 297 16r6e => 298 if(debug) 299 print("SWI_IsTTY(%d)\n", arg[0]); 300 r = 0; # how can we detect if it's a TTY? 301 * => 302 print("unsupported: SWI 0x%ux\n", op); 303 } 304 b = array[6] of byte; 305 b[0] = byte 16r13; 306 if(debug) 307 print("r0=%d\n", r); 308 if(r >= 0 && r <= 16rff) { 309 b[1] = byte 1; 310 b[2] = byte r; 311 sys->write(dfd, b, 3); 312 } else { 313 b[1] = byte 2; 314 b[2:] = bint(r); 315 sys->write(dfd, b, 6); 316 } 317} 318 319 320terminal() 321{ 322 b := array[1024] of byte; 323 c := 3; # num of invalid chars before resetting 324 tmode = 1; 325 for(;;) { 326 n: int; 327 b: array of byte; 328 alt { 329 scc <-= -8192 => 330 (b, n) = <- sdc; 331 (b, n) = <- sdc => 332 ; 333 } 334 if(n < 0) 335 raise string b; 336 c -= out(string b[:n]); 337 if(c < 0) { 338 scc <-= 0; 339 raise "rdp:tmode"; 340 } 341 if(!tmode) { 342 return; 343 } 344 } 345} 346 347getreply(n: int): (array of byte, int) 348{ 349 loop: for(;;) { 350 c := int sreadn(1)[0]; 351 case c { 352 16r21 => 353 oscmd(); 354 16r7f => 355 raise "rdp:reset"; 356 16r5f => 357 break loop; 358 * => 359 print("<%ux?>", c); 360 scc <-= 0; 361 raise "rdp:tmode"; 362 } 363 } 364 b := sreadn(n+1); 365 s := int b[n]; 366 if(s != 0) { 367 out(""); 368 print("[%s]\n", statusmsg(s)); 369 } 370 return (b[:n], s); 371} 372 373outstr: string; 374tpid: int; 375 376timeout(t: int, c: chan of int) 377{ 378 tpid = sys->pctl(0, nil); 379 if(t > 0) 380 sys->sleep(t); 381 c <-= 0; 382 tpid = 0; 383} 384 385bsc: chan of string; 386 387bufout() 388{ 389 buf := ""; 390 tc := chan of int; 391 n: int; 392 s: string; 393 for(;;) { 394 alt { 395 n = <- tc => 396 print("%s", buf); 397 buf = ""; 398 s = <- bsc => 399 #if(tpid) { 400 # kill(tpid); 401 # tpid = 0; 402 #} 403 if((len buf+len s) >= 1024) { 404 print("%s", buf); 405 buf = s; 406 } 407 if(s == "" || debug) { 408 print("%s", buf); 409 buf = ""; 410 } else { 411 buf += s; 412 if(tpid == 0) 413 spawn timeout(300, tc); 414 } 415 } 416 } 417} 418 419out(s: string): int 420{ 421 if(bsc == nil) { 422 bsc = chan of string; 423 spawn bufout(); 424 } 425 c := 0; 426 if(nocr || tmode) { 427 n := ""; 428 for(i:=0; i<len s; i++) { 429 if(!(nocr && s[i] == '\r')) 430 n[len n] = s[i]; 431 if(s[i] >= 16r7f) 432 c++; 433 } 434 bsc <-= n; 435 } else 436 bsc <-= s; 437 return c; 438} 439 440reset(r: int) 441{ 442 out(""); 443 if(debug) 444 print("reset(%d)\n", r); 445 p_isopen = 0; 446 b := array of byte sprint("b9600"); 447 sys->write(cfd, b, len b); 448 if(r) { 449 b[0] = byte 127; 450 sys->write(dfd, b, 1); 451 print("<sending reset>"); 452 } 453 ok := 0; 454 s := ""; 455 for(;;) { 456 n: int; 457 b: array of byte; 458 scc <-= -8192; 459 (b, n) = <- sdc; 460 if(n < 0) 461 raise string b; 462 for(i := 0; i<n; i++) { 463 if(b[i] == byte 127) { 464 if(!ok) 465 print("\n"); 466 ok = 1; 467 s = ""; 468 continue; 469 } 470 if(b[i] == byte 0) { 471 if(ok && i == n-1) { 472 out(s); 473 out(""); 474 return; 475 } else { 476 s = ""; 477 continue; 478 } 479 } 480 if(b[i] < byte 127) 481 s += string b[i:i+1]; 482 else 483 ok = 0; 484 } 485 } 486} 487 488sa1100_reset() 489{ 490 rdi_write(bint(1), int 16r90030000, 4); 491} 492 493setbps(bps: int) 494{ 495 # for older Emu's using setserial hacks... 496 if(bps > 38400) 497 sys->write(cfd, array of byte "b38400", 6); 498 499 out(""); 500 print("<bps=%d>\n", bps); 501 b := array of byte sprint("b%d", bps); 502 if(sys->write(cfd, b, len b) != len b) 503 print("setbps failed: %r\n"); 504} 505 506rdi_open(bps: int) 507{ 508 if(debug) 509 print("rdi_open(%d)\n", bps); 510 b := array[7] of byte; 511 usehack := 0; 512 if(!p_isopen) { 513 b[0] = byte 0; 514 b[1] = byte (0 | (1<<1)); 515 b[2:] = bint(0); 516 case bps { 517 9600 => b[6] = byte 1; 518 19200 => b[6] = byte 2; 519 38400 => b[6] = byte 3; 520 # 57600 => b[6] = byte 4; 521 # 115200 => b[6] = byte 5; 522 # 230400 => b[6] = byte 6; 523 * => 524 b[6] = byte 1; 525 usehack = 1; 526 } 527 sys->write(dfd, b, 7); 528 getreply(0); 529 p_isopen = 1; 530 if(usehack) 531 sa1100_setbps(bps); 532 else 533 setbps(bps); 534 } 535} 536 537rdi_close() 538{ 539 if(debug) 540 print("rdi_close()\n"); 541 b := array[1] of byte; 542 if(p_isopen) { 543 b[0] = byte 1; 544 sys->write(dfd, b, 1); 545 getreply(0); 546 p_isopen = 0; 547 } 548} 549 550rdi_cpuread(reg: array of int, mask: int) 551{ 552 if(debug) 553 print("rdi_cpuread(..., 0x%ux)\n", mask); 554 n := 0; 555 for(i := 0; i<NREG; i++) 556 if(mask&(1<<i)) 557 n += 4; 558 b := array[6+n] of byte; 559 b[0] = byte 4; 560 b[1] = byte 255; # current mode 561 b[2:] = bint(mask); 562 sys->write(dfd, b, 6); 563 (b, nil) = getreply(n); 564 n = 0; 565 for(i = 0; i<NREG; i++) 566 if(mask&(1<<i)) { 567 reg[i] = intb(b[n:n+4]); 568 n += 4; 569 } 570} 571 572rdi_cpuwrite(reg: array of int, mask: int) 573{ 574 if(debug) 575 print("rdi_cpuwrite(..., 0x%ux)\n", mask); 576 n := 0; 577 for(i := 0; i<32; i++) 578 if(mask&(1<<i)) 579 n += 4; 580 b := array[6+n] of byte; 581 b[0] = byte 5; 582 b[1] = byte 255; # current mode 583 b[2:] = bint(mask); 584 n = 6; 585 for(i = 0; i<32; i++) 586 if(mask&(1<<i)) { 587 b[n:] = bint(reg[i]); 588 n += 4; 589 } 590 sys->write(dfd, b, n); 591 getreply(0); 592} 593 594dump(b: array of byte, n: int) 595{ 596 for(i := 0; i<n; i++) 597 print(" %d: %2.2ux\n", i, int b[i]); 598} 599 600rdi_read(addr: int, b: array of byte, n: int): int 601{ 602 if(debug) 603 print("rdi_read(0x%ux, ..., 0x%ux)\n", addr, n); 604 if(n == 0) 605 return 0; 606 sb := array[9] of byte; 607 sb[0] = byte 2; 608 sb[1:] = bint(addr); 609 sb[5:] = bint(n); 610 sys->write(dfd, sb, 9); 611 (b[0:], nil) = getreply(n); 612 # if error, need to read count of bytes transferred 613 return n; 614} 615 616rdi_write(b: array of byte, addr: int, n: int): int 617{ 618 if(debug) 619 print("rdi_write(..., 0x%ux, 0x%ux)\n", addr, n); 620 if(n == 0) 621 return 0; 622 sb := array[9+n] of byte; 623 sb[0] = byte 3; 624 sb[1:] = bint(addr); 625 sb[5:] = bint(n); 626 sb[9:] = b[:n]; 627 sys->write(dfd, sb, 9); 628 x := 0; 629 while(n) { 630 q := n; 631 if(q > 8192) 632 q = 8192; 633 r := sys->write(dfd, b[x:], q); 634 if(debug) 635 print("rdi_write: r=%d ofs=%d n=%d\n", r, x, n); 636 if(r < 0) 637 raise "fail:hangup"; 638 x += r; 639 n -= r; 640 } 641 getreply(0); 642 return n; 643} 644 645rdi_execute() 646{ 647 if(debug) 648 print("rdi_execute()\n"); 649 sb := array[2] of byte; 650 sb[0] = byte 16r10; 651 sb[1] = byte 0; 652 sys->write(dfd, sb, 2); 653 getreply(0); 654 out(""); 655} 656 657rdi_info(n: int, arg: int) 658{ 659 sb := array[9] of byte; 660 sb[0] = byte 16r12; 661 sb[1:] = bint(n); 662 sb[5:] = bint(arg); 663 sys->write(dfd, sb, 9); 664 getreply(0); 665} 666 667 668regdump() 669{ 670 out(""); 671 reg := array[NREG] of int; 672 # rdi_cpuread(reg, 16rffff|(1<<R_PC)|(1<<R_CPSR)|(1<<R_SPSR)); 673 rdi_cpuread(reg, 16rffff|(1<<R_PC)|(1<<R_CPSR)); 674 for(i := 0; i < 16; i += 4) 675 print(" r%-2d=%8.8ux r%-2d=%8.8ux r%-2d=%8.8ux r%-2d=%8.8ux\n", 676 i, reg[i], i+1, reg[i+1], 677 i+2, reg[i+2], i+3, reg[i+3]); 678 print(" pc=%8.8ux psr=%8.8ux\n", 679 reg[R_PC], reg[R_CPSR]); 680} 681 682printable(b: array of byte): string 683{ 684 s := ""; 685 for(i := 0; i < len b; i++) 686 if(b[i] >= byte ' ' && b[i] <= byte 126) 687 s += string b[i:i+1]; 688 else 689 s += "."; 690 return s; 691} 692 693examine(a: int, n: int) 694{ 695 b := array[4] of byte; 696 for(i := 0; i<n; i++) { 697 rdi_read(a, b, 4); 698 print("0x%8.8ux: 0x%8.8ux \"%s\"\n", a, intb(b), printable(b)); 699 a += 4; 700 } 701} 702 703atoi(s: string): int 704{ 705 b := 10; 706 if(len s < 1) 707 return 0; 708 if(s[0] == '0') { 709 b = 8; 710 s = s[1:]; 711 if(len s < 1) 712 return 0; 713 if(s[0] == 'x' || s[0] == 'X') { 714 b = 16; 715 s = s[1:]; 716 } 717 } 718 n: int; 719 (n, nil) = str->toint(s, b); 720 return n; 721} 722 723regnum(s: string): int 724{ 725 if(len s < 2) 726 return -1; 727 if(s[0] == 'r' && s[1] >= '0' && s[1] <= '9') 728 return atoi(s[1:]); 729 case s { 730 "pc" => return R_PC; 731 "cpsr" or "psr" => return R_CPSR; 732 "spsr" => return R_SPSR; 733 * => return -1; 734 } 735} 736 737cmdhelp() 738{ 739 print(" e <addr> [<count>] - examine memory\n"); 740 print(" d <addr> [<value>...] - deposit values in memory\n"); 741 print(" get <file> <addr> - read file into memory at addr\n"); 742 print(" load <file> - load AIF file and set the PC\n"); 743 print(" r - print all registers\n"); 744 print(" <reg>=<val> - set register value\n"); 745 print(" sb - run builtin sboot (pc=0x40; g)\n"); 746 print(" reset - trigger SA1100 software reset\n"); 747 print(" bps <speed> - change bps rate (SA1100 only)\n"); 748 print(" q - quit\n"); 749} 750 751cmdmode() 752{ 753 b := array[1024] of byte; 754 for(;;) { 755 print("rdp: "); 756 r := sys->read(ifd, b, len b); 757 if(r < 0) 758 raise sprint("fail:%r"); 759 if(r == 0 || (r == 1 && b[0] == byte 4)) 760 break; 761 n: int; 762 a: list of string; 763 (n, a) = sys->tokenize(string b[0:r], " \t\n="); 764 if(n < 1) 765 continue; 766 case hd a { 767 "sb" => 768 sbmode(); 769 rdi_execute(); 770 "q" or "quit" => 771 return; 772 "r" or "reg" => 773 regdump(); 774 "get" or "getfile" or "l" or "load" => 775 { 776 if((hd a)[0] == 'l') 777 aifload(hd tl a, -1); 778 else 779 aifload(hd tl a, atoi(hd tl tl a)); 780 }exception e{ 781 "fail:*" => 782 print("error: %s\n", e[5:]); 783 continue; 784 } 785 "g" or "go" => 786 rdi_execute(); 787 "reset" => 788 sa1100_reset(); 789 "e" => 790 a = tl a; 791 x := atoi(hd a); 792 n = 1; 793 a = tl a; 794 if(a != nil) 795 n = atoi(hd a); 796 examine(x, n); 797 "d" => 798 a = tl a; 799 x := atoi(hd a); 800 for(i := 2; i<n; i++) { 801 a = tl a; 802 rdi_write(bint(atoi(hd a)), x, 4); 803 x += 4; 804 } 805 "info" => 806 a = tl a; 807 rdi_info(16r180, atoi(hd a)); 808 "bps" => 809 sa1100_setbps(atoi(hd tl a)); 810 "help" or "?" => 811 cmdhelp(); 812 * => 813 if((rn := regnum(hd a)) > -1) { 814 reg := array[NREG] of int; 815 reg[rn] = atoi(hd tl a); 816 rdi_cpuwrite(reg, 1<<rn); 817 } else 818 print("?\n"); 819 } 820 } 821} 822 823sbmode() 824{ 825 if(debug) 826 print("sbmode()\n"); 827 reg := array[NREG] of int; 828 reg[R_PC] = 16r40; 829 rdi_cpuwrite(reg, 1<<R_PC); 830} 831 832sbmodeofs(ofs: int) 833{ 834 if(debug) 835 print("sbmode(0x%ux)\n", ofs); 836 reg := array[NREG] of int; 837 reg[0] = ofs; 838 reg[R_PC] = 16r48; 839 rdi_cpuwrite(reg, (1<<0)|(1<<R_PC)); 840} 841 842inp: string = ""; 843 844help: con "(q)uit, (i)nt, (b)reak, !c(r), !(l)ine, !(t)erminal, (s<bps>), (.)cont, (!cmd)\n"; 845 846menu(fi: ref Sys->FD) 847{ 848 w := israw; 849 if(israw) 850 raw(0); 851mloop: for(;;) { 852 out(""); 853 print("rdp> "); 854 b := array[256] of byte; 855 r := sys->read(fi, b, len b); 856 case int b[0] { 857 'q' => 858 killgrp(); 859 exit; 860 'i' => 861 b[0] = byte 16r18; 862 sys->write(dfd, b[0:1], 1); 863 break mloop; 864 'b' => 865 sys->write(cfd, array of byte "k", 1); 866 break mloop; 867 '!' => 868 cmd := string b[1:r-1]; 869 print("!%s\n", cmd); 870 # system(cmd) 871 print("!\n"); 872 break mloop; 873 'l' => 874 w = !w; 875 break mloop; 876 'r' => 877 nocr = !nocr; 878 break mloop; 879 'd' => 880 debug = !debug; 881 break mloop; 882 't' => 883 sys->write(pifd, array[] of { byte 4 }, 1); 884 sdc <-= (array of byte "rdp:tmode", -1); 885 break mloop; 886 '.' => 887 break mloop; 888 's' => 889 bps := atoi(string b[1:r-1]); 890 setbps(bps); 891 * => 892 print(help); 893 continue; 894 } 895 } 896 if(israw != w) 897 raw(w); 898} 899 900 901input() 902{ 903 fi := sys->fildes(0); 904 b := array[1024] of byte; 905iloop: for(;;) { 906 r := sys->read(fi, b, len b); 907 if(r < 0) { 908 print("stdin: %r"); 909 killgrp(); 910 exit; 911 } 912 for(i:=0; i<r; i++) { 913 if(b[i] == byte echar) { 914 menu(fi); 915 continue iloop; 916 } 917 } 918 if(r == 0) { 919 b[0] = byte 4; # ctrl-d 920 r = 1; 921 } 922 if(tmode) 923 sys->write(dfd, b, r); 924 else 925 sys->write(pifd, b, r); 926 } 927} 928 929ccfd: ref Sys->FD; 930israw := 0; 931 932raw(on: int) 933{ 934 if(ccfd == nil) { 935 ccfd = sys->open("/dev/consctl", Sys->OWRITE); 936 if(ccfd == nil) { 937 print("/dev/consctl: %r\n"); 938 return; 939 } 940 } 941 if(on) 942 sys->fprint(ccfd, "rawon"); 943 else 944 sys->fprint(ccfd, "rawoff"); 945 israw = on; 946} 947 948killgrp() 949{ 950 pid := sys->pctl(0, nil); 951 f := "/prog/"+string pid+"/ctl"; 952 fd := sys->open(f, Sys->OWRITE); 953 if(fd == nil) 954 print("%s: %r\n", f); 955 else 956 sys->fprint(fd, "killgrp"); 957} 958 959kill(pid: int) 960{ 961 f := "/prog/"+string pid+"/ctl"; 962 fd := sys->open(f, Sys->OWRITE); 963 if(fd == nil) 964 print("%s: %r\n", f); 965 else 966 sys->fprint(fd, "kill"); 967} 968 969 970# Code for switching to previously unsupported bps rates: 971 972##define UTCR1 0x4 973##define UTCR2 0x8 974##define UTCR3 0xc 975##define UTDR 0x14 976##define UTSR0 0x1c 977##define UTSR1 0x20 978# 979#TEXT _startup(SB), $-4 980# MOVW $0x80000000,R2 981# ORR $0x00050000,R2 982# 983# MOVW $0, R1 984# MOVW R1, UTDR(R2) /* send ack */ 985# 986#wait: 987# MOVW UTSR1(R2), R1 988# TST $1, R1 /* TBY */ 989# BNE wait 990# 991# MOVW $0x90000000,R3 992# ORR $0x00000010,R3 993# MOVW (R4),R1 994# ADD $0x5a000,R1 /* 100 ms */ 995#delay1: 996# MOVW (R3),R1 997# SUB.S $0x5a000, R1 /* 100 ms */ 998# BLO delay1 999# 1000# MOVW UTCR3(R2), R5 /* save utcr3 */ 1001# MOVW $0, R1 1002# MOVW R1, UTCR3(R2) /* disable xmt/rcv */ 1003# 1004# MOVW R0, R1 1005# AND $0xff, R1 1006# MOVW R1, UTCR2(R2) 1007# MOVW R0 >> 8, R1 1008# MOVW R1, UTCR1(R2) 1009# 1010# MOVW $0xff, R1 1011# MOVW R1, UTSR0(R2) /* clear sticky bits */ 1012# 1013# MOVW $3, R1 1014# MOVW R1, UTCR3(R2) /* enable xmt/rcv */ 1015# 1016# MOVW $0, R0 1017#sync: 1018# MOVW R0, UTDR(R2) /* send sync char */ 1019#syncwait: 1020# MOVW UTSR1(R2), R1 1021# TST $1, R1 /* TBY */ 1022# BNE syncwait 1023# TST $2, R1 /* RNE */ 1024# BEQ sync 1025# MOVW UTDR(R2), R0 1026# MOVW R0, UTDR(R2) /* echo rcvd char */ 1027# 1028# MOVW $0xff, R1 1029# MOVW R1, UTSR0(R2) /* clear sticky bits */ 1030# MOVW R5, UTCR3(R2) /* re-enable xmt/rcv and interrupts */ 1031# 1032# WORD $0xef000011 /* exit */ 1033 1034 1035bpscode := array[] of { 1036 16re3a22102, 16re3822805, 16re3a11000, 16re5821014, 1037 16re5921020, 16re3110001, big 16r1afffffc, 16re3a33209, 1038 16re3833010, 16re5941000, 16re2811a5a, 16re5931000, 1039 16re2511a5a, big 16r3afffffc, 16re592500c, 16re3a11000, 1040 16re582100c, 16re1a11000, 16re20110ff, 16re5821008, 1041 16re1a11420, 16re5821004, 16re3a110ff, 16re582101c, 1042 16re3a11003, 16re582100c, 16re3a00000, 16re5820014, 1043 16re5921020, 16re3110001, big 16r1afffffc, 16re3110002, 1044 big 16r0afffff9, 16re5920014, 16re5820014, 16re3a110ff, 1045 16re582101c, 16re582500c, 16ref000011, 1046}; 1047 1048sa1100_setbps(bps: int) 1049{ 1050 print("<sa1100_setbps %d>", bps); 1051 nb := len bpscode*4; 1052 b := array[nb] of byte; 1053 for(i := 0; i < len bpscode; i++) 1054 b[i*4:] = bint(int bpscode[i]); 1055 rdi_write(b, 16r8080, nb); 1056 reg := array[NREG] of int; 1057 d := (3686400/(bps*16))-1; 1058 reg[0] = d; 1059 reg[R_PC] = 16r8080; 1060 rdi_cpuwrite(reg, (1<<0)|(1<<R_PC)); 1061 sb := array[2] of byte; 1062 sb[0] = byte 16r10; 1063 sb[1] = byte 0; 1064 sys->write(dfd, sb, 2); 1065 rb := sreadn(1); 1066 setbps(bps); 1067 do rb = sreadn(1); 1068 while(rb[0] != byte 0); 1069 sb[0] = byte 16rff; 1070 sys->write(dfd, sb, 1); 1071 do rb = sreadn(1); 1072 while(rb[0] != sb[0]); 1073 getreply(0); 1074} 1075 1076aifload(fname: string, adr: int) 1077{ 1078 out(""); 1079 if(adr < 0) 1080 print("<aifload %s>\n", fname); 1081 fd := sys->open(fname, Sys->OREAD); 1082 if(fd == nil) 1083 raise sprint("fail:%s:%r", fname); 1084 d: Sys->Dir; 1085 (nil, d) = sys->fstat(fd); 1086 b := array[int d.length] of byte; 1087 sys->read(fd, b, len b); 1088 if(adr < 0) { 1089 if(len b < 128) 1090 raise sprint("fail:%s:not aif", fname); 1091 tsize := intb(b[20:24]); 1092 dsize := intb(b[24:28]); 1093 bsize := intb(b[32:36]); 1094 tbase := intb(b[40:44]); 1095 dbase := intb(b[52:56]); 1096 print("%ux/%ux: %ux+%ux+%ux\n", tbase, dbase, tsize, dsize, bsize); 1097 rdi_write(b, tbase, tsize+dsize); 1098 reg := array[NREG] of int; 1099 reg[R_PC] = tbase+8; 1100 rdi_cpuwrite(reg, 1<<R_PC); 1101 } else 1102 rdi_write(b, adr, int d.length); 1103} 1104 1105 1106init(nil: ref Draw->Context, argv: list of string) 1107{ 1108 sys = load Sys Sys->PATH; 1109 str = load String String->PATH; 1110 1111 sys->pctl(Sys->NEWPGRP, nil); 1112 1113 port := df_port; 1114 bps := df_bps; 1115 usecmdmode := 0; 1116 ofs := -1; 1117 prog: string = nil; 1118 1119 argv = tl argv; 1120 while(argv != nil) { 1121 a := hd argv; 1122 argv = tl argv; 1123 if(len a >= 2 && a[0] == '-') 1124 case a[1] { 1125 'c' => 1126 usecmdmode = 1; 1127 'O' => 1128 ofs = atoi(a[2:]); 1129 'd' => 1130 debug = 1; 1131 'p' => 1132 port = a[2:]; 1133 's' => 1134 bps = atoi(a[2:]); 1135 'r' => 1136 nocr = 1; 1137 'l' => 1138 raw(1); 1139 'e' => 1140 if(a[2] == '^') 1141 echar = a[3]&16r1f; 1142 else 1143 echar = a[2]; 1144 't' => 1145 tmode = 1; 1146 'h' => 1147 print("usage: rdp [-crdlht] [-e<c>] [-O<ofs>] [-p<port>] [-s<bps>] [prog]\n"); 1148 return; 1149 * => 1150 print("invalid option: %s\n", a); 1151 return; 1152 } 1153 else 1154 prog = a; 1155 } 1156 1157 print("rdp 0.17 (port=%s, bps=%d)\n", port, bps); 1158 dfd = sys->open(port, Sys->ORDWR); 1159 if(dfd == nil) { 1160 sys->print("open %s failed: %r\n", port); 1161 return; 1162 } 1163 cfd = sys->open(port+"ctl", Sys->OWRITE); 1164 if(cfd == nil) 1165 sys->print("warning: open %s failed: %r\n", port+"ctl"); 1166 1167 pfd := array[2] of ref Sys->FD; 1168 sys->pipe(pfd); 1169 ifd = pfd[1]; 1170 pifd = pfd[0]; 1171 (scc, sdc) = (chan of int, chan of (array of byte, int)); 1172 spawn serinp(); 1173 spawn input(); 1174 r := 1; 1175 { 1176 if(tmode) 1177 terminal(); 1178 reset(r); 1179 if(!p_isopen) { 1180 rdi_open(bps); 1181 rdi_info(16r180, (1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)); 1182 } 1183 # print("\n<connection established>\n"); 1184 print("\n<contact has been made>\n"); 1185 if(usecmdmode) { 1186 cmdmode(); 1187 } else { 1188 if(prog != nil) 1189 aifload(prog, -1); 1190 else if(ofs != -1) 1191 sbmodeofs(ofs); 1192 else 1193 sbmode(); 1194 reg := array[NREG] of int; 1195 # rdi_cpuread(reg, (1<<R_PC)|(1<<R_CPSR)); 1196 # print("<execute at %ux; cpsr=%ux>\n", reg[R_PC], reg[R_CPSR]); 1197 rdi_cpuread(reg, (1<<R_PC)); 1198 print("<execute at %ux>\n", reg[R_PC]); 1199 rdi_execute(); 1200 } 1201 rdi_close(); 1202 1203 # Warning: this will make Linux emu crash... 1204 killgrp(); 1205 }exception e{ 1206 "fail:*" => 1207 if(israw) 1208 raw(0); 1209 killgrp(); 1210 raise e; 1211 "rdp:*" => 1212 out(""); 1213 if(debug) 1214 print("<exception: %s>\n", e); 1215 case e { 1216 "rdp:error" => ; 1217 "rdp:tmode" => 1218 tmode = !tmode; 1219 if(tmode) 1220 print("<terminal mode>\n"); 1221 else 1222 print("<rdp mode>\n"); 1223 "rdp:reset" => 1224 r = 0; 1225 * => 1226 r = 1; 1227 } 1228 } 1229} 1230 1231